C
prototypeAI & AgentsPosted 7h ago
Clawtable
Restaurant Booking Service
# CLAUDE.md
## Commands
```bash
npm run dev # Backend server (tsx watch, port 3000)
npm run dev:client # Frontend only (Vite, port 5173)
npm run build # TypeScript + frontend build
npm test # Vitest in watch mode
npm run test:run # Tests once (CI)
npm run lint # ESLint on src/
npm run db:generate # Generate Drizzle migrations
npm run db:migrate # Run migrations
npm run db:studio # Drizzle Studio (DB inspector)
npm run typecheck # Type-check only
```
## Architecture
ChatTable is an **agent-native restaurant booking platform** — a B2B SaaS where restaurants pay to accept bookings from AI agents. The ChatGPT Action is the first agent channel.
### Two-Sided Platform
**Agent Side** (`/v1/*`):
- ChatGPT Action (OpenAPI 3.1.0 spec in `docs/openapi.yaml`)
- Authenticated via API key (`ct_live_...` prefix) or OAuth 2.0
- Returns status-based responses: `confirmed | alternatives | pending_deposit | pending_merchant | incomplete | disambiguation_needed | failed`
**Merchant Side** (`/merchant/*`):
- Dashboard (React SPA in `frontend/`)
- Two booking modes:
- **AI Host** (default): Rules-based engine auto-handles requests (checks hours, tables, deposits, auto-confirms)
- **Webhook**: Forwards requests to merchant's POS/system via HMAC-signed webhooks
### Key Components
- `src/booking/engine.ts` — BookingEngine: resolves merchant, routes to direct channel or fallback
- `src/booking/direct-channel.ts` — Direct booking for onboarded restaurants
- `src/availability/checker.ts` — Rules-based availability engine (AI Host logic)
- `src/agent-api/routes.ts` — Agent-facing Fastify routes (ChatGPT Action endpoints)
- `src/merchant-api/routes.ts` — Merchant dashboard API
- `src/webhook/dispatcher.ts` — Outbound webhook dispatch with HMAC signing
- `src/webhook/receiver.ts` — Inbound webhook responses from merchant systems
- `src/auth/middleware.ts` — Agent auth (API key) + Merchant auth (JWT)
- `src/auth/oauth.ts` — OAuth 2.0 Authorization Code flow for ChatGPT
- `src/billing/usage.ts` — Per-booking billing and usage tracking
### Database
SQLite + Drizzle ORM. Schema in `src/db/schema.ts`:
- `merchants` — Restaurant profiles, settings (JSON), subscription tier
- `operatingHours` — Per-day open/close/last seating times
- `tableInventory` — Tables with min/max covers, seating type
- `bookings` — Reservations from any agent channel
- `agentChannels` — Registered agents (ChatGPT, OpenClaw, custom)
- `webhookConfigs` — Merchant webhook endpoints
- `webhookDeliveries` — Delivery audit trail
- `billingRecords` — Per-booking and subscription charges
- `availabilityOverrides` — Block/release slots
### Booking Flow
1. Agent calls `POST /v1/bookings/create` with restaurant + date/time/party/guest info
2. BookingEngine resolves merchant (by slug, ID, or name)
3. If onboarded + AI Host: AvailabilityChecker evaluates → auto-confirm or return alternatives/deposit
4. If onboarded + Webhook: Create pending booking → dispatch to merchant → agent polls for result
5. If not onboarded: Fallback to external platforms (ClawTable channels — TODO)
### Subscription Tiers
- **Starter** ($0/mo): 50 included bookings, $0.99/overage
- **Growth** ($79/mo): 500 included, $0.49/overage, webhook integration
- **Enterprise** ($249/mo): Unlimited, dedicated support
### Railway Deployment
Deployed via Docker on Railway with a persistent SQLite volume.
```bash
# Deploy to Railway
railway up
# Or link repo for auto-deploy on push
railway link
```
**Required Railway env vars:**
- `JWT_SECRET` — generate with `openssl rand -hex 32`
- `NODE_ENV=production`
**Railway volume:** Mounted at `/data` for SQLite persistence (`/data/chattable.db`).
**Config files:**
- `Dockerfile` — multi-stage build (builder → production)
- `railway.toml` — Railway-specific: Dockerfile builder, health check at `/health`, volume at `/data`
- `.dockerignore` — excludes node_modules, .git, .env
**ChatGPT Action setup:**
After deploy, use your Railway URL (e.g. `https://chattable-production.up.railway.app`) as the server URL in `docs/openapi.yaml`, then import that spec into the ChatGPT GPT editor.