---
name: whatsapp-business-platform
description: Build WhatsApp Business API platforms with SvelteKit frontend, Go/Fiber backend, OAuth integration, Docker deployment, and Cloudflare tunneling. Use when creating messaging platforms, WhatsApp Business integrations, multi-tenant SaaS messaging solutions, or customer communication platforms.
---

# WhatsApp Business Platform

Build production-ready WhatsApp Business API platforms using proven architecture patterns.

## When to Use

- Building WhatsApp Business API integrations
- Creating messaging platforms or CRM systems
- Multi-tenant SaaS messaging solutions
- Customer communication dashboards
- E-commerce messaging automation

## Architecture Pattern

**Frontend:** SvelteKit (TypeScript)
**Backend:** Go with Fiber framework  
**Database:** PostgreSQL + Redis
**Deployment:** Docker + Cloudflare Tunnel
**Authentication:** OAuth (Google/Facebook) + JWT
**Domain Routing:** Landing page + app subdomain

## Quick Start

1. **Initialize Project Structure**
```bash
mkdir my-messaging-platform && cd my-messaging-platform
mkdir -p {backend/{cmd/api,internal/{config,database,handlers,middleware,services,storage,queue}},frontend/src/{lib,routes,hooks},docs,assets}
```

2. **Backend Setup (Go/Fiber)**

Create `backend/cmd/api/main.go`:
```go
package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"

    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/cors"
    "github.com/gofiber/fiber/v2/middleware/helmet"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/gofiber/fiber/v2/middleware/recover"
    "github.com/joho/godotenv"
)

func main() {
    if err := godotenv.Load(); err != nil {
        log.Println("No .env file found")
    }

    app := fiber.New(fiber.Config{
        ServerHeader: "WhatsApp Platform API",
        AppName:      "WhatsApp Business Platform v1.0",
    })

    // Middleware
    app.Use(cors.New(cors.Config{
        AllowOrigins: os.Getenv("ALLOWED_ORIGINS"),
        AllowHeaders: "Origin, Content-Type, Accept, Authorization",
    }))
    app.Use(helmet.New())
    app.Use(logger.New())
    app.Use(recover.New())

    // Routes
    app.Get("/health", func(c *fiber.Ctx) error {
        return c.JSON(fiber.Map{"status": "ok"})
    })

    // API routes
    api := app.Group("/api/v1")
    api.Post("/webhooks/whatsapp", handleWhatsAppWebhook)
    api.Post("/auth/google/callback", handleGoogleCallback)
    api.Post("/auth/facebook/callback", handleFacebookCallback)

    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    log.Printf("Server starting on port %s", port)
    if err := app.Listen(":" + port); err != nil {
        log.Fatalf("Failed to start server: %v", err)
    }
}
```

3. **Frontend Setup (SvelteKit)**

Create `frontend/src/hooks.server.ts` for domain routing:
```typescript
import type { Handle } from '@sveltejs/kit';
import { redirect } from '@sveltejs/kit';

const LANDING_PATHS = ['/', '/docs', '/pricing', '/contact'];
const APP_PATHS = ['/login', '/register', '/dashboard', '/inbox', '/contacts', '/settings'];

export const handle: Handle = async ({ event, resolve }) => {
  const hostname = event.url.hostname;
  const pathname = event.url.pathname;
  
  const isLandingDomain = hostname === 'yourdomain.com' || hostname === 'www.yourdomain.com';
  const isAppDomain = hostname === 'app.yourdomain.com';
  
  if (isLandingDomain) {
    const isAppPath = APP_PATHS.some(p => pathname === p || pathname.startsWith(p + '/'));
    if (isAppPath) {
      throw redirect(302, 'https://app.yourdomain.com' + pathname + event.url.search);
    }
  }
  
  if (isAppDomain) {
    const isLandingPath = LANDING_PATHS.some(p => pathname === p || pathname.startsWith(p + '/'));
    if (isLandingPath && pathname !== '/') {
      throw redirect(302, 'https://yourdomain.com' + pathname + event.url.search);
    }
    if (pathname === '/') {
      throw redirect(302, 'https://app.yourdomain.com/login');
    }
  }

  const response = await resolve(event);
  response.headers.set('X-Frame-Options', 'SAMEORIGIN');
  response.headers.set('X-Content-Type-Options', 'nosniff');
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
  return response;
};
```

