July 2026
Production notes: jasonsantos.ca
This site replaces one that never launched. The previous version had a three.js starfield, a texture-atlas build pipeline, a CMS sync layer, feature flags, and ninety-six content files — about ninety of which were empty. The machinery outweighed the cargo so badly that the cargo never shipped. That failure is the founding lesson here, so these notes start with the call that shaped everything else: refuse machinery.
The constitution
Before the first line of code, this repository got a CONSTITUTION.md — eight short articles governing voice, truthfulness, simplicity, and legibility. It binds every contributor, including the AI agents that helped build the site and will help maintain it. Agents read it before writing anything, and the rules they might be tempted to bend (no placeholder content, honest statuses, every dependency earning its keep) are exactly the ones written down.
This is the same practice I bring to client teams: when most of the code is written at AI speed, the standards can't live in anyone's head — they have to live in the repo, where the gates can see them. Running my own site any other way would be advice I don't take.
The calls
Boring, mainstream stack. Next.js, Tailwind, markdown files read straight off the filesystem, rendered server-side. What was deliberately not installed matters more: no CMS, no component library, no icon package, no analytics SDK, no animation framework. Each of those is maintenance the last site proved wouldn't happen.
Content behind a published gate. Every page is a markdown file with a published flag, and the content loader — the one piece of code with tests written first — refuses to surface drafts. Case studies go live when they've been reviewed, not when they've been generated.
Production-ready, scaled honestly. For a five-page site that means: CI gates on lint, tests, and build; structured data and an llms.txt so the site is legible to the agents that increasingly read the web on people's behalf; dated freshness signals instead of pretending nothing ages.
What production had to say about it
Shipping is where theory meets the platform, even at this size. The first deploy was rejected — the pinned Next.js version had a known vulnerability, so the honest fix was upgrading, not overriding. The second warned that the build was on a deprecated Node runtime, fixed by pinning the engine. Neither was in the plan. Both are the point: production is the reviewer that never rubber-stamps, and small projects are cheap places to stay fluent in what it demands.
Total infrastructure cost: effectively zero. Time from first commit to deployed: one day. The constitution took longer than the scaffold — which is the correct order.