Skip to content
All work

02Editorial site + headless CMS

Fieldnote

Fieldnote is the build most studios actually subcontract: a content-led site with a real editing experience behind it. The Studio is embedded at /studio rather than hosted separately, so there is one deploy, one domain, and one thing for an editor to bookmark. If you look at one thing here, make it the 45-second capture of the editing experience — it answers the question a screenshot cannot.

Measured on the finished build

Lighthouse, homepage
97 / 100 / 100 / 100 / 100, mobile, LH 13.4.1
Lighthouse, article
95 / 100 / 100 / 100 / 100
Homepage timings
FCP 1.1s, LCP 2.6s, TBT 20ms, CLS 0
Article timings
FCP 0.9s, LCP 2.9s, TBT 20ms, CLS 0
Revalidation
Tag-based, webhook-driven, no timer
Editing experience
45-second capture, no narration, linked from the README

The hard part

The CMS is the deliverable, and nobody demos it

A headless build is judged twice: once by the visitor, on speed, and once by the editor, every week for years. The second audience is the one that renews the retainer, and it is the one a portfolio screenshot never shows.

The technical half of that is cache invalidation. An editor who hits publish, reloads, and sees the old version reasonably concludes the integration is broken — and then rings the studio.

What I did

Model it for the editor, invalidate on publish

The content model carries field descriptions, validation and custom preview titles, so the Studio reads as a tool rather than a form. Draft mode reads the drafts perspective, caches nothing, and turns on stega — invisible characters encoding document and field ids into the text, which is what makes a click on the rendered page jump to the right field in the Studio. Stega is enabled per request rather than on the client, because those characters are corruption in published output: they travel into copied text and search results.

Nothing revalidates on a timer. An article is not stale sixty seconds after it was fetched; it is stale when an editor changes it. Responses are cached indefinitely and tagged by document type and identity, and the publish webhook clears the matching tags when Sanity says something changed.

Decisions, with the price attached

What was chosen, and what it cost

Stated rather than left to be found

Known limits