# The Vibe — Fair-Trade Delivery Platform > Flat-fee food delivery for the Greater Toronto Area. > No commissions. No exploitation. Restaurants keep 100% of profits. --- ## Quick Start ```bash # 1. Copy env and fill in your keys cp .env.example .env # 2. Start PostgreSQL/PostGIS + Redis npm run docker:up # 3. Install all dependencies npm install # 4. Start backend + frontend npm run dev ``` Backend: http://localhost:3001 Frontend: http://localhost:3000 PgAdmin: http://localhost:5050 (after `docker-compose --profile dev up`) --- ## Project Structure ``` The_Vibe/ ├── packages/ │ ├── database/ │ │ ├── schema.sql # Full PostgreSQL + PostGIS schema │ │ └── seed.sql # GTA zones + dev data │ ├── backend/ # NestJS API (port 3001) │ │ └── src/ │ │ ├── modules/ │ │ │ ├── auth/ # JWT auth, roles guard │ │ │ ├── drivers/ # Sessions, break-even algorithm │ │ │ ├── restaurants/ # Menu, savings dashboard │ │ │ ├── orders/ # Full order lifecycle │ │ │ ├── payments/ # Stripe subscriptions + daily fee │ │ │ ├── tracking/ # Socket.IO real-time gateway │ │ │ ├── zones/ # GTA PostGIS geofencing │ │ │ ├── menu/ # Menu CRUD │ │ │ └── admin/ # Platform analytics │ │ └── database/ # pg Pool + transaction helper │ └── web/ # Next.js 14 frontend (port 3000) │ └── src/ │ ├── app/ │ │ ├── page.tsx # Landing page │ │ ├── restaurants/page.tsx # Browse + map │ │ ├── orders/[id]/track/ # Real-time order tracking │ │ ├── driver/dashboard/ # Break-even dashboard │ │ ├── restaurant/dashboard/ # Savings dashboard │ │ └── admin/page.tsx # Platform admin │ ├── components/ │ │ └── map/MapView.tsx # MapLibre GL JS │ ├── hooks/ │ │ └── useDriverTracking.ts # GPS + Socket.IO │ └── lib/ │ ├── api.ts # Axios client │ └── osrm.ts # OSRM routing client └── docker-compose.yml ``` --- ## Pricing Model | Stakeholder | Model | Amount | |---|---|---| | Restaurant | Monthly subscription | $500/month | | Restaurant | Per-order fee | $0.10/order | | Restaurant | CC processing (Stripe) | 2.9% + $0.30 | | Driver | Daily access fee | $20/day | | Driver | Delivery fee | $5 per delivery (kept 100%) | | Driver | Tips | 100% kept | | Customer | Delivery fee | $5 flat | | Customer | Hidden fees | $0 | ### Driver Break-Even - 4 deliveries × $5 = $20 → break even - Every delivery after #4 = pure profit - Tips never counted against break-even ### Restaurant Savings Example (100 orders/day) - UberEats at 30% on $35 avg: **$31,500/month** - The Vibe: $500 + $300 + CC ≈ **$3,400/month** - **Savings: ~$28,000/month** --- ## API Endpoints ### Auth ``` POST /api/v1/auth/register POST /api/v1/auth/login GET /api/v1/auth/me ``` ### Restaurants ``` GET /api/v1/restaurants?lng=&lat=&radius=&cuisine= GET /api/v1/restaurants/savings-calculator?orders=&avgValue= GET /api/v1/restaurants/:slug POST /api/v1/restaurants (restaurant_owner) GET /api/v1/restaurants/dashboard/savings (restaurant_owner) ``` ### Orders ``` POST /api/v1/orders (customer) GET /api/v1/orders/mine (customer) GET /api/v1/orders/:id PATCH /api/v1/orders/:id/confirm (restaurant_owner) PATCH /api/v1/orders/:id/ready (restaurant_owner) PATCH /api/v1/orders/:id/pickup (driver) PATCH /api/v1/orders/:id/delivered (driver) ``` ### Drivers ``` GET /api/v1/drivers/me/session POST /api/v1/drivers/me/session/start POST /api/v1/drivers/me/session/end PATCH /api/v1/drivers/me/location GET /api/v1/drivers/nearby?lng=&lat= ``` ### Payments (Stripe) ``` POST /api/v1/payments/restaurant/subscribe POST /api/v1/payments/driver/daily-fee POST /api/v1/payments/driver/payment-method POST /api/v1/payments/orders/:orderId/intent POST /api/v1/payments/webhook ``` ### Zones (GTA Geofencing) ``` GET /api/v1/zones GET /api/v1/zones/geojson # GeoJSON FeatureCollection GET /api/v1/zones/check?lng=&lat= ``` ### Admin ``` GET /api/v1/admin/stats GET /api/v1/admin/revenue?days=30 GET /api/v1/admin/restaurants GET /api/v1/admin/drivers PATCH /api/v1/admin/drivers/:id/approve ``` --- ## Map Stack - **MapLibre GL JS** — open-source map renderer (browser) - **OpenStreetMap** tiles via MapTiler (free tier) - **OSRM** — self-hosted routing engine (ontario-latest.osm.pbf) - **PostGIS** — geofencing, spatial queries, driver proximity ### GTA Zones (active at launch) 1. Downtown Toronto (priority 10) 2. Liberty Village (priority 9) 3. North York (priority 8) 4. Scarborough (priority 7) 5. Mississauga (priority 6) --- ## Real-Time Architecture ``` Driver App Socket.IO Gateway Customer App │ │ │ ├─ emit driver:location ──► │ │ ├─ emit driver:moved ────►│ │ │ │ │ ◄── emit join:order ──────┤ │ │ │ │ Orders Service │ │ ◄── order:new ────────────┤ │ ├─ emit to restaurant room │ ``` Driver location updates every 5 seconds via WebSocket. DB breadcrumbs written to `delivery_tracking` table. --- ## Environment Variables Required See `.env.example` for full list. Key ones: - `DATABASE_URL` — PostgreSQL + PostGIS connection string - `STRIPE_SECRET_KEY` — Stripe API key - `STRIPE_RESTAURANT_PRICE_ID` — $500/month Price ID in Stripe - `JWT_SECRET` — random secret, min 32 chars - `NEXT_PUBLIC_MAPTILER_KEY` — free MapTiler account for OSM tiles --- ## Performance Targets | Metric | Target | |---|---| | Restaurants | 1,000+ | | Active drivers | 5,000 | | Orders/day | 50,000 | | Location updates/sec | ~50,000 (drivers × 0.2hz) | | DB connections | max 20 (pg pool) | Scale path: Redis adapter for Socket.IO → horizontal Node scaling → Postgres read replicas.