WebXR demos & mini-games built with Three.js r184 + TypeScript + Vite, deployed to Cloudflare Pages with free HTTPS (required for WebXR). Built 2026-06-10.
โถ quest3-playground.pages.devquest3-playground.pages.dev in the address bar โ tap a demo card โ press Enter VR (or Start AR for passthrough demos) โ grant permissions when asked.
Press โ on the right controller to open the universal menu, then launch Browser (Meta Horizon Browser). It's a Chromium browser with full WebXR support โ nothing to install.
quest3-playground.pages.dev.
Type it in the address bar (or log into the same Meta account on your phone's Horizon app and send the tab to the headset). Bookmark it: tap the โญ in the address bar so it's one tap next time.
Each demo shows an Enter VR / Start AR button at the bottom of the page. AR demos (Room Invaders, Hand Garden) will show your real room via passthrough. The first time, the browser asks permission for the immersive session โ accept.
Hand tracking activates automatically a moment after you set the controllers down (make sure Settings โ Movement tracking โ Hand tracking is enabled). Pinch thumb+index to grab.
WebXR immersive sessions require a secure context (HTTPS) โ the Quest browser will simply not show the Enter VR button on plain http:// origins (only localhost is exempt, and "localhost" on the Quest is the headset itself). That rules out http://kubic.home.arpa:30xxx as-is. Your options, ranked:
| Method | Effort | Verdict |
|---|---|---|
| Cloudflare Pages (what we did) | One wrangler pages deploy | โ Free HTTPS, fast CDN, zero config. Re-deploy in ~10 s. |
| USB cable + adb reverse | adb reverse tcp:5173 tcp:5173 then open http://localhost:5173 in the headset | โ Best for rapid dev iteration โ headset sees your Mac's Vite dev server as its own localhost (secure-context exempt). Needs developer mode + USB-C cable. |
| kubic LAN + HTTPS | mkcert CA, install cert on Quest, or a Cloudflare Tunnel | โ ๏ธ Works but fiddly: Quest makes installing custom CAs painful. A cloudflared tunnel from kubic is the saner LAN-ish route. |
| Plain HTTP on LAN | โ | โ Enter VR button never appears. Dead end. |
All demos share a small TypeScript boilerplate (src/lib/xr.ts) that sets up the renderer (foveation 0.5, framebuffer scale 1.2 for Quest 3 sharpness, local-floor reference space), controllers with models + haptics, optional articulated hands, an in-VR canvas-texture score panel, and procedural WebAudio sound effects โ no audio files needed.
The hello-world: floating cube in a starfield. Point + trigger recolors it with a haptic kick. ~80 lines of demo code over the boilerplate โ the template for everything else.
open โถ60-second arcade round. Balloons spawn around you with wobble physics; laser-pop them for points. Score panel, pop particles, haptic pulses, procedural sfx, wave pacing.
open โถDrones materialize in your actual room and home in on your head. 3 lives, escalating waves, explosion shards. Shows why Quest 3 passthrough is the killer feature.
open โถController-free: pinch floating crystals with bare hands (25-joint tracking), throw them with real hand velocity, watch them drift back home. Runs in passthrough.
open โถSix classic glTF models (Damaged Helmet, Avocado, Duck, animated Fox/Horse/Flamingo) on pedestals under real HDRI image-based lighting. Trigger a pedestal to spin its exhibit.
open โถThe landing page is designed to be browsed inside the headset: big cards, big tap targets, plus 14 hand-picked external WebXR experiences one tap away.
open โถRanked roughly by wow-per-effort on Quest 3. Effort: weekend 1โ2 weeks ambitious
Use mesh detection (mesh-detection feature) to find a real wall, then render a stencil-buffer "hole" in it revealing a sci-fi vista behind. The single most jaw-dropping MR trick per line of code.
A ball bounces off your real walls and floor (plane detection + rapier physics). Controller = paddle. Quest 3's room mesh makes the ball feel genuinely physical.
An animated critter (the Fox model works!) lives on your real desk: walks on detected surfaces, follows your hand, eats pinch-fed virtual snacks, sleeps when ignored. Tamagotchi energy.
Two-handed bow archery (one hand holds, one draws โ great controller interaction) defending a castle wall from waves. Kenney's CC0 Castle Kit has all the models.
Punch incoming note-blocks to the beat (Moon Rider-lite). WebAudio analyser can auto-generate patterns from any MP3 the user drops in โ infinite content.
Minecraft-creative-lite: place/remove voxels with pinch gestures, palette on your wrist, export to GLB. Highly shareable output.
Water level rises in your real room (screen-space water shader clipped by room mesh). Fish swim around your furniture. Pure ambience showcase โ demo-reel material.
Two headsets (or headset + phone spectator) in one arena via WebRTC/WebSocket on kubic โ the one place your k8s cluster genuinely shines for XR. Laser tag in a shared virtual room.
To-scale planets you teleport between, with real NASA textures. Classic but always lands with first-time VR users. Good "show the family" demo.
Chess/checkers/card game on your real table (plane detection anchors the board). Hand-tracked piece grabbing. Add Claude API for an opponent that talks trash.
| Choice | Verdict |
|---|---|
| Three.js r184 + WebGLRenderer โ used here | The safe, stable core. Gotcha: the newer WebGPURenderer does not support XR on its WebGPU backend yet โ stick to WebGLRenderer for XR. |
| @pmndrs/xr / @react-three/xr v6 | The modern wrapper (full 2024 rewrite): one-liner sessions, default hand/controller models, pointer events on meshes. Worth adopting if demos grow; vanilla core needs no React. |
| Babylon.js 9 | Most batteries-included for deep MR โ plane/mesh detection, anchors, depth sensing are each one enableFeature() call. Pick it for the Portal Wall / Tabletop ideas if three.js plumbing gets annoying. |
Meta IWSDK (npm create @iwsdk@latest) | Meta's new (Sept 2025) opinionated three.js+ECS framework with physics, grab, locomotion, scene understanding built in. Young but the strongest scaffold for Quest-first projects. |
| IWER + @iwer/devui + @iwer/sem | Meta's WebXR emulator runtime: develop/test on the Mac in desktop Chrome, including synthetic Quest 3 rooms for passthrough/plane testing. Add when iteration speed matters. |
| Physics: @dimforge/rapier3d-compat | Rust/WASM, fast, TS-native, no COOP/COEP header hassles (WASM inlined). cannon-es is unmaintained; Havok belongs with Babylon. |
| UI: pmndrs/uikit | three-mesh-ui is dead โ uikit is the maintained spatial-UI lib (works vanilla or R3F). |
| A-Frame 1.7 | Alive (volunteer-paced), fine for HTML-first prototypes, but not the best fit for TS game loops. |
framebufferScaleFactor 1.2 (default undersamples the panel), foveation 0.5, local-floor reference space, transparent clear color in AR so passthrough shows through, haptics via XRInputSource.gamepad.hapticActuators.
All open directly in the Quest browser, no install, no login. These are also tap-able cards on the launcher index.
| Experience | What it is | Mode |
|---|---|---|
| Moon Rider | Free Beat Saber-style rhythm game, community songs | VR ยท controllers/hands |
| Above Par-adowski | WebXR Game of the Year mini-golf | VR ยท controllers |
| Flap Frenzy | Flap your arms to fly (Meta showcase) | VR ยท body input |
| Chairs Etc | Furniture placement in your real room | MR ยท hands+controllers |
| Sneaker Builder | Customize sneakers in passthrough | MR ยท hands |
| RealMeasure | Measure real furniture from inside the headset | MR ยท controllers |
| three.js Ball Shooter | Physics ball shooting in a grid room | VR ยท controllers |
| three.js XR Paint | Tilt-Brush-style 3D painting | VR ยท controllers |
| three.js AR Hit Test | Place objects on real surfaces (depth API) | MR ยท controllers |
| three.js Hand Cubes | Grab cubes with articulated hands | VR ยท hands |
| W3C WebXR Samples | Reference demos for every WebXR API feature | VR+MR |
| A-Painter | A-Frame's VR painting flagship | VR ยท controllers |
| A-Blast | Cute wave shooter | VR ยท controllers |
| Plockle | Spatial block-puzzle, 40+ levels | VR ยท controllers |
| Castle Builder | Multiplayer castle building, AR-capable | VR+MR |
| heyVR Arcade | Portal with dozens of no-install WebXR games | VR |
| PlayCanvas VR Lab | VR interaction patterns sandbox | VR ยท controllers+hands |
| VARTISTE | Full VR texture-painting art suite | VR ยท controllers |
Dropped during verification: Mozilla Hubs (shut down 2024 โ use FRAME), Silk Brush (domain dead), Project Flowerbed (WAF-blocked for bots; likely still fine in the headset).
| Asset | Source | License |
|---|---|---|
| Damaged Helmet (3.8 MB) | Khronos glTF-Sample-Assets | CC-BY (theblueturtle_) |
| Avocado (7.9 MB), Fox (159 KB, animated) | Khronos glTF-Sample-Assets | CC0 (Fox rig CC-BY) |
| Duck (118 KB) | Khronos glTF-Sample-Assets | SCEA Shared Source (attribution) |
| Horse, Flamingo (animated, <200 KB) | three.js examples (mirada, "3 Dreams of Black") | CC-BY |
| studio_small_03, venice_sunset HDRIs (1k) | Poly Haven | CC0 |
For future games: Kenney packs (kenney.nl โ Blaster Kit, Food Kit, Castle Kit, Space Kit, Nature Kit) are all CC0 with direct zip downloads and per-model GLBs of 10โ100 KB, perfect for Quest. Poly Haven 1K PBR textures follow the pattern dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/<slug>/<slug>_diff_1k.jpg (use _nor_gl_ normals for three.js). Quaternius models are CC0 but Google-Drive-only โ grab once via browser.
# dev server (desktop preview at http://localhost:5173)
npm run dev
# fastest headset iteration: USB-C cable + developer mode, then
adb reverse tcp:5173 tcp:5173
# โ open http://localhost:5173 in the Quest browser (secure-context exempt)
# typecheck + production build
npx tsc --noEmit && npx vite build
# ship it (~10 s)
npx wrangler pages deploy dist --project-name=quest3-playground --branch=main --commit-dirty=true
Each demo is an independent Vite page under demos/<name>/ โ copy any folder, add one line to vite.config.ts, and you have a new playground slot. The shared boilerplate lives in src/lib/xr.ts.