Obiz Solutions

Obiz Solutions — this very site

This is the site you’re reading right now. The goal: a place to share systems, solutions, and things I’ve learned, available in English (default) and Vietnamese, fast to load, and close to zero to run.

Architecture

Obiz Solutions deployment architecture: Markdown content → GitHub Actions build → Amazon S3 → CloudFront → visitor's browser

The path from writing a post to a reader seeing it:

  1. Content — posts are Markdown files under src/content/{blog,projects,docs}, each with a matching en/ and vi/ translation.
  2. A git push to main triggers the GitHub Actions workflow.
  3. GitHub Actions installs dependencies, runs astro check then astro build — Astro reads the Content Collections and renders every page to static HTML under dist/.
  4. Actions authenticates to AWS via OIDC (no long-lived access keys stored anywhere), then runs aws s3 sync dist/ s3://bucket --delete to sync the latest build and remove stale files.
  5. CloudFront sits in front of the S3 bucket, serving content over a CDN with HTTPS; Actions calls create-invalidation to clear the cache right after each deploy.
  6. The visitor’s browser gets back static HTML with next to no JavaScript, thanks to Astro’s Islands Architecture — see What is Astro? for more.

Content model

The three collections — blog, projects, docs — share one convention: each entry is a Markdown file under an en/ or vi/ folder, with frontmatter validated by a Zod schema in src/content/config.ts (see What is TypeScript? for why that matters). A wrong type or a missing field fails at astro build time, before it can ever reach production.

Bilingual routing

Astro’s i18n routing makes English the default (root route /), with Vietnamese under a /vi/ prefix. The LanguageSwitcher component computes the equivalent path in the other language from the current URL, and the Header figures out which nav item is active from Astro.url.pathname.

Contact form

The site has no backend, so the contact form on /contact POSTs straight to Web3Forms, a form-relay service that emails each submission through. The access key is injected at build time from a PUBLIC_WEB3FORMS_ACCESS_KEY variable — the GitHub Actions workflow passes it into astro build. If the key is missing, the form isn’t rendered at all and the page falls back to plain contact details (email, LinkedIn, phone). A small progressive-enhancement script submits via fetch and shows an inline status message; with JavaScript disabled the form still works as an ordinary POST. It’s the only client-side JavaScript on the site.

Why this stack