All posts

Engineering

How this portfolio is built

Warm print design, OKLCH color, and a content pipeline that is just TypeScript.

·4 min read

What this site is for

A portfolio is a claim you have to back up.

This site says I build software carefully. That claim is cheap unless the site itself is evidence, so I treat it as a small production project: measured performance, tested accessibility, and a public repository anyone can read. This post is the story of how it is built, including the parts I later ripped out.

The design: warm print

Paper, ink, and one green voice.

The current design borrows its rules from print. The background is a warm paper tone with a faint grain, the text is a near-black ink, and a single forest green carries every accent: links, eyebrows, buttons. Rules are hairlines, corners are square, and there is no dark mode, because a printed page does not have one.

Type does most of the work. Source Serif 4 sets the headings, IBM Plex Sans carries the body, and IBM Plex Mono handles the apparatus: labels, tags, file names. Every color on the site is defined in OKLCH, which gets its own post.

Content is TypeScript

The compiler replaced the content pipeline.

The first version of this blog ran on Velite: posts were MDX files, frontmatter was validated with Zod schemas at build time, and a prebuild step compiled everything into a typed data file. It worked, but it was a second build system to maintain, and every custom component had to pass through an MDX component registry.

The current version deletes all of that. A post is a plain TSX module: a typed metadata object and a React component, collected in a small registry array. The type checker validates the metadata, the bundler compiles the body, and interactive components are ordinary imports.

features/works/content/work-meta.tstypescript
export type WorkMeta = Readonly<{
  title: string;
  subtitle: string;
  slug: string;
  date: string;
  timeline: string;
  role: string;
  techStack: ReadonlyArray<string>;
  liveUrl?: string;
  summary: string;
  outcome: string;
}>;

export type Work = Readonly<{
  meta: WorkMeta;
  body: () => ReactNode;
}>;

The trade

MDX is the right tool when non-developers write content. Here the author is a developer with a compiler open anyway, so the pipeline was pure overhead.

How it ships

Agents write the code. Gates decide.

Agents write most of the code on this site, under the same rules as every repository I run: strict TypeScript, Biome with warnings treated as errors, and a Playwright suite that scans every route against the full WCAG 2.2 AA rule set. The gates fail closed. If a check cannot run, the change does not ship.

Those rules are public and versioned in their own repository, and every project syncs from it. The site you are reading passed them.


Read the source

The repository behind this site is public, gates and all.

View repository