kaichicken

2026-07-03 · 2 min read

How this site works

This site's entire content system is two TypeScript files. That is not a temporary hack on the way to a real setup — it is the setup, and this note explains why.

Content as data

Every project and every post is a typed object in a content/ directory. Publishing means editing an array:

// content/projects.ts
export const projects: Project[] = [
  {
    slug: "research-workbench",
    name: "AI research workbench",
    status: "egg", // "hatched" | "incubating" | "egg"
    tags: ["llm", "agents"],
    description: "An agent that runs the boring half of research…",
  },
];

The type checker is the editor. Forget a field, misspell a status, break a slug — the site refuses to build. For a one-person site this beats any CMS: the whole editing workflow is a text editor and git, which are the two tools I already live in. No admin panel to secure, no database to migrate, no drafts rotting in a web UI I never open.

Everything is static

Next.js prerenders every page at build time — including the sitemap, the robots file, and each note — and the result is plain files on a CDN. At runtime the server does nothing but hand them out. Fast everywhere, free to host, and nothing to patch at 2 a.m.

Route (app)
┌ ○ /
├ ○ /about
├ ○ /projects
├ ● /notes/[slug]
└ ○ /sitemap.xml

○ static  ● prerendered from content/

What's deliberately missing

No CMS, no MDX, no comments, no analytics, no newsletter popup. Each of those gets added the day the pain is real, not the day a tutorial suggests it. The upgrade paths are written down in the repo's README, so adding one later is a decision, not a research project.

Total runtime dependencies: three — React, Next.js, and Tailwind. The most complex asset on the site is the chicken, and it's six circles and a triangle.

← all notes