Will Aitchison: A portfolio as a contact sheet
12.9 → 3.7seconds to the first big picture on a throttled phone, Squarespace to new
I designed and built Will Aitchison's new site as a contact sheet, the direction he picked, with every shoot in one numbered sequence and no picture cropped. It's built for him to run from his own Sanity Studio, with rules that stop a change breaking the layout.
- Designer and developer
- Oct 2026
- Live, before the domain move (opens in a new tab)
12.9 → 3.7seconds to the first big picture on a throttled phone, Squarespace to new
willaitchison.com still shows his old Squarespace site until the domain moves. Screens of the new site are from 24 Oct 2026.
01Problem
Will Aitchison is a fashion and sportswear photographer in Newcastle. His clients include END. Clothing, Stone Island, Nike and Salomon. His brief was short. It mustn't look like a template, the target was "high fashion editorial", there'd be no write-ups, and he wanted "just a nice sequence" rather than project pages. The sections would stay Overview, Still Life and Info.
In the first version, the shoots and their order lived in a file in the code, so every change Will wanted had to go through me. Moving his content into Sanity, with his own Studio, came later. Every service sits on a free tier, and Vercel's free plan is non-commercial, so the live site had to move to Cloudflare. The only pictures to hand were the files his old site served, which are soft on big screens.
02Decisions
Research first, then let him choose from real options
Before any code, I studied about 60 photographers' and fashion sites, how they're built and how they move. I mocked three looks with Will's own photos, editorial, magazine and archive, alongside a run of smaller spikes. Then on the first night I built two directions in one app: an editorial sequence with three openers and a plain start, and a contact sheet with every shoot numbered in one run. Will picked the contact sheet, which grew out of the archive look. On 19 October I removed everything else, and the sheet became the whole site.
Measure the ground against his pictures, then keep it black and white
Will shoots dark. Two thirds of his pictures have a dark edge. I measured them against each candidate ground, and on black whole edges were lost, so a dark ground was out. Pure white was out too: most photographers' sites use it, and they all look alike. The research picked a deeper stone with one red mark, like an editor's grease pencil. I chose a paler stone, #EDECE8, with plain black and white type and no accent. The cost is one picture, which loses its edge on that grey. On the deeper stone, none did.
Never crop, and never blur
The site is there to show Will's work, so every picture keeps the shape he shot it in, and none is cropped. Each shoot is laid out from a recipe on a 12-column grid, and every tile takes its picture's own shape. There are no blur placeholders either, because a blurred preview makes fashion work look cheap. Each box is sized from the picture's width and height, and the picture fades in on the grey once it's decoded, so nothing moves as pictures load.
Own shapes. Shoots 013 to 016, upright and wide pictures side by side. Encode each picture once, and name it by its content
The build turns every original into AVIF, WebP and JPEG at up to eight widths, six from today's files. Each file is named from the original's sha1 and a hash of the settings, so browsers cache it for a year, and changing a setting renames every file. The one clip works the same way, with ffmpeg pinned so it re-encodes byte for byte. Its poster is the clip's first frame, so the switch to motion can't be seen.
One rules file for Will's Studio and the build
Will's Studio lists the order on the site, his shoots, Info, and a Help page that is his written guide. The layout has limits, such as how wide a shoot's row can get, so 17 limits live in one rules file. The Studio checks them as he edits, with messages that say what to do. The build runs them again, because the Studio's checks only run in the Studio. An error stops the build, and the last good site stays up.
Let a publish rebuild the site by itself
Sanity's webhook calls a small Cloudflare Worker. It checks the signature in constant time, refuses anything over five minutes old and starts a GitHub build. The build reuses an R2 cache, so a picture is only encoded once, and deploys to Cloudflare Workers. The relay has 16 tests. In a test on 25 October, a publish was live on the site about two and a half minutes later.
Let Will overrule me
On desktop I'd set his name large along the foot of the first screen, with Info alone in the top right. Will wanted his name at the top and Info beside the Overview and Still life switch. I had reasons for mine, but it's his site, so it changed to what he wanted.
His name moved from the foot of the first screen to the top, and Info joined the switch.
03Result
12.9 → 3.7until the largest picture shows on a throttled phone, old site against new, in seconds
The site went live as a preview on 11 October and moved to Cloudflare on 25 October, with the publish path on. See it live (opens in a new tab). It holds 46 shoots and 69 pictures, one of them a looping clip, with 20 shoots tagged still life. The Studio went live on 20 October with Will's content imported.
On the same phone test, the first screen's pictures fell from 0.99 MB to 0.15 MB. On desktop with no throttling, the largest picture shows in 0.65 seconds, down from 0.94.
It isn't finished. willaitchison.com still points at Squarespace, search engines are kept out until launch, and Will hasn't published anything himself yet.
The viewer 0:12

- Next.js
- TypeScript
- Sanity
- GSAP
- sharp
- ffmpeg
- Cloudflare Workers
- R2
- GitHub Actions