Hello — Thirty-six Ways to Greet
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
Research, writing, design, and build. I wrote all thirty-six entries myself, each with its etymology, its literal gloss and a short essay, then built the site around them. That covered the font subsetting pipeline, the scroll system and the plain-text version.

Challenges
Setting thirty-six words in eighteen writing systems on one page, without shipping whole font families and without a subset quietly breaking Arabic joining or leaving Devanagari matras floating off their consonants. The second problem was simpler to state: the whole piece argues by scrolling, and some readers can't or won't scroll through animation.

Solutions
A Noto face per script, subset to the glyphs actually used, with a CI guard that runs the real shaper through fontkit and fails the build on any .notdef glyph. Three scroll primitives in total: one ScrollTrigger for snapping, one IntersectionObserver for active state, one keyboard listener. Every reveal is CSS reading off a data-state attribute. A parallel /text route carries the same thirty-six entries with no motion.


Results
A fully prerendered page that stays cheap across thirty-six full-viewport sections by leaning on content-visibility. It installs as a PWA, and the no-motion version is linked from the skip link rather than buried.
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
