Shots in this scene
The lumen-motion Project
In one line
You will build one project all course: the launch page of the Lumen Volt e-bike. It starts complete and still; each phase gives one part motion. Every file has a place in one folder layout that never changes.
Think of it like this
Animators on a film do not start by drawing a new world. The set and the characters are designed first; then each scene is brought to life, shot by shot. The Lumen Volt page is your finished set. Each phase animates one scene.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- build-along
- A course where one project grows from phase to phase, instead of separate small demos.
- motion token
- A named value for motion, such as
--dur-base: 220ms, used everywhere instead of typing numbers by hand. Phase 2 starts them; Phase 18 finishes them. - motion spec
- A short document that lists each animation: what triggers it, what changes, how long it takes, its easing, and its reduced-motion version.
- storyboard
- A few sketches of key moments of an animation, drawn before any code, so the team agrees on what should happen.
Step by step
01The folder tree
This is the layout you will have by the end. You start with four files and add the rest phase by phase.
lumen-motion/
├── package.json scripts and pinned versions
├── vite.config.js two pages: index.html and ride.html (Phase 11)
├── index.html the Lumen Volt launch page
├── ride.html the ride page (Phase 11)
├── src/
│ ├── styles/
│ │ ├── tokens.css motion tokens (Phase 2, finished in 18)
│ │ ├── base.css page layout and type
│ │ ├── components.css buttons, toast, drawer, cards, gallery
│ │ ├── scroll.css scroll-driven effects (Phase 12)
│ │ └── motion-safe.css reduced motion and the site toggle (Phase 7)
│ ├── js/
│ │ ├── main.js wires everything
│ │ ├── motion/ loop.js, prefers-reduced.js, spring.js, flip.js
│ │ ├── components/ toast, cart, drawer, gallery, transitions, mascot, confetti
│ │ └── gsap/ the launch timeline (Phase 14)
│ ├── react/ the bike configurator (Phase 15)
│ └── assets/
│ ├── svg/ logo and route line (Phase 13)
│ └── mascot/ headlight.lottie (Phase 16)
├── docs/
│ └── motion-spec.md storyboard and spec (Phase 2)
└── tests/
├── motion.test.js Vitest (Phase 18)
└── launch.spec.js Playwright (Phases 18 and 19)02Replace the starter files
Vite's starter has src/main.js, src/counter.js and src/style.css. Delete counter.js and style.css, and create src/styles/ and src/js/. Topic 0.6 gives you the four files of the still page.
03One part per phase
Each phase animates one part of the page: the buttons in Phase 3, a toast in Phase 4, the accessory grid in Phase 5, and so on. Click a part of the map below to see which phases touch it.
04Keep the names
Later phases import functions and find elements by name: showToast in toast.js, the cart count #cart-count, the gallery's .photo elements. Keep the names the build topics use, so every phase's code fits the last one.
Try it yourself
- 1
Plan your own order
Click every part of the map. Which part gets the most phases? (The hero: a loading bar, a jank fix, a GSAP launch timeline and the confetti.) Pick the part you are most curious about and look up its phase in the course outline.
- 2
Look at the highlight's track
Click one part, then another, and look at the timeline. The first click starts five tracks, not two:
background-color, plus one for each side of the border (border-top-color,border-right-color,border-bottom-color,border-left-color), becauseborder-coloris a shorthand the browser splits into four properties. The second click on another part shows ten: five for the part that turns on and five for the part that turns off (they replace the first click's five). All are 160 ms. The background track is green (Chromium composites background-colour animations); the four border tracks are amber, because border colours repaint.
Code & diagrams
A map of the launch page. Click a part: it highlights with 160 ms colour transitions (the timeline shows which repaint) and the line below names the phases that animate it.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Rename a part's class
In the HTML of "Which phase animates which part?", change the first class="part" to class="parts", then click "Header · cart".
Myth vs fact
Myth
A demo per technique teaches as much as one project.
Fact
Demos skip the hard part: making many animations live together with shared tokens, one reduced-motion system and clean-up when parts are removed. The growing project makes you solve that.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Keeping motion values in
tokens.cssfrom Phase 2 means a later change ("make everything 20% faster on mobile") is one edit, not a search through every file. Phase 18 adds a JavaScript mirror so CSS and JavaScript animations share the same numbers. - ▸
The page works with JavaScript off and with reduced motion on before any animation is added. Every phase keeps both true: motion is an enhancement on top of a working page, never a requirement for it.
Remember this
- 1
The problem this solves: small separate demos teach techniques but not how they live together: one motion system, one set of tokens, reduced motion everywhere, nothing leaking when a part is removed. A single growing project forces those questions, the way a real job does.
- 2
The story. Lumen Bikes rents bikes across the island city of Ardenvale and is launching its first e-bike, the Volt. The team: Ama (head of design, wants "alive but calm"), Kofi (frontend engineer, owns the code), Mei (motion designer, makes storyboards and animation files), Lena (QA, tests on a cheap Android phone and a 120 Hz iPhone), Ravi (accessibility tester, who has a vestibular disorder and uses reduced motion and a screen reader) and Tomás (the founder). Each phase opens with the moment that needs its skill.
- 3
The page. A header with the Lumen logo and a cart button; a hero with the Volt, its price and a Reserve button; six accessories you can add to the cart; a gallery you can filter by colour; specs in collapsible sections; a footer. In later phases it gains a toast area, a cart drawer, a ride page, a scroll story, a React configurator, a mascot and confetti.
- 4
The folder layout (it stays the same all course, and each build topic says which files it adds or changes):
index.htmland laterride.htmlat the top;src/styles/fortokens.css(motion tokens),base.css,components.css,scroll.cssandmotion-safe.css;src/js/formain.js, your own helpers inmotion/, the parts incomponents/and the GSAP code ingsap/;src/react/for the configurator;src/assets/for SVG and the mascot file;docs/motion-spec.md; andtests/. The full tree is below. - 5
From this page to your files. Examples on this page are single pages: HTML, CSS and JavaScript tabs. Your project splits the same code across files. Each build topic shows every changed file in full under "Your project files", and its last live example is the same code merged into one page, so you can see it run here before you copy it.
Explain it without notes
Why does the course build one project instead of separate demos?
What are motion tokens and why start them early?
Practice
Draw the launch page on paper, one box per part, and write next to each box what you would like it to do when it moves. Keep the sheet: Phase 2 turns it into a motion spec.
In your Vite project, create the folders src/styles, src/js, src/js/motion, src/js/components and docs, and delete the starter's counter.js and style.css.
Done when you can
You can describe the Lumen Volt page and its parts
You know the folder layout and where each kind of file goes
You know the team and why Ravi's reduced-motion rule matters