Your garage. In 3D. In the browser.
An interactive 3D virtual garage - arrange your car collection, walk around it in first person, switch between day, night, rain and studio lighting, and upload your own GLB models. No install, no plugins, just WebGL.
- About the Project
- Features
- Tech Stack
- Project Structure
- Installation and Setup
- Scripts
- Docker
- License
Vroomly is a client-only 3D web app built on React Three Fiber. It renders a garage scene with your vehicle collection, and lets you walk around, drive an orbit camera, or watch cars rotate from a fixed showroom angle - all in real time in the browser.
There is no backend: the garage layout (car positions, rotation, color, name) is persisted to localStorage, and any custom .glb model you upload is stored in IndexedDB so it survives page reloads without ever leaving your machine.
Rendering quality auto-adapts to the device - mobile, low-end, or high-end GPUs each get a tuned shadow/post-processing/particle-count profile so the scene stays smooth everywhere.
- 3D Garage Scene - Three vehicles rendered by default, arranged on a garage floor with realistic lighting and shadows, built with React Three Fiber and Drei.
- Multiple Camera Modes - Fixed garage view, orbit-style explore camera (auto-rotate or manual drag), first-person walk mode with WASD + mouse-look (and a virtual joystick on touch devices), and a top-down overhead view.
- Scene Presets & Weather - Switch between Day, Night (neon), Rain, and Studio (showroom) presets, plus a separate weather layer (clear, rain, snow, fog, storm) with matching particle/lighting effects.
- Vehicle Customization - Reposition, rotate, recolor, and rename any car from an inspector panel; reset any vehicle back to its default placement.
- Custom Model Upload - Drop in your own
.glbfile (up to 150 MB); it's stored locally in IndexedDB and placed in a safe zone on the garage floor, complete with a generated fallback model if it fails to load. - Persistent Local State - The full garage layout auto-saves to
localStorage(debounced) with a live save-status indicator, and can be reset back to the default 3 cars at any time. - Adaptive Performance Tiers - Detects device class (mobile / low / medium / high) from GPU renderer string, RAM, and CPU core count, then scales shadow map resolution, DPR, post-processing, and particle counts accordingly.
- Ambient Audio & UI Sound Feedback - Looping ambient garage audio plus short UI sound cues (select, toggle, error, etc.) with a persisted volume/mute preference.
- Responsive HUD - A glassmorphic top bar, side rail, drawers, and scene dock built with Tailwind, fully responsive down to mobile, with Framer Motion transitions throughout.
- Route-Level Loading Screen - A progress-driven intro screen that tracks real asset loading (via
@react-three/drei'suseProgress) instead of a fixed timeout, with rotating trivia while you wait.
| Layer | Technologies |
|---|---|
| Framework | React 19 · TypeScript (strict) · Vite 5 |
| 3D Rendering | Three.js · React Three Fiber · Drei · @react-three/postprocessing |
| Styling / Motion | Tailwind CSS 4 · Framer Motion |
| Storage | localStorage (garage layout) · IndexedDB via idb (uploaded models) |
| Tooling | ESLint 9 · @gltf-transform CLI (model optimization) |
| Deployment | Docker · Nginx |
vroomly/
├── public/
│ └── models/ # Optimized .glb assets (cars + garage props)
├── scripts/
│ └── optimize-models.mjs # gltf-transform pipeline for public/models
└── src/
├── app/ # App shell, global styles, entry point
├── pages/ # Top-level page (Garage)
├── components/
│ ├── camera/ # Camera rig + touch joystick controls
│ ├── car/ # Car model, thumbnail, loading placeholder
│ ├── common/ # Shared UI primitives (Section, Slider, ErrorBoundary...)
│ ├── environment/ # Garage room, lighting, weather, post-processing
│ ├── hud/ # Glassmorphic HUD (top bar, drawers, scene dock)
│ ├── layout/ # Settings panels, upload panel, intro screen
│ └── scene3d/ # Canvas root and scene composition
├── contexts/ # Camera, scene, garage, effects, audio, toast providers
├── hooks/ # Garage state, model loading, camera/scene modes
├── types/ # Shared TypeScript types (car data, UI state)
└── utils/ # Constants, IndexedDB model store, upload handling, quality tiers
- Node.js 18+ and npm
git clone <repository-url>
cd vroomly
npm install
npm run devThe app starts at http://localhost:5173 by default.
| Command | Description |
|---|---|
npm run dev |
Starts the Vite development server |
npm run build |
Type-checks with tsc -b and builds for production |
npm run preview |
Serves the production build locally |
npm run lint |
Runs ESLint over the project |
npm run optimize:models |
Optimizes .glb models with gltf-transform |
docker-compose up -d --buildBuilds the app and serves the static output behind Nginx (see Dockerfile, docker-compose.yml, and nginx.conf) on http://localhost:8080.