Colophon
How this site
is built.
This site is the portfolio, so here is how it is made. Every figure on this page is read from the source code when the site is generated.
No inline script. Anywhere.
The Content-Security-Policy only lets the browser run script files served from this domain, plus two named Cloudflare scripts: the verification check and the cookieless analytics beacon. Inline <script> blocks and onclick handlers are refused. Styles may still use inline attributes; scripts may not.
Why it matters to a clientIf someone ever managed to inject markup into a page, it still could not run code in your visitors’ browsers. It also forces every behaviour into a named, reviewable file.
31 automated tests on every change.
They check that every public page carries the legal company details, has exactly one main heading, includes the assistant dialog, leaks no internal project names, and that every internal link and asset resolves. The assistant’s rules — refusing cross-origin requests, bounding message length, never quoting prices — are tested too.
Why it matters to a clientA broken link, a missing company number or a page that quietly lost its heading is caught before it ships, not reported by a visitor.
An explicit list of what ships.
The build copies 21 named pages and 70 named files. There is no folder copy and no wildcard, so drafts, internal documents and old assets cannot reach the live site by accident.
Why it matters to a clientNothing is published unless someone decided to publish it. For a client, that means private files stay private.
0 npm packages. 2 pinned libraries.
The site has no framework and installs nothing from npm. Scroll animation uses 2 self-hosted, version-pinned files (ScrollTrigger.min.js, gsap.min.js), served from this domain.
Why it matters to a clientFewer moving parts means fewer security updates, nothing to break when a package changes, and a site that still works in five years.
Static pages on a global edge network.
Every page is plain HTML generated ahead of time and served by Cloudflare Pages. The only server code is the optional assistant endpoint, which is off unless it is explicitly configured.
Why it matters to a clientFast everywhere, very little to attack, and almost nothing to run or pay for month to month.
Self-hosted type. Labelled imagery.
Archivo, Doto and JetBrains Mono are served from this domain, so no font request goes to a third party. The background films and renders behind each page were generated with Google Gemini and are decorative only: they never stand in for real work, real clients or real people. The films stay still if your device asks for reduced motion or data saving.
Why it matters to a clientFaster pages, no tracking through font services, and no stock photography pretending to be something it is not.
Built to be used without a mouse.
Visible focus on every control, a skip link, a native dialog for the assistant with focus kept inside it, keyboard-operable selectors, and animation that stops when your device asks for reduced motion.
Why it matters to a clientMore people can use it — and a site that works with a keyboard usually works better for everyone.
The actual policy
Read it yourself.
This is the Content-Security-Policy header the site sends, copied from the repository.
default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' https://challenges.cloudflare.com https://static.cloudflareinsights.com; connect-src 'self' https://challenges.cloudflare.com https://cloudflareinsights.com; frame-src https://challenges.cloudflare.com; form-action 'self' https://formsubmit.co mailto:; upgrade-insecure-requests
- The tests check structure and content, not appearance. Visual changes are reviewed by eye.
- Accessibility is designed in and checked by hand; there is no automated accessibility audit in the test suite yet.
- Performance has not yet been measured on a throttled connection against the live site, so no speed score is claimed here.
- The enquiry form is delivered by a third party (FormSubmit) and is not covered by the tests.
Start with the problem
What would you like
to work better?
You do not need a technical brief. Tell us what keeps taking time, getting missed or holding you back.