toji.moe
This site: a scroll-driven train ride from an afternoon park to a night station, with a 3D mascot and scenes that follow your clock.
Visit the site ↗- ROLESolo · design, code, 3D
- YEAR2026
- STACKNext.js 16 · TypeScript · Tailwind · GSAP · Lenis · anime.js · three.js · Blender · Python
- TypeScript55.8%
- Python32.9%
- CSS10.8%
- JavaScript0.5%
A portfolio you ride instead of read
Most portfolios are a list. I wanted mine to feel like a short trip: you scroll, and the camera walks from an afternoon park, along a river at golden hour, into a study full of project folders, and out to a night station where the contact tickets wait. Toji, my raccoon mascot, sits in every scene.
The page follows your clock: day, a dusk palette from four, night after seven, and a small weather chip for where you are. It reads in English or Vietnamese.
Scenes as data, motion on scroll
Each scene is layered artwork kept as source files. A Python script turns them into SVG components with three palettes and their parallax depths, and Next.js renders them on the server, so the artwork arrives as HTML and never runs as JavaScript. GSAP ScrollTrigger and Lenis drive the ride, and every section opens on the exact last frame of the one before it, so the hand-offs don't show.
In About, Toji is a real 3D model that I rigged and animated in Blender with Python: idle fidgets, blinking, and a turn toward your cursor that keeps the hands where they belong. three.js only loads after your first scroll or tap, and with data saver on you get the drawing instead.
A busy page that still loads light
All that artwork is thousands of SVG nodes, and on a throttled phone the first setup of every scroll animation was one 2.7-second freeze. Building each section only as you get near it, and animating only the layout on screen, took Lighthouse's blocking time from 2.9 s to about half a second.
With reduced motion the journey becomes a calm stacked page, the whole ride works from the keyboard, and with JavaScript off the content is still there.