Overview
Apollo Tyres Experience is a single-page, fully immersive 3D website that turns a tyre product catalogue into a guided brand story. A photorealistic 3D tyre sits at the centre of the screen and animates continuously as the visitor scrolls, leading them through six full-screen narrative sections — a rotating hero product slider, a vehicle selector, durability and safety stories, a feature grid, and a final call-to-action.
The defining idea: the 3D scene and the HTML content are not two layers stacked on top of each other — they are one choreographed experience sharing a single colour palette, lighting language, and motion system.
The Challenge
Tyres are a low-engagement, high-commodity product — most tyre websites are static spec sheets. The brief was to make a tyre feel premium, engineered, and worth exploring, the way a car or a flagship phone is marketed. That created three hard problems:
- Engagement — keep a visitor scrolling through a full brand story instead of bouncing.
- Cohesion — a 3D WebGL object and standard HTML text usually look like they belong to different worlds. They had to feel like one designed scene.
- Reach — deliver a heavy real-time 3D experience that still runs and adapts gracefully on mobile.
The Approach
1. Scroll as the storytelling engine
Instead of native browser scroll, the experience is driven by
ScrollControls from @react-three/drei across
six "pages" of content. Native scrollbars are hidden and
overflow is locked, so scrolling becomes a
timeline scrubber rather than a document scroll. The tyre's
movement is defined as keyframes — position and rotation targets at
specific scroll offsets — interpolated with a smoothstep easing curve
and continuous rotation to avoid any snapping:
const ANIMATION_SEQUENCE_DESKTOP = [
{ t: 0.00, pos: (0, -25, 0), rot: (0, 0.4, 0) }, // Hero: centre
{ t: 0.18, pos: (130, 0, -50), rot: (0.1, 1.8, 0.1) },// Vehicle select
{ t: 0.35, pos: (100, -10, -60), rot: (0, 3.2, 0.2) }, // Durability
{ t: 0.55, pos: (-120, 5, -40), rot: (-0.1, 4.8, -0.1)},// Safety
{ t: 0.75, pos: (0, -10, -100), rot: (0, 6.2, 0) }, // Features
{ t: 1.00, pos: (0, -30, -200), rot: (0.2, 7.5, 0) } // Footer: recedes
];
The camera itself reacts to scroll velocity — a "rush" impulse zooms in when scrolling down and eases out when scrolling up — giving the whole page a sense of momentum.
2. One palette, two renderers
The entire design system is declared once in the Tailwind config. The same hex values feed both Tailwind CSS classes and the Three.js lights and materials, so the WebGL tyre and the HTML headlines read as a single scene lit by the same studio.
| Token | Hex | In the DOM | In the 3D scene |
|---|---|---|---|
| orange | #f7941d | CTAs, accents | Rim light, hover-pulse emissive |
| purple | #5c2d91 | Vehicle selector, borders | Fill light, idle "breathing" emissive |
| backdrop | #050505 | Body background | Canvas clear colour |
3. A studio lighting rig in WebGL
Rather than flat lighting, the scene uses a multi-light photographic
setup: a crisp white key light, strong purple fill and rim lights for
brand-coloured edge definition, orange dramatic rim and kick lights,
low ambient for contrast, and a blurred city environment
map for realistic metal reflections. The rim "breathes" purple at idle
and pulses orange on hover.
4. Tactile interaction
The tyre is a physical object you can play with: grab-and-drag to
orbit it, with grab / grabbing cursor states
for affordance; it spins faster as you scroll and slows when you hover
to inspect it; and a point light kicks on under the hover state to
make it gleam.
5. Built to adapt
A resize listener switches between two complete animation paths — a
desktop sequence with wide horizontal movement and a mobile sequence
constrained to a narrow viewport — and scales the model down on
mobile. Device pixel ratio is capped at [1, 2] to protect
performance on high-DPI screens.
6. A procedural fallback tyre
The project ships with a complete code path that
builds a tyre entirely from primitives — cylinders
and tori for the carcass, instanced meshes for 40 tread blocks and
shoulder lugs, and curved 3D text spelling "APTERRA AT2" / "APOLLO" /
"245/70 R16" wrapped around the sidewall. A single
USE_CUSTOM_MODEL flag swaps between this generated
geometry and the loaded .glb model.
Technology
| Layer | Choice | Why |
|---|---|---|
| Framework | React 19 + TypeScript | Component model + type safety for a complex animated scene |
| Build | Vite 6 | Instant HMR, fast 3D-asset iteration |
| 3D core | Three.js | Industry-standard WebGL engine |
| 3D React layer | @react-three/fiber | Declarative Three.js as React components |
| 3D helpers | @react-three/drei | ScrollControls, Environment, ContactShadows, useGLTF, Text |
| Styling | Tailwind CSS | Single-file design tokens shared with the 3D layer |
| Icons | lucide-react | Consistent, lightweight iconography |
| Fonts | Orbitron + Rajdhani | Technical, engineered typographic voice |
| Asset | tyre.glb | Custom GLTF product model |
Highlights
Unified Design System
A single source-of-truth token set drives both the DOM and WebGL, eliminating the usual visual seam between 3D and HTML.
Velocity-Aware Camera
Scroll speed — not just position — shapes the cinematography, adding momentum to every movement.
Dual Responsive Choreography
Separate keyframe timelines and model scale for desktop and mobile, not just CSS breakpoints.
Resilient Geometry
A procedural fallback means the experience can render a full tyre even without the binary model asset.
Outcome
The result transforms a commodity product page into a premium, explorable showcase where the tyre is the hero and the brand's colour and lighting language carries consistently from the first pixel of HTML into the depths of the 3D scene. It demonstrates that real-time WebGL and conventional web content can be fused into one coherent, performant, responsive experience.