One palette, both themes
Every colour comes from one palette: 32 groups, with 454 values for each theme. Each part reads its colours by name, so a part can change theme on its own. Tap one in the miniature.
- The top
- The field
- Featured work
- The footer
The site you're on, in two builds: the one before, and v3, which replaced it on 2 November 2026. Drag across a page to go from one to the other.


HomeThree job titles over a 3D box became the statement “Software, end to end.” Its figures now mix experience, projects and school.
On 28 October alone, 23 commits rebuilt the works index, Birdie Golf and WhatToWear.
The first portfolio.
From the first commit on 25 February: the slanted-stripe hero, a preloader, a works directory, About and Contact, Vercel with an asset CDN, and the contact form writing to Supabase.
A 3D box joined the hero; case-study pages moved onto reusable templates.
The contact form, the database and the theme hardened, with the first automated tests.
The rebuild, page by page: 79 commits.
230 commits. The two snapshot commits of 3 June are left out: they stored files, not site work. Subjects are quoted from v3 only; earlier ones were short tags.
7 pages and an API route, plus the case studies337 JavaScript files65 automated tests230 commits
Every colour comes from one palette: 32 groups, with 454 values for each theme. Each part reads its colours by name, so a part can change theme on its own. Tap one in the miniature.
The words sit in their own file beside each part. Change them here and the miniature follows, while its layout stays put.
With Reduce Motion on, every moving part on the site rests in a still state that reads the same. The tool pile settles; the screens stop.
A case study opens on its real pages, which pass under numbered pins as you scroll. Then its chapters run beside a screen that shows each one's picture. Birdie Golf was the first on it.
The bar at the bottom of the window searches pages, projects, tools and actions.
65 automated tests on Node's built-in runner. The first, on 3 October, covered the contact form's checks, the database's row security and the theme surviving blocked storage.
Five checks stand between the form and the database. Pick a sender to see where it stops.
You, from ContactSending…
A script that skips the browser meets the same checks on the server.
While a message is on its way, what you type is kept, and the form says whether it arrived or failed.
An audit of the old page.
Live prototypes in different directions. I pick one or mix them.
Every line of copy approved in a copy sheet.
Every fact checked against the project's own repo or files.
The finished page checked on the production build at desktop, laptop, tablet and phone widths, in both themes and with Reduce Motion, before each commit.

Next.js 16, React 19, Tailwind 4 and plain JavaScript, with a contact form that writes to Supabase.
Built with Claude Code and Codex, directed and reviewed by me.