A modern WhatsApp Business Platform built with Go (Fastglue) and Vue.js (shadcn-vue).
- Multi-tenant Architecture: Support multiple organizations with isolated data
- Role-Based Access Control: Three roles (Admin, Manager, Agent) with granular permissions
- WhatsApp Cloud API Integration: Connect with Meta's WhatsApp Business API
- Real-time Chat: Live messaging with WebSocket support
- Template Management: Create and manage message templates
- Bulk Messaging: Send campaigns to multiple contacts with retry support for failed messages
- Chatbot Automation:
- Keyword-based auto-replies
- Conversation flows with branching logic and skip conditions
- AI-powered responses (OpenAI, Anthropic, Google)
- Agent transfer support
- Canned Responses: Pre-defined quick replies for agents
- Organization-wide shared responses
- Category-based organization (Greetings, Support, Sales, etc.)
- Slash command support (type
/shortcutin chat) - Dynamic placeholders (
{{contact_name}},{{phone_number}})
- Analytics Dashboard: Track messages, engagement, and campaign performance
Click to view screenshots
- Go 1.21+ with Fastglue (fasthttp-based HTTP framework)
- PostgreSQL for data storage with GORM v2
- Redis for caching, pub/sub, and job queues (Redis Streams)
- JWT for authentication
- Worker Service for reliable campaign processing
- Vue 3 with Composition API and TypeScript
- Vite for build tooling
- shadcn-vue / Radix Vue for UI components
- TailwindCSS for styling
- Pinia for state management
- Vue Query for server state
whatomate/
├── cmd/
│ ├── server/ # Main application entry point
│ └── worker/ # Standalone worker entry point
├── internal/
│ ├── config/ # Configuration management
│ ├── database/ # Database connections
│ ├── handlers/ # HTTP handlers
│ ├── middleware/ # HTTP middleware
│ ├── models/ # Data models
│ ├── queue/ # Redis Streams job queue
│ ├── services/ # Business logic
│ └── worker/ # Worker service for job processing
├── docker/ # Docker configuration
├── frontend/ # Vue.js frontend
│ ├── src/
│ │ ├── components/ # UI components
│ │ ├── views/ # Page views
│ │ ├── stores/ # Pinia stores
│ │ ├── services/ # API services
│ │ └── lib/ # Utilities
│ └── ...
├── config.example.toml # Example configuration
├── Makefile # Build commands
└── README.md
- Go 1.21+
- Node.js 18+
- PostgreSQL 14+
- Redis 6+
- Docker & Docker Compose (optional)
-
Clone and configure:
cd whatomate cp config.example.toml config.toml # Edit config.toml with your settings
-
Start backend:
# Install dependencies go mod download # Run database migrations make migrate # Start the server (includes 1 embedded worker by default) make run # Or run with more workers for higher throughput go run cmd/server/main.go -workers=3 # Or disable embedded workers (run workers separately) go run cmd/server/main.go -workers=0
-
Start frontend:
cd frontend npm install npm run dev
# Build Docker images
make docker-build
# Start all services (PostgreSQL, Redis, Server, Worker)
make docker-upAccess the application at http://localhost:3000 or http://localhost (port 80 via nginx)
# Stop all services
make docker-down
# View logs
make docker-logs
# Rebuild and restart
make docker-build && make docker-upFor high-volume campaign processing, you can scale the worker service:
cd docker
docker compose up -d --scale worker=3Workers use Redis Streams consumer groups, ensuring each job is processed by exactly one worker.
When you run migrations for the first time, a default admin user is created:
- Email:
admin@admin.com - Password:
admin
Important: Change this password immediately after first login via the Profile page.
Copy config.example.toml to config.toml and update the values:
[app]
name = "Whatomate"
environment = "development"
debug = true
[server]
host = "0.0.0.0"
port = 8080
[database]
host = "localhost"
port = 5432
user = "whatomate"
password = "your-password"
name = "whatomate"
ssl_mode = "disable"
[redis]
host = "localhost"
port = 6379
password = ""
db = 0
[jwt]
secret = "your-jwt-secret"
access_token_expiry = "15m"
refresh_token_expiry = "7d"
[whatsapp]
api_version = "v18.0"
webhook_verify_token = "your-webhook-verify-token"
[ai]
openai_api_key = ""
anthropic_api_key = ""
google_api_key = ""The worker service handles bulk campaign message processing using Redis Streams for reliable job queuing.
┌─────────────┐ Redis Streams ┌─────────────┐
│ Server │ ─────────────────────► │ Worker 1 │
│ (enqueue) │ whatomate:campaigns ├─────────────┤
└─────────────┘ │ │ Worker 2 │
└─────────────►│ Worker N │
└─────────────┘
- Reliable Processing: Jobs persist in Redis until acknowledged
- Horizontal Scaling: Add more workers to increase throughput
- Graceful Shutdown: Workers complete current job before stopping
- Automatic Recovery: Stale jobs are reclaimed on worker startup
Embedded Mode (default): The server runs workers internally.
# Default: 1 worker
./whatomate
# Run with 3 embedded workers
./whatomate -workers=3
# Disable embedded workers (use standalone workers only)
./whatomate -workers=0Standalone Mode: Run workers as separate processes.
# Run standalone worker (1 worker)
go run cmd/worker/main.go
# Run with multiple workers
go run cmd/worker/main.go -workers=5
# Or with Docker Compose
docker compose up -d --scale worker=3Workers can be added dynamically without restarting the server. Since all workers consume from the same Redis Stream consumer group, new workers immediately start processing queued jobs.
# Server running with 1 embedded worker
go run cmd/server/main.go -workers=1
# In another terminal, add 5 more workers
go run cmd/worker/main.go -workers=5
# Add even more workers if needed
go run cmd/worker/main.go -workers=10This is useful for:
- Burst processing: Scale up workers during high-volume campaigns
- Zero-downtime scaling: Add capacity without interrupting the server
- Resource optimization: Run workers on different machines
POST /api/auth/register- Register new userPOST /api/auth/login- LoginPOST /api/auth/refresh- Refresh tokenPOST /api/auth/logout- Logout
GET /api/accounts- List accountsPOST /api/accounts- Create accountPUT /api/accounts/:id- Update accountDELETE /api/accounts/:id- Delete account
GET /api/users- List usersPOST /api/users- Create userGET /api/users/:id- Get userPUT /api/users/:id- Update userDELETE /api/users/:id- Delete user
GET /api/contacts- List contacts (agents see only assigned)POST /api/contacts- Create contactPUT /api/contacts/:id/assign- Assign contact to agentGET /api/contacts/:id/messages- Get messagesPOST /api/contacts/:id/messages- Send message
GET /api/templates- List templatesPOST /api/templates/sync- Sync from Meta
GET /api/campaigns- List campaignsPOST /api/campaigns- Create campaignGET /api/campaigns/:id- Get campaign detailsPUT /api/campaigns/:id- Update campaignDELETE /api/campaigns/:id- Delete campaignPOST /api/campaigns/:id/start- Start campaign (queues for processing)POST /api/campaigns/:id/pause- Pause campaignPOST /api/campaigns/:id/cancel- Cancel campaignPOST /api/campaigns/:id/retry-failed- Retry failed messagesGET /api/campaigns/:id/stats- Get campaign statisticsGET /api/campaigns/:id/recipients- List recipientsPOST /api/campaigns/:id/recipients/import- Import recipients
GET /api/flows- List flowsPOST /api/flows- Create flowGET /api/flows/:id- Get flowPUT /api/flows/:id- Update flowDELETE /api/flows/:id- Delete flowPOST /api/flows/:id/save-to-meta- Save/update flow on MetaPOST /api/flows/:id/publish- Publish flow on MetaPOST /api/flows/:id/deprecate- Deprecate flowPOST /api/flows/sync- Sync flows from Meta
GET /api/chatbot/settings- Get settingsPUT /api/chatbot/settings- Update settingsGET /api/chatbot/keywords- List keyword rulesGET /api/chatbot/flows- List flowsGET /api/chatbot/ai-contexts- List AI contexts
GET /api/canned-responses- List canned responsesPOST /api/canned-responses- Create canned responseGET /api/canned-responses/:id- Get canned responsePUT /api/canned-responses/:id- Update canned responseDELETE /api/canned-responses/:id- Delete canned responsePOST /api/canned-responses/:id/use- Track usage
GET /api/webhook- Webhook verificationPOST /api/webhook- Receive messages
The platform supports three user roles with different permission levels:
| Feature | Admin | Manager | Agent |
|---|---|---|---|
| User Management | Full | None | None |
| Account Settings | Full | Full | None |
| Contacts | Full | Full | Assigned only |
| Messages | Full | Full | Assigned only |
| Templates | Full | Full | None |
| Flows | Full | Full | None |
| Campaigns | Full | Full | None |
| Chatbot Settings | Full | Full | None |
| Canned Responses | Full | Full | Use only |
| Analytics | Full | Full | None |
- Admin: Full access to all features including user management
- Manager: Full access except cannot manage users
- Agent: Can only chat with contacts assigned to them
Conversation flows allow you to create multi-step automated conversations that collect information from users.
Each step can have an optional skip condition that determines whether to skip the step based on previously collected data. If the condition evaluates to true, the step is skipped and the flow proceeds to the next step.
| Operator | Description | Example |
|---|---|---|
== |
Equals | status == 'confirmed' |
!= |
Not equals | phone != '' (not empty) |
> |
Greater than | amount > 1000 |
< |
Less than | age < 18 |
>= |
Greater or equal | count >= 5 |
<= |
Less or equal | score <= 100 |
AND |
All conditions must be true | name != '' AND phone != '' |
OR |
Any condition can be true | status == 'vip' OR amount > 1000 |
() |
Grouping | (status == 'vip' OR amount > 100) AND name != '' |
# Skip if phone already collected
phone != ''
# Skip if both name and email are provided
name != '' AND email != ''
# Skip for VIP users or high-value orders
status == 'vip' OR amount > 1000
# Complex condition with grouping
(status == 'vip' OR amount > 100) AND name != ''
When a user clicks a button, two variables are stored:
{store_as}- The button ID (e.g.,btn_1){store_as}_title- The button text (e.g.,Yes)
To check the button text in skip conditions, use the _title suffix:
# Check button text
choice_title == 'Yes'
# Check button ID
choice == 'btn_yes'
# Check if any button was clicked (not empty)
choice != ''
- Create a Meta Developer account at developers.facebook.com
- Create a new app and add the WhatsApp product
- Get your Phone Number ID and Business Account ID
- Generate a permanent access token
- Configure the webhook URL to point to
/api/webhook - Set the webhook verify token in your configuration
See LICENSE for details. Free to use and distribute.















