[{"data":1,"prerenderedAt":174},["ShallowReactive",2],{"site-settings":3,"project-sofia-dives":76,"project-logs-sofia-dives":120,"project-articles-sofia-dives":173},{"global":4,"header":11,"footer":27},{"brandName":5,"brandStamp":6,"brandTagline":7,"communityUrl":8,"defaultSeoDescription":9,"defaultOgImage":10},"Useful Labs","est. 2025 · UK","Serious software, built out loud.","https:\u002F\u002Fcommunity.usefullabs.io","A product-led lab building production-grade platforms in the open — Sonic Artistes, Castora and more. A few times a year we take that same craft to a client build. Real software, shipped at product-team pace, shared honestly.",null,{"navLinks":12,"scarcityPulse":10,"showClock":25,"ctaLabel":26,"ctaUrl":8},[13,17,20,23],{"label":14,"url":15,"external":16},"Projects","\u002Fprojects",false,{"label":18,"url":19,"external":16},"Writing","\u002Fblog",{"label":21,"url":22,"external":16},"Tools","\u002Ftools",{"label":24,"url":8,"external":25},"The Hub",true,"Join the community",{"tagline":7,"aboutParagraph":28,"copyrightLine":29,"columns":30,"legalLinks":63},"A UK product lab, built in the open. Real production software, documented honestly — no hype, no highlights reel.","© Useful Labs {year} · Made in the UK with unusual patience.",[31,41,50],{"heading":14,"links":32},[33,36,39],{"label":34,"url":35,"external":25},"Sonic Artistes","https:\u002F\u002Fapp.sonicartistes.com",{"label":37,"url":38,"external":25},"Castora","https:\u002F\u002Fgetcastora.com",{"label":40,"url":15,"external":16},"Archive",{"heading":18,"links":42},[43,44,47],{"label":18,"url":19,"external":16},{"label":45,"url":46,"external":16},"RSS feed","\u002Frss.xml",{"label":48,"url":49,"external":16},"Newsletter","#newsletter",{"heading":51,"links":52},"Elsewhere",[53,54,57,60],{"label":24,"url":8,"external":25},{"label":55,"url":56,"external":25},"GitHub","https:\u002F\u002Fgithub.com\u002Fpaulwilliams-us",{"label":58,"url":59,"external":25},"X \u002F Twitter","https:\u002F\u002Fx.com",{"label":61,"url":62,"external":16},"Email","mailto:hello@usefullabs.io",[64,67,70,73],{"label":65,"url":66,"external":16},"Privacy","\u002Fprivacy",{"label":68,"url":69,"external":16},"Terms","\u002Fterms",{"label":71,"url":72,"external":16},"AI Policy","\u002Fai-policy",{"label":74,"url":75,"external":16},"Colophon","\u002Fcolophon",{"id":77,"slug":77,"name":78,"idLabel":79,"tagText":80,"description":81,"accent":82,"meta":85,"modules":95,"chips":102,"progress":109,"followLabel":112,"followHref":113,"siteUrl":10,"siteLabel":114,"status":115,"isFeatured":25,"isHeroFeatured":16,"publishedIso":116,"modifiedIso":117,"hero":-1,"contentHtml":118,"featuredImage":10,"screenshots":119},"sofia-dives","Sofia Dives","06 \u002F SD","Launching soon","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.",{"token":83,"rgb":84},"neutral","148, 163, 184",[86,89,92],{"value":87,"label":88},"8","Pages",{"value":90,"label":91},"16","CMS models",{"value":93,"label":94},"AA","Accessible",[96,97,98,99,100,101],"Story-driven homepage","Sponsorship enquiry flow","Directus-managed content","News journal","Results table","Safeguarding-first architecture",[103,104,105,106,107,108],"Astro","TypeScript","Tailwind CSS","Directus","Cloudflare Pages","EmailIt",{"label":110,"percent":111},"Build progress",85,"Follow the build","\u002Fprojects\u002Fsofia-dives","sofiadives.co.uk","shipping","2026-06-02T15:00:05","2026-06-02T16:11:51","\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n\r\n\r\n\r\n\u003Cp class=\"wp-block-paragraph\">Built with Astro and strict TypeScript, styled with Tailwind on a bespoke Navy &amp; 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.\u003C\u002Fp>\r\n\r\n\r\n\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>",[],[121,129,135,141,148,155,161,167],{"id":122,"slug":123,"projectId":77,"kind":124,"title":125,"contentHtml":126,"dateLabel":127,"publishedIso":128,"commitUrl":-1,"image":-1},"5ef6097f-8142-4a6d-85ae-0df301ac7f70","news-gets-the-magazine-treatment-full-bleed-hero-navy-drop-cap-calculated-reading-time","shipped","News gets the magazine treatment: full-bleed hero, navy drop cap, calculated reading time","\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n","3w ago","2026-06-02T15:00:00",{"id":130,"slug":131,"projectId":77,"kind":124,"title":132,"contentHtml":133,"dateLabel":127,"publishedIso":134,"commitUrl":-1,"image":-1},"e9b3b4c3-2e98-485a-a424-51314f19ea99","results-turns-into-a-broadcast-scoreboard-board-filter-pb-highlights-pagination","Results turns into a broadcast scoreboard — board filter, PB highlights, pagination","\r\n\u003Cp class=\"wp-block-paragraph\">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 \u002F 3m \u002F platform \u002F synchro), personal-best rows get a faint gold wash and a PB tag, and client-side pagination kicks in past 20 entries.\u003C\u002Fp>\r\n","2026-06-02T12:00:00",{"id":136,"slug":137,"projectId":77,"kind":124,"title":138,"contentHtml":139,"dateLabel":127,"publishedIso":140,"commitUrl":-1,"image":-1},"4c2ec4a7-957b-48f4-ab97-7adcb545b560","enquiries-now-reach-the-parents-inbox-turnstile-emailit-zero-payment-surface","Enquiries now reach the parents’ inbox: Turnstile + EmailIt, zero payment surface","\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n","2026-06-02T09:00:00",{"id":142,"slug":143,"projectId":77,"kind":144,"title":145,"contentHtml":146,"dateLabel":127,"publishedIso":147,"commitUrl":-1,"image":-1},"a3f87ebc-b8f0-4825-be46-87f777bd65c0","emailit-kept-404ing-turns-out-the-endpoint-is-v2-not-v1","fixed","EmailIt kept 404ing — turns out the endpoint is \u002Fv2\u002F, not \u002Fv1\u002F","\r\n\u003Cp class=\"wp-block-paragraph\">The contact send was failing against the \u002Fv1\u002Femails path. The live EmailIt API is \u002Fv2\u002Femails — swapped it and the enquiry flow went green end to end.\u003C\u002Fp>\r\n","2026-06-02T08:00:00",{"id":149,"slug":150,"projectId":77,"kind":151,"title":152,"contentHtml":153,"dateLabel":127,"publishedIso":154,"commitUrl":-1,"image":-1},"6208353f-b5ae-4e17-8f40-9972cee386a5","draft-news-stays-invisible-to-the-public-api-the-parents-email-never-leaves-the-server","noted","Draft news stays invisible to the public API; the parent’s email never leaves the server","\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n","2026-06-01T17:00:00",{"id":156,"slug":157,"projectId":77,"kind":124,"title":158,"contentHtml":159,"dateLabel":127,"publishedIso":160,"commitUrl":-1,"image":-1},"1dd62963-85f8-4854-aac3-79226a6e5e74","image-uploads-land-on-wasabi-and-come-back-as-on-the-fly-webp","Image uploads land on Wasabi and come back as on-the-fly WebP","\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n","2026-06-01T15:00:00",{"id":162,"slug":163,"projectId":77,"kind":124,"title":164,"contentHtml":165,"dateLabel":127,"publishedIso":166,"commitUrl":-1,"image":-1},"086bc826-3bdd-49e8-b9fd-6f03bdb71cdd","editors-edit-in-directus-the-site-rebuilds-itself-from-committed-snapshots","Editors edit in Directus; the site rebuilds itself from committed snapshots","\r\n\u003Cp class=\"wp-block-paragraph\">Content-as-code: a Directus flow posts to \u002Fapi\u002Fdirectus-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.\u003C\u002Fp>\r\n","2026-06-01T13:00:00",{"id":168,"slug":169,"projectId":77,"kind":124,"title":170,"contentHtml":171,"dateLabel":127,"publishedIso":172,"commitUrl":-1,"image":-1},"522fdd6b-0b8c-4490-b35e-82508925a115","from-brief-to-a-running-astro-build-in-a-day-8-pages-directus-wired-compiling-clean","From brief to a running Astro build in a day — 8 pages, Directus-wired, compiling clean","\r\n\u003Cp class=\"wp-block-paragraph\">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.\u003C\u002Fp>\r\n","2026-06-01T09:00:00",[],1782519037276]