The bottleneck was never building
I rebuilt my portfolio with AI, like everyone else did. But building it was the easy part. The hard part was deciding what to leave out.
My showcase page shows my projects as cards on a timeline. Between two of the cards, there's one line of text, floating by itself:
“The bottleneck was never building. It was deciding what to build.”
I wrote that line about my work as a designer. It turned out to be about this site too.
Everyone built it
The pitch right now goes like this. The portfolio used to be a stack of case studies. Now it's a product. Shipping is the proof. Here are twenty designers who vibe-coded their sites, every link works, go click them.
I agree with most of it, and I'm not a neutral party. I just rebuilt this site with Claude Code, and it's a Next.js app with a 3D timeline, a fake shell, and a command palette. I'm the person that argument is about.
But it stops one step short. When building stops being the constraint, “I built it” stops being the interesting claim. Everyone built it. The models are good and the weekend is long. What's left, once the cost of making things falls to roughly zero, is the part that was always the actual work: deciding what not to make. What to cut. What to hide.
So this isn't a post about what I shipped. It's about two things I hid, what they cost, and the bug that fell out of hiding one of them.
The terminal you have to find
There's a CLI on the homepage. It boots for 4.8 seconds behind a progress bar, types an ASCII wordmark into itself, and answers to about, projects, stack, contact, theme, reboot. Type coffee and it does something. Type sudo and it declines.
It's the densest thing on the site, and it isn't on the page. You get a >_in the corner. That's it.
Every instinct from ten years of product work says this is wrong. Discoverability is a virtue. Don't bury the good part. I buried the good part.
The reason is that a terminal you're handed is a widget, and a terminal you find is a room. The whole premise is that it rewards poking, and you can't reward poking if you've already given away the answer. So it pulses once on a first visit, and after that you're on your own.
It's a trade, and the cost is real. Plenty of people will never type anything, and plenty is most of them. What I get back is that the ones who do find it get something better than a feature tour. I'm not certain it's the right call. I'm certain it's a call, and I'd rather own it than pretend it tested well.
Scroll to run
The showcase is a 3D timeline: ten glass cards on a 2016 to 2026 axis, side projects riding above the line, company work below. It's the biggest thing I built.
There's no button to it.
Instead, at the bottom of the homepage, there's a band styled as a terminal prompt with the command already sitting in it:
bryan@garage ~ % showcase --3d-timeline [░░░░░░░░░░░░░░░░░░░░░░░░] scroll to run
When you hit the bottom of the document, your extra scroll starts filling the bar. 1,200 pixels of wheel delta to fill 24 cells. The label goes from scroll to run to loading timeline… 47% to entering /showcase, a dithered pixel field grows up from the bottom edge like phosphor warming, and at 100% a WebGL sweep takes you there.
Stop scrolling and it drains back down in under a second, so a stray tick never leaves it half lit.
The idea is small: the site's whole identity is a command line, so the way into its centerpiece should be a command, and scrolling should be running it. Not a button that looks like a terminal. The scroll is the input.
Underneath, it's a plain <a href="/showcase"> with an aria-label, and the command text ships rendered from the server. Click it, tap it, tab to it and press Enter, arrive with JavaScript off: all fine. The gate is decoration on top of a link, which is the only reason I let myself build it.
The entrance that silenced the room
Here's the thing nobody tells you about deciding the way into your site is a scroll.
Browsers won't start audio from a scroll. wheel is not a user activation gesture, by design, because that's exactly the loophole that would let every page on the internet start talking at you. Clicks count. Keys count. Scrolling does not.
And the timeline has sound. Not from files: every cue is synthesized live in Web Audio. Each card that passes the center plays a soft bell, and the notes walk up a C major pentatonic, C5, D5, E5, G5, A5, so a fast scroll reads as a little melody instead of the same beep ten times. The whole bus runs through a 5.2 kHz lowpass so the blips feel felt rather than shrill.
So I'd designed an entrance that structurally guaranteed the thing behind it would be silent. The two best decisions on the site were quietly incompatible. I didn't find out from a bug report. I found out because it was silent and I couldn't figure out why.
The fix has three parts, and only one of them is clever.
The AudioContext is a module-level singleton, so a context started on the homepage survives the client-side navigation into the showcase. Then the homepage listens for the first real gesture anywhere on it, a click, a keypress, a touch, and quietly starts the context at zero volume. Nothing makes a sound on the homepage. It's just warm, so a scroll-only ride lands on a page whose audio is already running.
The earlier version had a bug worth naming, because it's the kind you only get by shipping. It armed itself, saw the first wheel event, decided that counted as its one shot, and removed its own listeners. The context never started. The page stayed silent for the entire session, even if you clicked twenty times afterward. The fix was to stop trusting the attempt and keep retrying until the context actually reports running.
The third part isn't code at all. The speaker icon used to say sound was on, because I'd set a flag that said sound was on. Meanwhile the page was factually silent. Now the icon mirrors whether the context is genuinely running, and while it's still locked, the hint line says a click is what starts it.
That's the one I keep thinking about. The bug was in the browser policy. The failure was that my interface was willing to lie about its own state, and I wrote the flag that let it. AI wrote most of the audio graph. AI did not notice the speaker was lying, because AI didn't know what the icon was for. That's not a knock on the model. It's just where the job actually is now.
The gamble, named
I know the counterargument, because it's mine too.
A recruiter gives a portfolio thirty seconds. My site hides its CLI behind a >_, its centerpiece behind an overscroll, and its contact form inside a command palette. Somebody is going to land here, scroll once, see a nice timeline and some cards, and leave with no idea any of it exists. That happens. I can't tell you it doesn't.
What I can tell you is that it's a choice and not an accident, that everything hidden has a keyboard path and a real link under it, and that I'd rather be specifically interesting to a few people than uniformly legible to everyone. The companies everyone lists in these posts, the ones that say they want people who ship: they can also tell the difference between a site that's hiding things and a site that has nothing to hide.
But I'm not going to pretend the gamble isn't a gamble.
What you left out
Build the thing, obviously. It costs a weekend now. That's the good news, and it's also the whole problem, because it means the thing itself has stopped being evidence of much.
The interesting part is what you did after it worked. What you took out. What you refused to explain. Where you decided a visitor should have to do a little work, and what you're prepared to lose for it.
The bottleneck was never building. It was deciding what to build. And then, harder, deciding what to leave out.