A real-time food ordering and delivery platform with three role views — Customer, Restaurant, and Driver — connected live via Socket.io.
pnpm --filter @workspace/api-server run dev— run the API server (port 8080)pnpm --filter @workspace/bytebite run dev— run the frontend (port 18763)pnpm run typecheck— full typecheck across all packagespnpm run build— typecheck + build all packagespnpm --filter @workspace/api-spec run codegen— regenerate API hooks and Zod schemas from the OpenAPI specpnpm --filter @workspace/db run push— push DB schema changes (dev only)- Required env:
DATABASE_URL— Postgres connection string - Optional env:
STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET— for real Stripe payments (falls back to simulated checkout if not set)
- pnpm workspaces, Node.js 24, TypeScript 5.9
- Frontend: React + Vite, Tailwind CSS, Framer Motion, Socket.io-client, Zustand
- API: Express 5 + Socket.io
- DB: PostgreSQL + Drizzle ORM
- Validation: Zod (
zod/v4),drizzle-zod - API codegen: Orval (from OpenAPI spec)
- Build: esbuild (CJS bundle)
lib/api-spec/openapi.yaml— single source of truth for all API contractslib/db/src/schema/— Drizzle table definitions (restaurants.ts, orders.ts)artifacts/api-server/src/routes/— route handlers (menu, orders, drivers, checkout)artifacts/api-server/src/socket/— Socket.io event emittersartifacts/bytebite/src/— React frontend (pages/, components/, hooks/, lib/)
- Socket.io at
/ws/socket.iopath (listed in api-server artifact.toml paths array so the proxy forwards it) - Cart state managed in Zustand with localStorage persistence
- Role switcher (Customer / Restaurant / Driver) stored in Zustand — no auth required
- Stripe checkout is optional: if
STRIPE_SECRET_KEYis not set, the server simulates a successful payment and marks the order as paid - Orders use
jsonbcolumn for items array (avoids a separate order_items join table for simplicity)
- Customer: Browse Ember & Co. menu by category, add to cart, checkout with name + address, live order status tracker
- Restaurant: Stats dashboard (order counts by status + revenue), incoming orders board, one-click status progression (Accept → Cooking → Ready)
- Driver: Available pickups (orders with status "ready"), accept with driver name, mark as delivered
- Real-time: Every status change broadcasts via Socket.io and instantly updates all connected role views
Populate as you build — explicit user instructions worth remembering across sessions.
- The
/wspath MUST be inartifacts/api-server/.replit-artifact/artifact.tomlpaths array — without it the proxy drops WebSocket connections silently - The API server uses
http.createServer(app)+ Socket.io (notapp.listendirectly) so Socket.io can attach to the same port - After schema changes: run
pnpm --filter @workspace/db run pushthen restart the API server workflow - Orval body schema names must be entity-shaped (not
<OperationId>Body) to avoid TS2308 collisions
- See the
pnpm-workspaceskill for workspace structure, TypeScript setup, and package details