NomadNinja
An eight-chapter scroll narrative that only ever decodes one video

Capabilities demonstrated
- Web Development
- Web Design
- Interactive Web Experiences
Stack
- React 18
- Vite 5
- Motion
- Tailwind CSS v4
- Remotion
- sharp
- Azure Static Web Apps
What it is
NomadNinja is a small-group expedition brand for Japan twelve travellers, one country, six routes. The site is built as an editorial piece rather than a catalogue: its centrepiece is an eight-chapter scroll sequence that walks through a single trip minute by minute, and its argument is that almost none of a route is the summit photograph.
It is a Korame studio build. The brand is a vehicle for the engineering: a media-heavy narrative site that still has to load quickly and behave on a phone.
What made it hard
The centrepiece section is eight video chapters. The obvious implementation puts eight
The second problem was the title sequence. The brand opens with an animated mark, and the natural tool for that is Remotion but @remotion/player plus its runtime is roughly 95kB gzipped, close to the size of the entire site bundle again. Loading that in front of first paint, in order to cover first paint, is self-defeating.
How we approached it
The journey section is a tall container with a sticky stage inside it. Scroll position selects the active chapter, and only the active chapter is mounted and playing the other seven do not exist in the DOM. Each chapter owns slightly less than one screen of scroll, so the reader is always moving rather than waiting for the next beat to arrive.
Critically, nothing is scroll-jacked. The wheel, the scrollbar, the keyboard and a trackpad fling all behave exactly as they do everywhere else on the page. Hijacking scroll is the obvious way to build a sequence like this and it breaks every one of those inputs.
The intro is code-split away from the critical path. The preloader shell paints the storyboard's opening beat a mark on bare paper with no extra JavaScript at all, and the Remotion player arrives during it. The composition is transparent where the paper tears away, so what shows through the tear is the real hero section underneath rather than a picture of it. That is the reason the finale cannot simply be a video file: a video has no hole in it.
What was built
Eight-chapter sticky scroll narrative
Scroll-position-driven chapter selection with only the active clip mounted, so decode cost stays at one video regardless of section length.
No scroll-jacking
Native scroll throughout keyboard, scrollbar, wheel and trackpad momentum all behave normally.
Code-split Remotion title sequence
A programmatic intro rendered by the Remotion player, deliberately kept out of the first-paint bundle and loaded behind a zero-JavaScript shell.
Transparent reveal onto live DOM
The intro composition tears away to expose the actual hero section beneath it, not a rendered image of it.
Bilingual editorial typography
Japanese and English set together throughout the navigation and section labels as a deliberate typographic system.
Generated media pipeline
Build-time scripts produce the responsive imagery, the logo assets and the video posters, so nothing is hand-exported and nothing drifts.
Structured data generated from content
The FAQPage JSON-LD is generated from the same array that renders the FAQ, so the markup and the structured data cannot disagree.
Under the hood
Frontend
React 18 on Vite 5 with Tailwind CSS v4. Below-the-fold content is code-split into a separate chunk so the hero is not competing with the rest of the document for the main thread.
Motion
Motion throughout useScroll and useTransform for the scroll-linked chapter machinery, AnimatePresence for chapter transitions, and useReducedMotion respected at every point.
Video
Muted, looping, playsInline video with poster frames, mounted one at a time and paused when off-screen. playsInline is not optional; iOS refuses inline autoplay without it.
Build pipeline
Node scripts using sharp generate responsive imagery, brand assets, video posters and the FAQ structured data as part of the prebuild step.
SEO
Unique title and description, canonical URL, Open Graph tags, and a JSON-LD graph including TravelAgency and FAQPage all present in the served HTML rather than injected at runtime.
Deployment
Static build deployed to Azure Static Web Apps and served from the CDN edge.
How it feels to use
Navigation is a single-page anchor system with bilingual labels "The Days 日", "Places 地", "Routes 道" which doubles as the site's typographic signature rather than being decoration bolted on.
The journey section is the emotional centre and it is deliberately slow: eight beats, each under a screen of scroll, showing the unphotogenic minutes between the highlights. The design argument and the engineering constraint point the same way, because mounting one chapter at a time is both cheaper and more focused.
Everything below the first screen is deferred, so the opening animation gets the main thread to itself rather than competing with the rest of the document mounting.
What came out of it
A media-dense narrative site thirty images, multiple video sequences and a programmatic title sequence that still ships as a single JavaScript bundle and a single stylesheet, with the heaviest dependency loaded off the critical path.
The scroll narrative pattern is the reusable result: sticky stage, scroll-derived index, one mounted child. It gives the feel of a bespoke scroll experience without the two costs those usually carry, which are broken scrolling and a decoder per section.
Capabilities this draws on
Tell us what you are trying to build.
A short conversation is usually enough to tell you whether this is a week of work or a quarter of it and whether you should be building it at all.