Riflessi Auto Care
It’s easy to call an architecture reusable. I built a second site on mine to find out, and I’ll show you what had to change.
- Period
- Jul – Sep 2026
- Role
- Sole engineer · self-directed
- Reading
- 2 min
Overview
Riflessi Auto Care took five weeks from its first commit to a full first build. I swapped the design-token values, rewrote the content against the same fixed type contracts, and adapted the components to the new brand, while the content layer, tokens and lead pipeline carried over. That’s how I know DriftPilot’s abstractions were doing real work.
Two parts did need new code, the motion layer and the 3D stage, because they were things DriftPilot never had.
Why a 3D model at all
A detailer sells a finish, and you judge a finish from more than one angle. So the homepage is a scroll-driven sequence in seven acts. Each act pairs its copy with a camera pose and a material state: where the camera sits and what it points at, how bright the key light is, and how far the paint has come from freshly corrected to a cured ceramic coat. As you scroll, the car moves between them. A photo can’t do that, and it’s the reason the site has a 3D model at all. It’s also most of what makes the site feel premium.
GSAP ScrollTrigger tracks the progress and Lenis smooths the scroll. Both load in the same lazy chunk as the scene, so a visitor on the static fallback never downloads either one. Lenis only runs while the sequence is on the page, so every other route keeps native scrolling, and the render loop stops as soon as the sequence scrolls out of view.
The 19 MB hero
The hardest part was the hero: a licensed 3D vehicle model that weighed 19.07 MB, on a site aiming to load in under 1.5 seconds.
The obvious fix didn’t work. Every node in the asset had the same name, so matching on node names found nothing; the meaning lived in the material names. So I deleted hidden geometry by material instead. Profiling showed the tyres alone were 63% of the model, so I decimated them from 205k to 96k vertices. I stripped all seven textures, because the paint is applied at runtime, then welded, deduplicated, quantized and meshopt-compressed what was left. It came out at 2.05 MB, an 89% reduction, with a content-hashed filename so a one-year immutable cache header is safe.
Gating at the import
I gate the 3D scene at the dynamic import, so a device that can’t run it never downloads the chunk. Viewport size, CPU core count, device memory and a WebGL probe decide, and prefers-reduced-motion overrides all of them. Gating the render would have been easier, but it would still have shipped the payload.
Keeping the shop’s address private
A preparation script strips every photo’s metadata, GPS included, and blurs any licence plate I’ve marked before the photo goes on the site. The shop runs from home and the site keeps the address private on purpose, so the GPS data in the first uploaded photo would have given it away. The script also lists every photo nobody has checked for plates yet, so a missed one shows up before it ships.
Stack
- Next.js 16
- React Three Fiber
- GSAP ScrollTrigger
- Lenis
- glTF-Transform
- meshoptimizer
Measured
- First commit to first full build7 Jul – 11 Aug 2026
- 5 weeks
- Hero asset reduction19.07 MB → 2.05 MB
- 89%
- Tyre mesh verticesafter decimation
- 205k → 96k
- Pull requests in that build
- 11

