July 1, 2026 · 3 min read

My portfolio had no client, so I set its limits first

Without a client or a deadline, I kept reopening decisions. The accent, the navigation and the hero line each stayed open to one more revision, because nobody outside my own head could say they were finished.

So I gave the project the limits a client engagement would have had. I chose a visual baseline, set a scope ceiling, settled each open decision before any code was written, and made two risks block the launch. After that, every review had one question I could answer: was this version ready to ship?

Who decided what

AI wrote most of the code on this site. I set the direction, wrote the constraints each build had to meet, reviewed the output against them and sent generic drafts back. The accent value, the type rungs and every deferral below were decisions I made and can defend. I am accountable for what shipped, including the parts a model typed.

A baseline instead of a blank page

I started from the portfolios I kept returning to: Yan Wang, Perry Wang, Julius, Dimitri Knight and Kyle Conrad. Kyle Conrad's fluid type system influenced this site's typography most directly.

A baseline turned taste into something I could check. Every size on the site scales from one fluid unit, --base: clamp(4px, 0.5vw, 16px), and every departure from the baseline is logged with the original value, mine, and the reason. A change without a reason in that log is a change I have not decided yet.

The live style guide documents the type scale, color tokens and spacing system, read straight from globals.css.
Style guide page showing the fluid type scale, with Lyon Display headings and their clamp values

The scope ceiling

The first call was to settle the visible identity now and defer structural experiments. That changed every later question from "what could this be?" to "what does this version need?"

Within that ceiling, I settled the open decisions one at a time, each with a recommendation to react to:

  • Accent. A deep cobalt, #1E40AF, chosen to read as deliberate rather than default blue.
  • Mark. My photo sits in the hero headline where a logo would go. A personal site's strongest identity signal is a face.
  • Hero line. It names what connects my work, delivery systems and the interfaces they produce, instead of a generic promise about delightful experiences.
  • Footer. One sentence, written before layout and quoted in the build plan: the site is the product, and the footer stays subordinate to it.

The consequential one was navigation. The inherited header scrolled away after the first screen and reappeared only in the footer. I replaced it with a persistent sticky bar, against my own long-standing preference for navs that hide on scroll. On a site where visitors move between studies, essays and the about page, reliable navigation was worth more than minimal chrome.

Two risks that blocked launch

Some decisions were about taste, and some were about whether the site was safe to publish. I kept those questions separate, so nothing was dropped out of caution and nothing risky shipped because I liked it.

Private data. The site began inside a workspace that also holds family and finance records. Before Vercel ever saw it, I moved the site into its own private repository, so the deploy pipeline had no path to that data.

Font licensing. The display faces are commercial. I shipped first to an unlisted *.vercel.app preview and did not touch the domain until web licensing was confirmed. Had the answer been no, the site would have waited at that preview URL.

Some protections went into code instead of memory. Image handling runs as a script before every deploy, so no one has to remember not to double-compress a screenshot. The contact form is a licensed component from a commercial library I own, reskinned to the site's type, color and spacing. Its layout and validation were already solved; my work was making it belong to this system.

What waited

Dark mode waited. Colors live in CSS variables, which keeps a second theme possible, but maintaining two themes was not part of this version. Structural experiments waited too, and they have since arrived one logged change at a time.

What shipped in each release, in plain language, is on the changelog. The case studies show client and team work; this project shows how I finish work that nobody else will call finished.

Related Writing