Build log · The Stillness Report
Brief
An editorial chapter — the first of the anthology — rendered as an issue of a fictional quarterly called The Stillness Report. The aesthetic target was unmistakably editorial: serif display type, a deliberate masthead, an asymmetric content grid, and interaction details that feel quiet rather than showy. The reviewer should read the landing hero, click "Open chapter" on Chapter 01, and feel the transition hand them off to a different register with its own typographic voice.
Patterns used
grid-page-transition— mosaic wipe into the chaptereditorial-grid-variable-span— 8-column asymmetric gridtext-scramble-hover— interactive headingspixel-grid-mouse-trail— ambient cursor layerinfinite-marquee-css— footer ticker
Type and palette
Fraunces (variable serif) for display, JetBrains Mono for body and metadata. The two pair because
Fraunces has enough personality to carry an editorial masthead while Mono keeps captions, bylines,
and dates feeling like plates from a printing press. The chapter palette is set on the route's
layout wrapper via [data-chapter="editorial"], switching these CSS variables:
[data-chapter="editorial"] {
--color-bg: #f5f2ea;
--color-fg: #121212;
--color-muted: #646058;
--color-accent: #8a1515;
}The accent red is only used for metadata — issue number, tags, the marquee bullets. It appears fewer than a dozen times on the page, which is exactly the point.
Decisions
The grid is an 8-column system, not 12
Twelve-column layouts are the default, but they invite halves and thirds — symmetrical chunking
that reads more like a product page than a publication. Eight columns favours 5 + 3 and 3 + 5
pairings, which is the asymmetry that makes magazine grids feel deliberately composed.
editorial-grid-variable-span/index.tsx exposes five spans (slim | narrow | half | wide | full)
and three breakpoints (single column → 4 → 8). Every card declares its intent; the grid does the
layout. Authors never write column math at the page level.
Page transitions are opt-in, not global
The grid-page-transition pattern is tempting to make site-wide: one provider, every link
hijacked, the whole product feels "transition-y." I pushed back. Not every chapter uses the same
transition — Chapter 02 needs a clip-path reveal, Chapter 03 a different shape again — and a
site-wide hijack loses its specificity the third time you see it.
The provider in grid-page-transition/grid-transition.tsx intercepts only anchors that carry
data-transition="grid". Landing page's editorial card sets it. Nothing else does. When Chapters
02 and 03 land, each will register its own provider listening on a distinct value. Providers
coexist; the set of links each owns is disjoint.
The pull quote sits on a blockquote with semantic footer
Easy to miss, but the pull quote on this page uses <blockquote> with a <footer> inside — the
same markup a real publication would ship. Screen readers get the quotation structure; styling
(the em-dash, the tracking, the uppercase byline) lives purely in the visual layer. The
temptation to render it as a clever div with ARIA roles is the wrong one.
Text scramble triggers on focus, not just hover
Focus parity is boring but important. Keyboard users tab through headings; the scramble fires on
onFocus the same way it fires on onMouseEnter. The tabIndex={0} is the tradeoff — we add a
stop to the tab order. For a fictional publication that's reasonable; for a real product catalog
it might not be.
Pixel grid blend mode differs from its source
The reference site (digital.tattooprojects.com) uses mix-blend-mode: soft-light on a dark
background. That looks great on a near-black canvas; on The Stillness Report's warm-paper bg
(#f5f2ea) soft-light is invisible. I switched to difference with a clamped maxOpacity: 0.55.
The grid now reads as a faint ink-wash reacting to the cursor — editorial, not gamer.
Marquee is CSS-only and accessibility-tagged
infinite-marquee-css ships as a server component. No hydration, no scroll listeners. The
duplicated track is marked aria-hidden="true" so screen readers read the ticker exactly once.
prefers-reduced-motion pauses the animation via a media query — no JS involved. This is one of
the pattern library's cheapest components and the one most likely to survive future refactors
unchanged.
Tradeoffs rejected
- Running the scramble animation on every card image by default. Too busy. The scramble is reserved for headings, where the reader's attention has just arrived.
- Using GSAP Flip for the grid layout. Overkill — CSS Grid handles this natively, and Flip would add bundle weight for no visible payoff.
- Pinning the masthead. Would cannibalise screen space and compete with the custom cursor + pixel grid for z-index attention. The masthead is tall on purpose; let it scroll off.
- Per-card hover video. Images are grayscale-by-default, saturate on hover. Adding video to cards would double payload and break the "reading a quiet publication" mood.
Performance notes
- Google Fonts loaded via
next/fontwithdisplay: swap. Fraunces is an opsz-axis variable font, which means one file covers every size we use. - Unsplash images loaded through
next/imagewith explicitsizes. The grid's tallest wide card is 1400w; the narrow cards cap at 900w. - Pixel grid is 40 × 24 = 960 cells on this page. GPU-composited opacity transitions. On an M1
this runs pinned at 60 fps with the scroll active; on low-end hardware the setTimeout queue can
back up — a future refactor could batch updates in a single
rAFpass. - The mosaic transition runs once per navigation and is 96 cells (
12 × 8). Stagger amount is 0.45s; the whole in/out cycle is under 700ms, which is slower than instinct says it should be but exactly right for the ceremony the chapter needs.
What I'd change in production
- Make the article cards real routes. Right now they're visual only. Each should resolve to
/editorial/the-nine-minute-rulewith its own article layout, and the build log should link into them. That's a second pass worth doing once an editor has actual copy. - Swap Unsplash for commissioned photography. The grayscale → colour hover tells on the stock images; editorial sites live or die by their art direction.
- Add a print stylesheet. Editorial sites have readers who print. Twenty lines of CSS gets you a respectable letter-format output.
- Pull the pixel grid into a shared
AmbientLayerprimitive once Chapters 02 and 03 are live, so each chapter can swap its ambient treatment (video texture for cinematic, animated SVG for playful) without duplicating the viewport-layer plumbing.