4. **Environment Configuration**

Create `backend/.env.example`:
```bash
# Server
ENVIRONMENT=development
PORT=8080

# Database
DATABASE_URL=postgres://postgres:postgres@localhost:5432/messaging_platform?sslmode=disable

# JWT
JWT_SECRET=your-super-secret-jwt-key-min-32-chars-here
JWT_EXPIRY=15m
JWT_REFRESH_EXPIRY=168h

# OAuth - Google
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=https://app.yourdomain.com/auth/google/callback

# OAuth - Facebook
FACEBOOK_APP_ID=your-facebook-app-id
FACEBOOK_APP_SECRET=your-facebook-app-secret
FACEBOOK_REDIRECT_URI=https://app.yourdomain.com/auth/facebook/callback

# WhatsApp Business API
META_ACCESS_TOKEN=your-meta-access-token
WEBHOOK_VERIFY_TOKEN=your-webhook-verify-token
WHATSAPP_PHONE_NUMBER_ID=your-phone-number-id

# CORS
ALLOWED_ORIGINS=https://yourdomain.com,https://app.yourdomain.com

# Redis
REDIS_ADDR=localhost:6379
REDIS_PASSWORD=
REDIS_DB=0
```

5. **Docker Configuration**

Create `docker-compose.yml`:
```yaml
version: '3.8'

services:
  backend:
    build: ./backend
    container_name: messaging-backend
    restart: unless-stopped
    ports:
      - "127.0.0.1:8084:8080"
    environment:
      - PORT=8080
      - TZ=Asia/Jakarta
    env_file:
      - backend/.env
    networks:
      - messaging-network
    depends_on:
      - db
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  frontend:
    build: ./frontend  
    container_name: messaging-frontend
    restart: unless-stopped
    ports:
      - "127.0.0.1:3002:3000"
    environment:
      - NODE_ENV=production
    networks:
      - messaging-network

  db:
    image: postgres:15
    container_name: messaging-db
    restart: unless-stopped
    ports:
      - "127.0.0.1:5434:5432"
    environment:
      - POSTGRES_DB=messaging_platform
      - POSTGRES_USER=postgres  
      - POSTGRES_PASSWORD=postgres
    volumes:
      - messaging_db_data:/var/lib/postgresql/data
    networks:
      - messaging-network

  redis:
    image: redis:7-alpine
    container_name: messaging-redis
    restart: unless-stopped
    ports:
      - "127.0.0.1:6379:6379"
    volumes:
      - messaging_redis_data:/data
    networks:
      - messaging-network

networks:
  messaging-network:
    driver: bridge

volumes:
  messaging_db_data:
  messaging_redis_data:
```

## Meta WhatsApp Business API Setup

1. **Create Meta App**
   - Go to Meta for Developers
   - Create new app → Business
   - Add WhatsApp product

2. **Configure Webhooks**
```go
func handleWhatsAppWebhook(c *fiber.Ctx) error {
    // Webhook verification
    if c.Query("hub.verify_token") == os.Getenv("WEBHOOK_VERIFY_TOKEN") {
        return c.SendString(c.Query("hub.challenge"))
    }

    // Handle incoming messages
    var payload WebhookPayload
    if err := c.BodyParser(&payload); err != nil {
        return c.Status(400).JSON(fiber.Map{"error": "Invalid payload"})
    }

    // Process messages asynchronously
    go processWhatsAppMessage(payload)
    
    return c.JSON(fiber.Map{"status": "received"})
}
```

