Skip to main content
WEB

The site you are reading, shipped by pushing to main

A design system in CSS variables, visual baselines at five widths, and a deploy that has to prove itself healthy.

THE PROBLEM

What was in the way

A freelance site is the first work sample a client ever sees, and most of them are a bought template with a name swapped in. Nothing about them tells you whether the person can build and run software.

The second problem is upkeep. A site deployed by hand drifts away from what is in the repo, and a layout change quietly breaks a page nobody happens to open that week.

THE APPROACH

How it was built

The design system was written down before the first component. Palette, type scale and spacing exist once as CSS variables that every component reads, so the document and the build cannot drift apart. They are the same values.

A marketing site normally ships with no tests. This one has Playwright across every route, the API handlers and the accessibility basics, plus full-length screenshots at five widths with the baselines committed. Deploy is a push to main, and a container that never reports healthy fails the deploy instead of replacing a working one.

Tokens to live container
Tokens to live container
HIGHLIGHTS

How it works

The stylesheet is the design system

The stylesheet is the design system

Palette, type scale and spacing are declared once as CSS variables. Changing the accent colour is a single edit rather than a search through components.

Every page is diffed at five widths

Every page is diffed at five widths

Eight pages captured full length from 375 to 1920 pixels, baselines in the repo. A regression arrives as a failing test with a diff image attached.

A deploy that can refuse to finish

After the rebuild the workflow waits on the container health endpoint. A container that never goes healthy exits the deploy non-zero with its logs, instead of reporting success on a broken build.

RESULTS

What it does now

8 pages, 5 widthsfull-page baselines committed to the repo
0.2% pixel tolerancethe threshold a visual diff fails at
no unhealthy deploycontainer health polled for 150 seconds
STACK

What it is built on

Next.jsapp router, standalone build
TypeScriptcomponents and test suite
Tailwind CSStokens as CSS variables
Framer Motionreveal and scroll motion
Playwrightend-to-end and visual regression
Dockermulti-stage build, non-root runtime
GitHub Actionsdeploy on push to main

Got something in your workflow that looks like this?