The archive
06 / SD· Shipping·Launching soon

Sofia Dives

A storytelling and sponsorship website for Sofia, a 14-year-old elite junior diver on the Olympic pathway. Astro, TypeScript and a self-hosted Directus CMS on a bespoke Navy & Gold design system, deployed static to Cloudflare Pages. Enquiry-based with no on-site payments — every approach routes privately to her parents, and safeguarding leads every decision.

Added2 Jun 2026
8Pages
16CMS models
AAAccessible

Overview

A public, static-first website for Sofia — a 14-year-old elite junior diver on the Olympic pathway. It does two jobs: tell her story compellingly, and turn sponsors, funders, press and supporters into backers through an enquiry flow her parents manage end to end. No commerce, no login, no fundraising totals — just the story and a way to get in touch.

Built with Astro and strict TypeScript, styled with Tailwind on a bespoke Navy & Gold design system, and powered by a self-hosted Directus CMS so every headline, stat, milestone, result and news post is editable without touching code. The frontend ships to Cloudflare Pages as a static build that reads committed JSON snapshots: on any content change a Directus flow commits fresh snapshots to GitHub and the push triggers the build, so the live site never depends on the CMS being up.

Safeguarding is the project’s highest-priority rule. First name only; no location, school, club or training specifics anywhere — copy, alt text, metadata or structured data — and parent-approved imagery throughout. Support is enquiry-based with no on-site payments: every tier and contact CTA opens one form that emails her parents server-side via EmailIt, behind Cloudflare Turnstile and a honeypot. Analytics are cookieless and the whole site is built to WCAG 2.1 AA.

Build log

8 entries

  1. News gets the magazine treatment: full-bleed hero, navy drop cap, calculated reading time

    Single news posts now open with a full-bleed cover hero and an overlaid headline (a navy gradient and ring motif when there is no cover), then a bone reading body with a navy drop cap and Newsreader pull-quotes. Reading time is computed from word count, never entered by hand.

  2. Results turns into a broadcast scoreboard — board filter, PB highlights, pagination

    The Results page now leads with an airy achievement stat row and a Latest Result card, then a medal-badge scoreboard: filter by board (1m / 3m / platform / synchro), personal-best rows get a faint gold wash and a PB tag, and client-side pagination kicks in past 20 entries.

  3. Enquiries now reach the parents’ inbox: Turnstile + EmailIt, zero payment surface

    One shared enquiry form sits behind every tier and contact CTA. Cloudflare Turnstile plus a honeypot guard it, the send runs server-side in a Cloudflare Pages Function, and it routes to a single parent address. No checkout, no donations — support is always an enquiry.

  4. EmailIt kept 404ing — turns out the endpoint is /v2/, not /v1/

    The contact send was failing against the /v1/emails path. The live EmailIt API is /v2/emails — swapped it and the enquiry flow went green end to end.

  5. Draft news stays invisible to the public API; the parent’s email never leaves the server

    Safeguarding guardrails on the data layer: the public role reads only published news and active supporters, the parent email is excluded from every public response and injected server-side, and a draft news item was confirmed invisible to the public API. First name only, everywhere.

  6. Image uploads land on Wasabi and come back as on-the-fly WebP

    Directus stores uploads in an S3-compatible Wasabi bucket and serves them through on-the-fly transforms. A 1.8 MB PNG comes back as a ~92 KB WebP at the right width — hero, news covers and supporter logos are all sized at request time.

  7. Editors edit in Directus; the site rebuilds itself from committed snapshots

    Content-as-code: a Directus flow posts to /api/directus-sync, which pulls the public content and commits fresh JSON snapshots to GitHub. The push triggers the Cloudflare Pages build — so the live site reads committed snapshots and never depends on Directus being up.

  8. From brief to a running Astro build in a day — 8 pages, Directus-wired, compiling clean

    Day one and the whole thing stands up: Home, Her Story, Results, News, Support, Contact and Privacy, all ported from the mockups, wired to a self-hosted Directus, and passing astro check + build with zero errors. Static-first on Cloudflare Pages, strict TypeScript, self-hosted fonts.