Edit: /opt/mawid/DEMO.md (5398B)
# Demo Setup — real WhatsApp from your laptop (no company, no server)
Goal: pitch Mawid to a clinic with a live demo — the clinic owner messages a
real WhatsApp number from their own phone, the AI books them an appointment,
and you show it landing on the dashboard calendar in real time.
Uses Meta's **free test number** (individual developer account, no business
verification, no payment method). Everything runs on your laptop; a tunnel
exposes the webhook.
## One-time setup (~45 min)
### 1. Meta developer app (no company needed)
1. developers.facebook.com → **My Apps → Create App** → type **Business**
(creating the app and a Business Portfolio needs no documents — the
portfolio can be named after yourself).
2. **Add product → WhatsApp → Set up** → Meta creates a test WhatsApp Business
Account + **free test phone number**.
3. From *WhatsApp → API Setup*, note:
- **Phone number ID** and **WABA ID**
- App Settings → Basic → **App secret**
4. Still in API Setup → **To** field → **Manage phone number list** → add up to
**5 recipient numbers** (your phone + the clinic owner's). Each gets an SMS
code. Only these numbers can chat with the test number — plenty for demos.
5. Token: the API-Setup token expires in 24h — fine for a first try, but for
demos create the permanent one now (GOLIVE.md §3.2, System User) so it
never dies mid-pitch.
### 2. Tunnel (public HTTPS → localhost)
ngrok's free plan includes one **static domain** — better than a random URL
because the Meta webhook config survives restarts:
```bash
brew install ngrok
ngrok config add-authtoken
# claim your free static domain in the ngrok dashboard, then:
ngrok http --domain=.ngrok-free.app 3001
```
Leave this running during demos. (Alternative: `cloudflared tunnel --url http://localhost:3001` — zero signup, but the URL changes every run and you must re-save the Meta webhook each time.)
### 3. Local env + restart
Create `.env` in the repo root (compose picks it up automatically):
```
WA_PHONE_NUMBER_ID=
WA_BUSINESS_ACCOUNT_ID=
WA_ACCESS_TOKEN=
WA_APP_SECRET=
WA_WEBHOOK_VERIFY_TOKEN=
OPENAI_API_KEY=
```
```bash
docker compose up -d api # restart with the new env
```
### 4. Point Meta at your tunnel
App dashboard → WhatsApp → **Configuration**:
- Callback URL: `https://.ngrok-free.app/webhooks/whatsapp`
- Verify token: your `WA_WEBHOOK_VERIFY_TOKEN` → **Verify and save**
- Webhook fields → subscribe to **messages**
### 5. Wire the demo clinic to the test number
```bash
docker compose exec -T postgres psql -U mawid -d mawid -c \
"UPDATE \"Clinic\" SET \"waPhoneNumberId\"='' WHERE name='Demo Dental Clinic';"
```
### 6. Templates (only needed for the reminder/waitlist part of the demo)
WhatsApp Manager → Message templates → create `appointment_reminder` and
`waitlist_offer` per GOLIVE.md §3.4 (test WABAs can create custom templates;
Utility templates usually approve in minutes). The AI chat itself needs no
templates — replies ride the 24h window the patient just opened.
### 7. Smoke test
WhatsApp the test number from your registered phone: *"Merhaba, yarın için
muayene randevusu almak istiyorum"* → the agent should reply with real slots.
Watch `docker compose logs -f api` and the dashboard **Conversations** page.
## Demo script (10 min pitch)
1. **Hook** — hand the owner your phone (or use theirs if registered): they
message the clinic in Turkish or Arabic, the AI answers in the same
language, offers real free slots, books one. No app, no forms.
2. **Dashboard** — flip to `localhost:3000`: the appointment is on the
calendar, the transcript is under Conversations, "take over" pauses the AI.
3. **The money slide** — reminders: show Settings → reminder offsets, explain
the T-24h/T-2h buttons + the unconfirmed-risk flag. If templates are
approved, pre-stage an appointment with short offsets so a real reminder
with ✅/❌/🔁 buttons arrives during the pitch.
4. **Waitlist** — cancel the booked slot from the phone (❌ button or chat):
the waitlisted patient (your second registered number) gets the offer with
a 20-minute hold; accept → slot refilled, owner notified.
5. Close with the weekly summary (dashboard card): "this is the report you
get on WhatsApp every Monday."
## Reset between demos
```bash
./scripts/demo-reset.sh +90XXXXXXXXXX # wipe one demo patient (GDPR delete)
```
Removes that phone's patient row, appointments, conversations and waitlist
entries via the API, so the next pitch starts from a blank chat. (WhatsApp
chat history on the phone: just delete the chat.)
## Gotchas
- Test numbers only talk to the 5 registered recipients — register the clinic
owner's phone *before* the meeting, the SMS verification takes a minute.
- The tunnel and `docker compose` stack must both be running; check
`https:///health` before walking in.
- If replies stop after ~24h token life, you used the temporary token —
switch to the System-User permanent token.
- Demo on hotel/clinic Wi-Fi: ngrok occasionally gets blocked on guest
networks; tether to your phone's hotspot as a fallback.