Why this portfolio is static

The design decisions behind a statically generated portfolio with typed content, build-time search and no runtime service.

This portfolio is built as a static site. The content lives in Git, the pages are generated during the build, and the deployed site does not need a database, runtime server, or CMS.

That choice is deliberate. A portfolio should be easy to inspect, easy to deploy, and difficult to break accidentally. A small operational surface also leaves more time for the work the site is meant to explain.

Content is part of the repository

Projects and writing are Markdown collections with typed frontmatter. Astro and Zod validate the shape of every entry before the site is generated. Dates, slugs, reading time, table of contents data, related entries, and archive ordering are derived from the source content rather than maintained by hand.

This keeps content changes reviewable. A new project is a file in a pull request, not a hidden record in an external system. The same commit contains the copy, metadata, and any code needed to render it.

Search is generated at build time

The site uses Pagefind to build its search index after Astro has generated the HTML. The browser only loads the search runtime when the visitor opens the search dialog. There is no search API to operate and no request to a separate service at runtime.

The tradeoff is simple: publishing content requires a new build. For a personal site, that is a useful constraint. The output stays connected to the source commit, and a deployment can be reproduced from the repository.

Verification is part of the build

The production command does more than generate pages. It also builds the search index, verifies Content Security Policy hashes, and checks internal links. Unit tests cover the pure content and publication rules, while browser tests exercise navigation, accessibility, search, responsive layout, and generated pages.

These checks are intentionally close to the deployment path. A broken link or a content rule that passes locally but fails in production should be caught before the static files are uploaded.

The practical boundary

Static generation is not the right answer for every product. An application with frequent writes, user accounts, or real-time state needs a runtime system. This portfolio has none of those requirements, so a static boundary keeps the system small while still supporting structured content, search, metadata, and a clear publishing workflow.

The result is a site that treats content, code, and deployment as one reviewable artifact. That is the same kind of boundary I value when designing backend services: explicit inputs, predictable outputs, and a failure mode that is easy to understand.