01 — Why I built it

A professional site for a combat sports photographer.

Geoff shoots MMA and Muay Thai across the UK and EU. He needed a site that showed his work at full quality, sold prints at checkout, and let him update everything himself between events — without any SaaS subscription, any CMS to learn, and without waiting on me. The whole project became about making the admin feel easier than email.

2 wks

From kickoff to live site, including Stripe + Supabase wiring.

0

CMS subscriptions. Geoff owns the whole stack.

1

Photographer. Everything from upload to payout runs off his dashboard.

Geoff Angel homepage
Home
Services page
Services
Print shop
Shop
02 — How I worked

From client call to live site, step by step.

  1. 01
    Kickoff call + brief

    One call, one page of notes. Pinned down what he sells, how often he updates, what he never wants to touch again.

  2. 02
    Sketched the site on paper

    Home, services, shop, contact. Four pages, no nav tricks. Got to v1 layout before opening Figma.

  3. 03
    Set the visual tone in Figma

    Dark background, gold accent, warm cream highlight — tuned around the way his photography actually looks on screen.

  4. 04
    Built directly in HTML + CSS

    No framework. Every page is a static file — loads instantly, survives any hosting, editable by him.

  5. 05
    Wired Supabase + Stripe for the shop

    Products in Supabase, checkout via Stripe. Zero dashboard I had to build from scratch.

  6. 06
    Purchase notifications + orders dashboard

    Stripe webhook flags new orders the moment payment clears — Geoff gets an email, the sidebar shows a badge, and orders filter by status with a mark-as-delivered action.

  7. 07
    Automatic photo delivery to buyers

    Geoff bulk-uploads the clean web + hi-res files, filenames auto-match to each order line, and the buyer gets an email with a download button. No manual send.

  8. 08
    Taught Geoff the admin, then left

    15-minute walkthrough. He uploads new prints, fulfils orders, and pulls payout reports without me.

The admin panel

Geoff edits every page, price, and photo himself.

The real deliverable wasn't the public site — it was this admin. Seven sections, one for each thing Geoff actually changes: events he's covering, the home page, about, contact, pricing tiers, orders from the shop, and site settings. Every form writes straight to Supabase; every save is live within seconds. No CMS to subscribe to, nothing for him to install.

geoffangelphotography.com/admin
Events

Upcoming coverage

Bellator MMA — London
May 18, 2026
Published
YOKKAO 58 — Manchester
Jun 02, 2026
Draft
Cage Warriors 185
Jun 20, 2026
Published
Editing · Bellator MMA — London
7

Sections Geoff owns: events, home, about, contact, pricing, orders, settings.

1 login

Email + password. Everything behind Supabase auth — no admin URL to hide.

0 deploys

Copy changes go live without redeploying the site.

The automation

One Stripe webhook, both sides done.

When Stripe confirms payment, two things happen at once: the order lands in Geoff's dashboard with a pending badge, and the buyer gets an email with a download button for the photos they just bought. No copy, no paste, no forwarding files.

geoffangelphotography.com/admin/orders
Orders

1 new pending

Action needed
#2026-0420-001
alex@…
£48.00
Pending
#2026-0418-003
sam@…
£32.00
Delivered
#2026-0415-002
jo@…
£12.00
Delivered
Inbox — alex@…
From: info@geoffangelphotography.comToday, 21:04
To: alex@…
Your photos from Bellator MMA — London

Thanks for your order — your photos are ready to download.

IMG_4821.jpg — Hi-Res
Print-quality
£28.00
IMG_4902.jpg — Web
Social / web
£20.00

Links are gated by your order ID. Keep this email to redownload.

< 10s

From Stripe’s webhook firing to Geoff’s inbox and the buyer’s receipt.

0 sends

Clean files are matched to orders by filename — download links generate themselves.

1 email

Receipt, line items, and hi-res + web downloads all live in one message.

03 — Design × engineering

The right stack is the smallest stack.

Shopify would have given him a dashboard to pay for monthly and a theme to fight with. Next.js would have added a build step I had to debug every time his copy changed. Static HTML + Supabase + Stripe gave us the opposite: no subscription fees, no framework fights, no cold starts — a site he owns, deployed via Vercel, charged per transaction rather than per month.

04 — What I learned

Client work taught me to remove things.

When the person using the admin isn't an engineer, every extra option is friction. I cut Geoff's admin down to the three tasks he actually does — upload a print, edit a service, pull a payout — and hid everything else.

No framework is sometimes the right framework. Four pages of HTML rendered faster, stayed simpler, and cost him nothing in runtime fees. The job wasn't to build a product — it was to give one person a tool.

The handover is the deliverable. I shipped the site, then spent as much time writing the 15-minute walkthrough as I did on any single page. The walkthrough is what keeps the site shipped.