The work, by what it proves rather than by when it happened.
A design system, then payment infrastructure, then the department I ran, then the side research. They're not the same size and aren't billed as though they are.
Co-founder & Design Systems Engineer Feb 2024 to now
An accessibility-gated design system and a navigable ATS product, built on my own across two full rebuilds. The best thing I've made, and the only reason I can say so is that something other than me checks it.
117Components
26ATS Workflows
174Routes Audited
0Axe Violations
117 components · 26 ATS workflows · 174 routes audited · 1,564 tests · 360 contrast pairings per run · 0 axe violations, both themes · three-tier W3C DTCG tokens in OKLCH holding 280px to 5K · React Aria
Full Stack Developer, contract Sept 2025 to Apr 2026
Hired to make an FCA-regulated collections site accessible, then asked to take on the payment migration instead. Least fashionable work I've done and easily the most useful: when it breaks it isn't an ugly page, it's somebody already in arrears who can't get the payment through.
80%More mobile payments
70%Of those on Apple Pay
2,046Lines of C# written
0Failed cutovers
Four screens to one · 80% more mobile payments, 70% Apple Pay · Fiserv end to end · legacy ASP.NET onto a typed Next.js stack · 0 failed cutovers
Head of Web
Paul McFadden Wealth Dec 2022 to Jan 2024
Owning a revenue number is different from contributing to one. It means the funnel breaking is your problem at nine on a Sunday, and every argument about page speed, form length and one more tracking script lands on your desk. Most technical decisions turn out to be staffing decisions in a costume.
3Hired
7Co-managed
60%Open rates up
27%Cold replies up
Personally accountable for £10m+ of web revenue · hired three, co-managed seven · open rates up 60%, cold-outreach replies up 27%
Print's had baseline grids since metal type; the web has never had one. Nobody asked me for it and I built it anyway, which tells you most of what you need to know. The six years before it are why the build half is any good. One shot, it goes on a press, and a wrong bleed arrives as a room full of boxes.
228Of 239, seated
0Sizes a fit has to change
76msTo fit, with no browser
4th of 9Coherence vs design systems
Quoin v1.26.0 · fits the design before the CSS exists · 228 of 239 seated on this page, 0 sizes changed, 76ms with no browser, 26 kB, no dependencies, MIT · NOVAVAPES, graphic designer to brand lead · DesignBuddy UK, 50+ clients since 2017
Seven principles, each linked on /work to where it has already been done
A standard is a gate, not a statement
You get the number without asking twice
Own the number, not a share of it
Hold both halves
Finish what other people left
Release like it's going to press
Bring people on, and write it down
Every other number here is checked by something. This bit isn't. It's the only part of the site that's an opinion rather than a measurement, so it gets to have an edge. Wrote it angry. Took the swearing out on the read-back and then put all of it straight back in.
Sheet03 / 09 · The problem
Claim typeArgument · nothing here is testable
Measure62ch · two columns above 52rem
Groundoklch(26% 0.065 40) · the same umber, one tier down
The thing I keep being hired to fix
We went from 200kbps to 2000mbps, everything got fancier, usability got cluttered and overcomplicated.
Three decades on from documents anybody could open, it takes two megabytes of JavaScript to show you a paragraph that was already text. The scroll gets hijacked so a logo can rotate on the way past. Zoom gets switched off because it breaks the layout. There's a functioning industry selling a widget that makes an inaccessible site compliant without making it one bit easier to read.
Machines got faster every single year of that, and the whole gain went on decoration. Almost none of it is malicious, because checking who got locked out is boring and the cool shit is what gets shared. But the outcome stops caring what you meant. Somebody can't read the page, the reason is a contrast ratio that looked nicer, and your information is now behind a door with you holding the key.
Theme parks are made for people, but not disabled people. That is slowly changing. The web is going the other way, and it has better tools and more bandwidth than it has ever had.
Nobody sets out to lock people out. It just never gets checked, and unchecked always drifts one way.
The British Dyslexia Association asks for dark text on a light background rather than black on pure white, because white dazzles. WCAG pushes the contrast up, the dyslexia guidance pushes it back down, the maximum turns out not to be the target, and somebody has to sit and work out which reader they are serving. That is a person's job, not a linter's. The ground on this page is not white.
Sheet05 / 09 · The method
Gatenpm run verify · fails the build, not a report
Checked byEvery deploy, before it ships, not by me
Last runNo receipt in this build
Found9 real defects in my own AAA claim
How I'd change what you ship
A statement is not a standard.
A standard you can only assert is a standard you haven't met yet, and you won't know which until something checks.
Nearly every company shipping an inaccessible site has an accessibility statement somewhere on it. Almost none have a test that could fail. A statement costs an afternoon. A gate costs you the argument, in public, the day it goes red, which is exactly why it works and exactly why nobody wants to write it.
Writing the gate is the work. I put one in front of my own AAA claim and it took the claim straight off me: nine real defects nothing else had caught, including an unnamed dialog sitting behind every sheet in the system. That is the version of this you actually want on your team.
Shipped as gates, not intentions: 360 contrast pairings on every run · 1,564 tests across 174 routes · 0 axe violations in both themes · AA everywhere, AAA on thirteen criteria, three exceptions published rather than quietly dropped · a colour-literal ratchet that only moves down · a check on the delivered CSS rather than the source, because the build was quietly flattening OKLCH to hex and nothing said a word.
This is the bit that makes people go quiet in interviews. Not the number, the fact that it can fail.
Sheet06 / 09 · The commercial case
Measured+80% mobile payments · 70% Apple Pay
SourceClient analytics · their numbers, not mine
ConstraintFCA-regulated · PCI-DSS · live throughout
Why this pays for itself
The accessibility fix and the money fix keep turning out to be the same fix.
A person in arrears, on a phone, being asked to type a sixteen digit card number into a debt collection form has several good reasons to give up. Removing those reasons is an accessibility job and a conversion job at the same time. Mobile payments went up 80%, and 70% of them came through Apple Pay.
That flow had four screens because those two jobs belonged to two different people. Almost every expensive problem I get called into lives in that gap. Design says it's an engineering problem, engineering says it's a design one, and it sits there for a year with nobody's name against it. I can hold both halves, which is the only reason I can see it at all.
SagePay to Fiserv, finished solo after roughly half a dozen developers had left it short of testing: tokenisation, digital wallets, HMAC-SHA256, 3D Secure, store ID routing, 2,046 lines of C# I hadn't written since 2016, against a PCI-DSS estate of 97+ stored procedures that never stopped taking live money. Zero failed cutovers.
Nobody's posting a Fiserv gateway on Dribbble with a nice gradient behind it. It still moved more money than anything I've made.
Sheet07 / 09 · How I got here
OrderDeveloper first, design in the middle
SkillsListed only if shipped, no bars
Sourcesrc/data/about.ts · src/data/skills.ts
How I got here
You can't see a foundation. You only ever see what happens when there wasn't one.
I started building for the web at fourteen and had the degree by nineteen. Then I couldn't get a job doing it. A few years of freelance and whatever else paid, by the end of which I'd had enough of the industry entirely, so I retrained as a graphic designer and did that properly for six years instead. I came back to code in 2020 and spent the guts of a year rebuilding everything I'd let go rusty. So this isn't a designer who learned to build, it's the other way round, and the six years in the middle are the whole point. I make shit look good, then I build it.
Five people in my family and I'm the only one who isn't dyslexic. Mum, dad, both my sisters. That's why I check the contrast rather than claim it.
Vercel ·Preview and production environments ·Cutover and rollback runbooks ·Zero-downtime migration ·Environment and secret management ·IIS / Windows Server (legacy estates)
WCAG 2.2 (AA gated, AAA where it holds) ·axe-core / jest-axe ·Playwright ·Vitest / Jest ·Testing Library ·Lighthouse CI ·Pa11y ·Chromatic
Research & Documentation
Technical documentation ·Design system specification ·Competitive and standards research ·Accessibility auditing ·Handover and onboarding packs ·Architecture decision records
Design & Creative
UI/UX Design ·Adobe Creative Suite ·Brand Identity ·Prototyping ·Art Direction ·Typography
AI & Agent Systems The speed is real and so is the rubbish, and the difference between them is entirely whether somebody read the thing before it went out. I run agent sessions the way I run builds. Tight brief, obvious done-state, nothing ships that I haven't read end to end. The skills and MCP servers and rules sitting in this repo are there because without them the work wanders off and comes back sounding like everybody else. Which is the one thing I'm not interested in being.
Best thing about years in print? You learn quickly that design isn't pixels. It's whether somebody actually lifts the thing off a shelf in a shop. No hover state is saving you there. Everything I build still starts with that question.
Sheet08 / 09 · Open non-conformances
Count43 · ratchet, down only
First count184 on 5 September, 130 of them in a stylesheet nobody was serving
Fixed since11, the last on 15 September
StatusOpen, published, not deleted
Also2 level A failures, live for months
The bit most people delete before you arrive
43 things on this site are still wrong.
43 colour literals bypass my own theme. I could have quietly fixed them before you got here. It's on the page because a portfolio that only shows the bits that worked is a showreel, and because if you're hiring at this level the useful question isn't whether somebody has open defects, it's whether they can tell you the number without being asked twice.
I also claimed AAA for eight months while the test that checks it had never once loaded. Eight typefaces gave me the same number and I read it as consistency; every measurement was against a font that had never loaded. A control that can't fail will agree with you three times in a row and sound authoritative doing it.
Ratchet: down only, one commit at a time, in public. A full audit of this build found fourteen more, nine fixed the same day, and two were level A failures that had been live for months because the suite only ever ran at one screen width. All of it is written up rather than deleted.
Every honest number on here started out as a worse one I'd talked myself out of publishing.
Sheet09 / 09 · Enquiries
ReplyInside the hour, UK working hours, by a person
Open toLead, principal, head of engineering or first technical leader · contract or permanent
Not on this sitePreloaders · hamburger menus · carousels
Enquiries
Tell me what's breaking.
If you already know which detail it is, say so in the first line and we'll skip the discovery call. I read every email that comes in. If it's a template I'll know, because you all use the same three openers.