A furniture e-commerce storefront with 3D product previews, smooth scrolling, and an admin catalog.
Wood is a React app with a shop, product detail views, cart, wishlist, and admin tools for managing products and taxonomy. Product metadata lives in Supabase; images and 3D models are served from Cloudflare R2.
Live demo: wood-place.vercel.app
Frontend: React, Vite, Tailwind CSS, React Three Fiber, Three.js, GSAP, Framer Motion, Lenis
Backend: Supabase, Vercel serverless functions
Storage: Cloudflare R2
Maps: MapLibre GL
- Shop, product detail, cart, and wishlist flows
- Persistent Three.js scene for product previews
- GSAP scroll animations and Lenis smooth scrolling
- Route-level code splitting and shared product transitions
- Admin dashboard for products and taxonomy
- Supabase-backed catalog with R2 media storage
- Node.js 20+
- npm
- Supabase project
- Cloudflare R2 buckets for product media
git clone https://github.com/jvchi/wood.git
cd wood
npm installCopy .env.example to .env.local and fill in your Supabase and R2 values.
npm run devOpen http://localhost:5173.
npm run build
npm run previewRun supabase/admin_catalog.sql in the Supabase SQL editor before using /admin/products.
The schema creates catalog tables, upload tracking, inventory logs, public-read policies, and authenticated admin-only write policies.
Important
Admin routes require VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY. Product assets are stored in R2, not Supabase Storage.
Note
See docs/r2-migration.md for R2 setup, migration, verification, and cleanup.
src/
components/ # layout, shop UI, Three.js scene, admin views
context/ # cart, wishlist, toast, shared transitions
hooks/ # initial load and route helpers
lib/ # route preloaders and utilities
api/ # serverless handlers and R2 helpers
supabase/ # SQL schema and edge functions
docs/ # R2 migration runbook
public/ # static assets and favicon
Skills live in a private library so they do not clutter this public repo.
# after clone (requires gh auth as jvchi)
bash scripts/install-skills.shInstalls into .agents/skills/ (gitignored). Re-run to update.