nathanrumsey.dev
Personal portfolio, resume, and dev diary. The site you're reading now.
Photo by Safar Safarov on Unsplash
When I set out creating my own personal website, two requirements were non-negotiable from the start: static output (no server, CDN-served, deployable for free) and file-based content (adding a blog post or updating a resume entry means editing a text file, not touching UI code). Everything else followed from those constraints.
This site (that you are on now) covers four sections: landing, resume, blog, and projects. All of these sections are driven by YAML and MDX files in the codebase, with no content hardcoded in pages or components. The build validates all content against Zod schemas and fails on any violation, so content errors surface before they can reach production. The blog supports series grouping with per-series pages, client-side tag and sort filtering, and an RSS feed. The projects catalog implements progressive disclosure: a project with frontmatter only gets a catalog card linking to its external URL; a project with MDX body content gets its own detail page.
Technology Stack
- Framework: Astro 6: chosen over Next.js (static export) and Gatsby. Astro treats static output as its primary design goal rather than an opt-in mode. Content Collections give typed, schema-validated file-based content management with no additional tooling. Islands Architecture means zero JavaScript ships to the browser by default; React is added only where interactivity is required.
- Content Layer (
src/content.config.ts): schema-first with Zod. The data contract is declared before any UI is written, and the UI trusts it.getCollection/getEntryfromastro:contentare the single access point for all content; pages never readsrc/content/files directly. This follows the Repository Pattern, with one abstraction layer between the data store and the consumers. - Tailwind CSS v4: CSS-first configuration via
@theme {}blocks inglobal.css. Notailwind.config.ts. Custom color tokens and typography settings live in one place as CSS variables, which means a light theme is a CSS-only addition with no component rewrites. - Deployment: This website is deployed strictly through CI/CD. The deployment flow looks like: (1)
git push main, (2) GitHub Actions, (3) Cloudflare Pages. The entire pipeline is configured in code (wrangler.toml+ the workflow YAML) with no manual dashboard steps after initial project creation.
Deliberate Tradeoffs
- No CMS. At one-author scale, editing text files in an IDE is faster than any CMS workflow. This comes with the cost that ddda non-technical contributor couldn’t update content without a pull request. That’s not a current constraint, and Decap or Keystatic are well-understood extension points if it ever becomes one.
- No site-wide search. Pagefind (static search index) is feasible and well-supported in Astro. The site is small enough that tag filtering covers all discovery needs. This is an explicit deferral, since adding search would require no architectural changes if I choose to introduce this feature.