Building · Building this site

Start with almost nothing

Why I started with a tiny static site and made the platform earn each new layer.

TL;DR I could imagine a much larger platform, but kept version one to Astro, Markdown, a static dist/ directory, tests, and a protected deployment. I add structure when a real need makes its value clear.

I can imagine this platform eventually containing writing, research, tools, private modules, APIs, and an iOS app.

If I had treated all of that as version one, I would probably still be designing version one.

The first finish line was much smaller: put a real page on a real domain, build it from a clean repository, test it, and make production wait for my approval.

Astro was a good fit because the site is mostly content. It can turn Markdown into ordinary static HTML without giving me an application server, database, container, login system, or origin machine to maintain. The build produces dist/; Cloudflare serves it.

That was enough to start.

Make the site earn complexity

The repository has grown since then, but most of the additions came after a specific problem appeared.

Repeated pages earned a shared layout. Articles earned typed metadata. A broken nested 404 earned a real 404 test. A skip link that scrolled without moving keyboard focus earned a browser assertion. Preview work earned a separate trust boundary between building unreviewed code and deploying its static artifact.

Even the production domain got one canonical home in site.config.mjs only after the same value began appearing in enough places to become a maintenance problem.

That is the pattern I want to keep:

Add the layer after the problem becomes real, not because I can imagine needing the layer someday.

One of the earliest AI-generated plans did the opposite. It produced a dependency tree containing 12,537 generated files before we had agreed what the project should even be. It was a useful reminder that a machine can create an impressive amount of unnecessary structure very quickly.

Deleting that plan was one of the cheapest architecture decisions in the project.

What the small stack buys me

The current path is easy to describe:

Markdown + Astro source

clean build and checks

verified dist/

Cloudflare preview

human approval

production

The important repository commands are similarly boring:

npm ci
npm run check
npm run build
npm run audit:browser

The lockfile is committed. GitHub Actions installs the recorded dependencies in a clean runner. astro build creates the site, and repository checks inspect the result rather than assuming a successful build means the artifact is correct.

What I did not add

There is still no authentication, database, CMS, payment system, mutable production API, private preview service, or container platform. Some of those may become useful later; today they would mostly create obligations.

A database becomes worthwhile when something needs durable mutable data. Authentication becomes worthwhile when there is something private to protect. Visual-regression infrastructure becomes worthwhile when image diffs offer more signal than noise.

Each unused subsystem adds a dependency, permission boundary, upgrade path, and maintenance surface. Keeping the platform small makes it easier to understand what is actually running and why.

The goal is not to remain static forever. It is to keep the platform legible while adding the next layer when a concrete need makes the tradeoff visible.