3. **Send Messages**
```go
func sendWhatsAppMessage(to, message string) error {
    url := "https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages"
    
    payload := map[string]interface{}{
        "messaging_product": "whatsapp",
        "to": to,
        "text": map[string]string{"body": message},
    }
    
    // HTTP request with Meta Access Token
    // Implementation details...
    
    return nil
}
```

## OAuth Integration

**Google OAuth Setup:**
```go
func handleGoogleCallback(c *fiber.Ctx) error {
    code := c.Query("code")
    
    // Exchange code for tokens
    tokenResp, err := exchangeGoogleCode(code)
    if err != nil {
        return c.Status(400).JSON(fiber.Map{"error": "Invalid code"})
    }
    
    // Get user info
    userInfo, err := getGoogleUserInfo(tokenResp.AccessToken)
    if err != nil {
        return c.Status(500).JSON(fiber.Map{"error": "Failed to get user info"})
    }
    
    // Create/update user in database
    user, err := createOrUpdateUser(userInfo)
    if err != nil {
        return c.Status(500).JSON(fiber.Map{"error": "Database error"})
    }
    
    // Generate JWT
    token, err := generateJWT(user)
    if err != nil {
        return c.Status(500).JSON(fiber.Map{"error": "Token generation failed"})
    }
    
    return c.JSON(fiber.Map{
        "success": true,
        "token": token,
        "user": user,
    })
}
```

## Domain Routing Strategy

**Landing Domain** (`yourdomain.com`):
- `/` - Homepage
- `/pricing` - Pricing page
- `/docs` - Documentation
- `/contact` - Contact form

**App Domain** (`app.yourdomain.com`):
- `/login` - Login page
- `/register` - Registration
- `/dashboard` - Main dashboard
- `/inbox` - Message inbox
- `/contacts` - Contact management
- `/settings` - User settings

All app routes on landing domain redirect to app domain.
All landing routes on app domain redirect to landing domain.

## Security Best Practices

1. **Environment Variables**
   - Never commit `.env` files
   - Use strong JWT secrets (32+ chars)
   - Rotate tokens regularly

2. **CORS Configuration**
   - Specific origins only
   - No wildcards in production

3. **Webhook Security**
   - Verify webhook tokens
   - Validate payloads
   - Rate limiting

4. **Database Security**
   - Localhost-only binding (127.0.0.1)
   - Strong passwords
   - Connection pooling

## Deployment

1. **Standard Architecture**
   - Use `claude` standard-architecture skill for Nginx + Unix Socket + CF Tunnel
   - Localhost-only port binding (127.0.0.1)
   - SSL termination at Cloudflare

2. **Domain Setup**
   - Configure DNS for yourdomain.com and app.yourdomain.com
   - Both pointing to Cloudflare Tunnel

3. **Environment Setup**
   - Copy `.env.example` to `.env`
   - Configure all variables
   - Test OAuth callbacks

## Testing

1. **Backend Health Check**
```bash
curl http://localhost:8080/health
```

2. **Webhook Testing**
```bash
curl -X POST http://localhost:8080/api/v1/webhooks/whatsapp \
  -H "Content-Type: application/json" \
  -d '{"test": "payload"}'
```

3. **Frontend Routing**
   - Test domain redirects
   - Verify OAuth flows
   - Check security headers

## Scaling Considerations

- **Message Queue**: Use Redis/Asynq for background processing
- **Database**: PostgreSQL with read replicas
- **Cache**: Redis for session storage
- **Monitoring**: Health checks and logs
- **Rate Limiting**: Per-user and global limits

## Revenue Features

- **Multi-tenancy**: Workspace isolation
- **Usage tracking**: Message counts, API calls
- **Billing integration**: Stripe/payment gateway
- **Analytics**: User engagement, conversion
- **API limits**: Tiered pricing model

This pattern provides a solid foundation for building scalable WhatsApp Business platforms with modern web technologies.