How I Built This Website

A storyboard, a weekend, and a lot of arguing with a language model about spacing.


AI-assisted writing. I built this site with Claude Code over Labor Day weekend 2026, and this post about it was drafted the same way. The opinions, the decisions, and every complaint below are mine.

It started as a storyboard, not a repo

Before a single line of the real site existed, there were two files.

The first was Home_Page_Layout_Options_v1.html: a single static page, about 38 KB, that laid out every screen of the site as flat mockups. No framework, no build step, just markup and a stylesheet already set in Times New Roman. It was the fastest way to argue with myself about proportion. If a layout looked wrong there, it was going to look wrong everywhere.

The second was Personal_Site_Content_Inventory_v1.md, a 2,500-word inventory that settled the things a mockup cannot show: who the site is for, what lives on each page, what the nav says, and the rules the whole thing had to obey. Some of those rules were oddly specific and I am glad they were written down early:

Photos: black 1px border, either 16:9 (landscape) or 9:16 (portrait), with two exceptions. The Home page sketch uses 4:5 instead. The Resume preview uses actual page proportions (8.5:11) since it's standing in for a document, not a photo.

Both files are below, exactly as they were on day one.

Home_Page_Layout_Options_v1.html
Personal_Site_Content_Inventory_v1.md

That paragraph did more work than any amount of design taste would have. Every time a new image showed up over the following two days, there was already an answer for what shape it had to be, and the answer never depended on my mood.

The aesthetic came from those two files and nowhere else: academic journal feel, Times New Roman, white background, minimal but intentional. Not a portfolio template. Not a hero video. A paper.

The mockup's fingerprints are still on the live site, which I find funnier than I should. Five class names went in verbatim and never changed: site-header, lede, blog-post, gallery-trigger, contact-pill.

Then the blanks got filled in

Once the framework was standing, the rest took less than 24 hours. That is the part I want to be honest about, because it sounds like a brag and it is really a statement about where the time actually goes.

The scaffolding is not the hard part anymore. The hard part is having decided, in advance, what the thing is. Every hour after the framework existed was spent on judgment calls that no model could make for me: which essays to publish, how much of the Andrew Chang work could be shown at all, whether a grade of 25/100 on my own powerlifting post was funny or just self-deprecating.

Between prompts, I learned the boring half of running a website. How to actually host one. How to wire a contact form to a transactional email service so it does not just dump into the void. What a DNS record is, in practice rather than in theory. A dozen little things that never come up until you own the domain.

The stack ended up small on purpose:

FrameworkNext.js, App Router
Stylingplain CSS, one stylesheet, ~1,770 lines
ContentMDX files on disk, no CMS
MathKaTeX, loaded only by posts that ask for it
EmailResend
LanguageJavaScript, not TypeScript

Seven runtime dependencies. No component library, no Tailwind, no animation library. The 3D point cloud on the home page tile is drawn by hand onto a 2D canvas, because pulling in a WebGL library to render 600 dots and a wireframe cube would have cost the home page a few hundred kilobytes to do arithmetic I could write myself.

What the model was actually good at

Not writing. It was good at catching things.

Three separate times it found a real bug I would have shipped without noticing. Two live emails were still embedded as clickable link annotations underneath the black redaction bars on my resume PDF, because Google Docs stores link objects separately from the text they sit on. A black rectangle covers pixels, not the objects beneath them. Turning on math support globally quietly ate the dollar amounts in my car-financing post, so "$32,500 MSRP on a 36-month term" rendered as an italic equation. And a stylesheet that hid the site chrome on the theme demo leaked out of that route and left every page after it black.

All three looked completely fine on the surface. That is the pattern worth naming: the failures that survive are the ones that render correctly.

The GitHub thing

Now the complaint.

GitHub flagged my account as spam. For no reason. No commits pushed, no activity to speak of, no explanation given, no rule I can point to that I plausibly broke. Just a new account, an empty repo, and a flag.

The deployment chain for this site is GitHub → Vercel → the domain. That flag is sitting in the middle of it. So the site you are reading was built, in full, in a weekend, and the thing standing between it and the internet is an automated moderation decision that nobody at GitHub has looked at yet.

The appeal is filed. If you are reading this, it either worked, or I uploaded a static .zip to Hostinger.

What I would tell someone doing the same thing

Storyboard first, in whatever medium is fastest for you to throw away. My mockup took an afternoon and saved two days of rebuilding.

Write the rules down. "16:9 or 9:16, 1px black border, these two exceptions" is worth more than a mood board, because it is checkable.

And expect the last 10% to be the whole thing. The framework was a weekend. The copy, the photographs, the crops, the file cleanup, deciding what stays private — that is still going.