jhsu.xyz
In typical designer fashion, I constantly have the urge to redesign my portfolio, but I never get around to it. The last time I updated my website was before agents, so this became the chance to do two things at once: rebuild my portfolio, and find out where Claude held up and where it didn’t. It was one of my first real collaborations with an agent, so I used it to answer one question: where do agents fit into my design process?
Process
How I approached the portfolio redesign
I approached the redesign the way I’d approach a real product feature, which meant doing the parts I usually skip on personal work: who it’s for, its purpose, and its constraints. Most of the early effort went into deciding which qualities I wanted a visitor to actually notice, an idea I took from Josh Puckett’s writing on Interface Craft. I landed on three facets:
- Intentional: every animation, interaction and styling property should feel fine-tuned.
- Modular: the same body of work should take a different shape on each page and still feel cohesive.
- Playful: the site should feel physical to use and carry some of my personality, with some restraint.
Then I gathered references and built a moodboard for the direction I wanted. All of it went to Claude as a single brief, along with the facets, the constraints, and enough about me and the work that what came back was specific to me.
I first explored layouts and site structure in Figma, but I quickly felt that Claude’s output through the Figma MCP wasn’t good enough to design against, and I spent longer working around that than I should have before switching. Moving to Paper fixed it. The artifacts improved immediately, and once implementation started, Claude turned out to be better at building from a Paper file than from a Figma one. Most of my design work happens in Paper now.
Outcome
Obsessing over details
I wanted the portfolio to feel intentionally crafted and still be easy to read. My main concern was striking a balance between the two. Anything opinionated had to hold up on every page without pulling attention off the work itself, so I kept it to a handful of details rather than a few big gestures. Three of those took most of the time.
1. The ruler
I wanted the portfolio to play into the drafting aesthetic of real-world instruments. Cutting mats. Rulers. Rough sketches. The subtle grid lines on every page serve as visual references to accentuate content alignment. I wanted that structure to be reactive so that it didn’t feel like a static SVG.
2. The mosaic
The mosaic on the home page renders differently on every visit. I defined a set of shapes and had them placed randomly across a grid of cells. This approach got me pretty close to the result I wanted, but the composition still felt “off.” The shapes felt too cramped. For the composition to hold together, I had to introduce some logic for how shapes were grouped.
I cut out shapes that felt visually unaligned with the rest of the composition. I also introduced weighting that determined how shapes were placed alongside each other. This created a better-balanced composition of curved and straight-edged shapes.
3. The cutting mat
The work deck intro card was the result of an experiment where I replicated a cutting mat. It started off pretty basic, but that felt too generic, like something an agent would produce. The protractor added to the drafting aesthetic of the card, and provided some curvature to an otherwise edge-heavy piece. Then I added assets from my previous work to make it feel personalized.
The solid fill coloring on the cutting mat felt out of place and unnatural. I landed on a halftone CMYK shader that gave the card some texture. I liked the state of the card, but felt like there was still something missing: the roughness that comes from sketching. That led to rough.js, a library I found that emulates the feel of drawing by hand.
Reflection
What I learned
The split between what I handed over and what I kept shifted a lot during this project. Here’s where it landed.
1. Working from a reference
Claude works great when there’s already something to work from. I gave it the Paper wireframes and the first version came back close to them. It’s quick, too. Getting from an idea to a wireframe or a working prototype got cheap, so I could push a direction far enough to judge it rather than talking myself out of it first.
2. Precision without judgment
It’s good at anything with a right answer. Precise offsets, consistent spacing, the same value applied everywhere it appears. It can’t tell you whether the result feels right, and that turns out to be most of the work.
Animation is the clearest case. Claude implements the timing you ask for accurately, as long as you use the right words for what you want. It just has no opinion on whether that timing is the right one. Placement is the same. It’ll put an element exactly where I say, and I still have to nudge it around before it sits properly.
When I let it make those calls itself, the work came back generic, with obvious tells that nobody had chosen anything.
3. Memory between sessions
Some of what I learned through this project had nothing to do with design. One of the first hurdles I encountered was managing context for Claude. On a project this long, I found myself explaining decisions I’d already made, and reopening ones I thought were closed. I dedicated effort to configuring proper workflows for Claude Code. Writing decisions down where the next session reads them first. Clearing context before it fills up with things that don’t apply anymore. I built a small skill, /save, that closes a session by committing the work and writing down what happened.
4. Skills as a second pass
Partway through I started running other people’s skills over my own interaction code, Emil Kowalski’s and Interface Craft’s. They caught things I didn’t know to look for, and a few I’d have noticed eventually and let slide. I treated it like a review, so it only helped once I had something finished to look at.
run emil-design-eng over the v12 motion and interaction code
Ran skill /emil-design-eng
Most of it holds up. The deck’s damped scroll, the card spring-return, the page entrance and the reduced-motion handling are all on-principle. The real findings cluster in the tooltip I just built and in the theme toggle.
Five changes worth making:
.tooltip-content animates on every open
[data-state='instant-open'] { animation: none }
animation: tooltip-in 130ms ease
animation: tooltip-in 130ms var(--ease-out)
ThemeToggle has no :active state
active:scale-95 + transition-[color,transform]
local SPRING = cubic-bezier(0.34, 1.56, 0.64, 1)
var(--ease-spring)
tilt fires on any pointerType
gate to e.pointerType === 'mouse'
anything you looked at and decided to leave
Two, and I want them on the record rather than quietly skipped.
- Tooltip slides directionally, rather than scaling from its origin. The principle behind origin-aware scaling is spatial connection to the trigger, and a 3px translate toward it already achieves that. Deliberate, so it stays.
- The card animates `box-shadow`, a paint rather than a transform. A real cost, but subtle and only while tracking, and rewriting it to a pseudo-element opacity fade is more churn than the frames are worth today. Noted, not fixed.
apply the five, leave the two
Fold SongShelf’s local spring into var(--ease-spring), or leave the duplicate curve?
Gate the tilt to fine pointers, or leave touch as-is?
Edited globals.css+6-2
Edited ThemeToggle.tsx+1-1
Edited SongShelf.tsx+5-2
Built after the fixes
Clean. The five are in, and the two I left are written down where they will be found again rather than rediscovered.
So where do agents fit? Anywhere there’s already something to follow. Claude built more of this site than I expected it to, and it moved fastest whenever I’d already decided what I wanted. A lot of the design still needed my judgment: whether a timing feels right, whether a composition is balanced, whether something reads as considered or just generated. That stayed mine.