Skip to content

Stage 5a: MiniWhatsApp β€” Local Test Harness πŸ“± ​

A standalone WhatsApp-lookalike web app that talks to Orbita over HTTP + WebSocket, so we can iterate on real external messaging without touching Meta's API.

Status: βœ… Complete Lives at: /Users/sajithmr/1box/miniwhatsapp/ (sibling project, NOT inside orbita-core) Plugin: orbita-core/plugins/whatsapp-mock.plugin.tsPort: 4000 (miniwhatsapp) ↔ 3210 (orbita)

Why This Exists ​

The hardest part of "real WhatsApp" is iteration speed. You can't fluently debug Meta's Business API β€” slow approvals, template rules, 24-hour windows, webhooks behind public URLs. So we built a pretend WhatsApp that speaks the same shape:

  • Users register with a phone number (any string, no OTP)
  • Send messages browser-to-browser via WebSocket
  • Orbita sends outbound via POST /api/send
  • Orbita receives inbound via webhook POST /wa-webhook

Swap the plugin's URL later β†’ real WhatsApp works. Core unchanged.

Architecture ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  MiniWhatsApp :4000 │◄────WS─►│  Browser chats        β”‚
β”‚  - server.ts        β”‚         β”‚  - public/index.html  β”‚
β”‚  - data.json (disk) β”‚         β”‚  - public/admin.html  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β”‚ POST /wa-webhook    (inbound message)
           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Orbita :3210       β”‚
β”‚  - whatsapp-mock    │──── watches matching inboxes
β”‚    .plugin.ts       │──── POST /api/send (outbound)
β”‚  - InboxManager     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Endpoints (miniwhatsapp side) ​

MethodPathWho calls itPurpose
POST/api/sendOrbita pluginPush outbound message (Orbita β†’ a user)
GET/api/usersAnyoneList registered users
GET/api/messagesBrowser UIHistory for current thread
WS/Browser UILive inbound/outbound events
GET/BrowserChat UI (public/index.html)
GET/admin.htmlBrowserContact admin UI

Endpoints (orbita side) ​

MethodPathWho calls itPurpose
POST/wa-webhookminiwhatsapp serverForward incoming browser message into agent's inbox

The Plugin (whatsapp-mock.plugin.ts) ​

Lives in orbita-core/plugins/ and implements the Plugin API from Stage 4b:

typescript
// Maintains a contact book: agentName β†’ phone number
// (stored in its own MongoDB collection, NOT in core)

watch(inbox):
  if inboxMsg.toAgent has a phone number mapping:
    POST http://localhost:4000/api/send
         { to: phone, text: formatMessage(inboxMsg) }

onWebhook("/wa-webhook"):
  resolve phone β†’ agentName via contact book
  inbox.send("whatsapp-mock", agentName, "external_message", {...})

The plugin OWNS the phone↔agent mapping. The core never sees phone numbers.

Running It ​

bash
# Terminal 1 β€” Orbita core
cd orbita-core
npm start                    # port 3210

# Terminal 2 β€” MiniWhatsApp
cd ../miniwhatsapp
npm start                    # port 4000

# Browsers:
# http://localhost:4000/           β€” chat as any user
# http://localhost:4000/admin.html β€” manage contacts
# http://localhost:3210/talk       β€” chat with Axiom

Open multiple incognito windows to simulate multiple people.

Why admin.html exists ​

Initial plan was curl-driven contact management. Multi-line curl in zsh kept biting us with quoting. The admin page is a visual form for:

  • Register a new user (name + phone)
  • Map agent name β†’ phone (this is the plugin's contact book)
  • Simulate inbound messages (for testing without a second browser)

What this unblocks ​

  • Full end-to-end external messaging with zero Meta dependency
  • Any number of concurrent "users" (one per browser window)
  • Real HTTP + WebSocket transport (no in-memory shortcuts that lie about concurrency)
  • Confidence that the Plugin API genuinely handles external systems
  • Real WhatsApp is now just a new plugin with the same shape

Not Implemented (by design) ​

  • ❌ Authentication (any name/number accepted β€” it's a dev tool)
  • ❌ Message encryption
  • ❌ Media messages (text-only)
  • ❌ Templates / 24h windows (those are Meta-specific)
  • ❌ Delivery receipts beyond "received by server"

These belong in 5b-whatsapp (real Meta plugin).

Orbita β€” We don't build software. We grow organisms.