Pub — 3D scrollytelling site
Scrolling walks you through the pub in 3D, then to the full menu and a WhatsApp order.
- Astro
- Three.js
- Lenis
- JavaScript
- GitHub Actions
- GitHub Pages
- 0downloaded 3D models: every object is procedural
- 3tiers: full 3D, lighter 3D on phones, SVG fallback
- 15bugs logged as symptom, cause and fix
From one text file to a walk through the pub
A static site where the scroll moves a camera from the door past the tap, the burgers and the darts, while the menu and the opening hours live in one content file.
Tap a block to see what it does.
- Input
- Infrastructure
- Logic
- Output
Input
Content file
One TypeScript file holds hours, the full menu with prices, contacts and SEO. Fields still to confirm are flagged in comments.
- TypeScript
Hands to Static build
Infrastructure
Static build
Astro renders the home and the menu page to static HTML; GitHub Actions builds and publishes on every push to the site folder.
- Astro
- GitHub Actions
- GitHub Pages
Gets from Content fileHands to Device check, Menu and cart
Logic
Device check
Reads WebGL support, device memory, data saver and reduced motion, then picks full 3D on desktop, lighter 3D on phones, or no 3D.
- JavaScript
Gets from Static buildHands to Scroll timeline, SVG fallback
Output
Menu and cart
Menu page with SVG icons per category and a cart kept in localStorage (sizes, quantities, total). The order leaves as a WhatsApp message; no backend.
- localStorage
- SVG
Gets from Static build
Logic
Scroll timeline
Lenis driven by one requestAnimationFrame loop and a single 0 to 1 progress. Camera waypoints with tension and easing; no GSAP.
- Lenis
Gets from Device checkHands to Pub in 3D
Output
SVG fallback
Without WebGL, with reduced motion or data saver: the same story in SVG, and the glass still fills as you scroll.
- SVG
- CSS
Gets from Device check
Output
Pub in 3D
Procedural Three.js stations: a pint filling at the tap, a burger coming apart in mid-air, darts, two mugs toasting on the call to action.
- Three.js
- WebGL
Gets from Scroll timeline

The problem
A craft-beer pub with beers on tap, burgers and a game room had only photos and a PDF menu. It needed a site that gives the feel of the place, stays fast on phones and can be updated without a developer.
What I built
- I made scrolling the story: you enter through the door and the camera moves through the pub, stopping at stations with small scenes.
- I directed the camera paths as waypoints with tension and easing, so the ride does not feel like it runs on rails.
- I had every object built procedurally in Three.js, with no downloaded models, to keep control of weight and look.
- I put hours, menu, contacts and SEO in one content file, so an update is a text edit, and orders and table requests leave as a prefilled WhatsApp message.
- I turned the method into a reusable skill for scroll-driven 3D sites: camera rig, scroll timeline, render loop, device checks.
The hard part
Smooth motion on phones. Animation tied to the frame rate caused jank, the camera jumped on the first scroll in mobile Chrome and Safari, and lazy GPU uploads caused micro-stutter. I logged each bug as symptom, cause and fix; the stutter went away by pre-warming the GPU along the camera path.
Result
Live as a static site with the walkthrough and a menu page, rebuilt and published by GitHub Actions on every push. A second-opinion audit by Codex on the published bundle rated the product 8.1/10 and the code 7.4/10.
My role
I set the concept and the camera direction, chose scenes and details, tested on real phones and merged through my pull requests; Claude Code wrote the code on its own branches.