Hello
A scroll essay on thirty-six greetings from thirty-six languages, built in Next.js with eighteen self-hosted scripts, a build that fails if any of them renders wrong, and a plain-text version of the whole thing.
Creative Frontend Development
2 Days

Introduction
A scroll essay on thirty-six greetings from thirty-six languages, built in Next.js with eighteen self-hosted scripts, a build that fails if any of them renders wrong, and a plain-text version of the whole thing.
Work Done
Interactive Essay

Challenges
Setting thirty-six words in eighteen writing systems without shipping whole font families or letting a subset break Arabic joining, and making a scroll-driven piece work for readers who can't scroll.

Solutions
A subset Noto face per script, with a CI guard that runs the real shaper through fontkit and fails the build on any .notdef glyph. Three scroll primitives in total, plus a parallel /text route carrying the same entries with no motion.


Results
A fully prerendered page, installable as a PWA, that holds thirty-six full-viewport sections cheaply and puts its no-motion version in the skip link.
Details
Almost none of them mean "hello"
Hello is a scroll essay about thirty-six greetings and the thing they have in common: hardly any of them literally mean hello. They mean peace, health, victory, breath — or simply, I see you. Each greeting gets a full screen, a romanization and IPA, a line saying what the words actually say, and a short essay on where it came from.
Eighteen scripts, checked by the build
Eighteen writing systems, each needing its own Noto face subset down to just the glyphs the site uses. Codepoint coverage turns out not to be enough. Subsetting can strip a font's GSUB and GPOS tables and leave you a file that contains every character and still renders Arabic unjoined, Devanagari with matras floating off their consonants. So the build runs the real shaper through fontkit, lays each word out, and fails if one glyph comes back `.notdef`.
Three ScrollTriggers for thirty-eight sections
The naive build of a snapping scroll site puts a ScrollTrigger on every section, and they spend their time fighting over the scroll position. This one runs on three things: one ScrollTrigger holding a snap-point array, one IntersectionObserver deciding which section is active, and one keyboard listener.
The observer sets `data-state="active | passed | upcoming"` and every reveal is CSS reading off that attribute. That includes the ink wipe, which paints a greeting on through a masked gradient and then, once you scroll past, unwrites it in the direction it was laid down. GSAP tweens none of it. It runs the ticker Lenis shares, so smooth scroll and the progress rail never disagree about where the page is.
A text version, not a fallback
The skip link doesn't go to "main content". It goes to `/text`, which describes itself as the plain reading of the site: no scrolling, no animation, no sound. Under reduced motion the snapping is skipped and the page simply scrolls. Even the 404 is in on it, with faces arranged into the numerals under the line "Nobody here says anything."
Tope Akintola
September 20, 2026
Creative Frontend Development
