> ## Documentation Index
> Fetch the complete documentation index at: https://dev-doc.dualmindlab.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Production Deployment

> Deployment guide for DualMind Lab — backend on Azure, frontend and admin on Cloudflare Workers.

<Info>
  DualMind Lab uses a split deployment: backend on **Azure App Service**, frontend and admin on **Cloudflare Workers**. Database is managed by **Supabase**.
</Info>

## Architecture overview

| Component   | Platform                     | URL                                        |
| ----------- | ---------------------------- | ------------------------------------------ |
| Backend API | Azure App Service            | `https://api.dualmindlab.tech`             |
| Frontend    | Cloudflare Workers           | `https://arena.dualmindlab.tech`           |
| Admin Panel | Cloudflare Workers           | Separate Workers project                   |
| Database    | Supabase (hosted PostgreSQL) | `https://calqfzajyidkdzbaswjp.supabase.co` |

## Backend deployment (Azure)

<Tabs>
  <Tab title="GitHub Actions (CI/CD)">
    The backend auto-deploys via GitHub Actions on push to `main`:

    ```yaml filename=".github/workflows/master_dualmind-arena.yml" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    # Trigger: push to main branch
    # Steps: restore → build → publish → deploy to Azure App Service
    ```

    <Tip>This is the recommended deployment method. Every push to `main` triggers an automatic build and deploy.</Tip>
  </Tab>

  <Tab title="Manual">
    ```bash filename="Terminal" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    cd DualMind_Back/src/DualMind.API
    dotnet publish -c Release -o ./publish
    # Deploy ./publish to Azure App Service
    ```
  </Tab>

  <Tab title="Docker">
    ```bash filename="Terminal" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    cd DualMind_Back
    docker-compose up -d
    ```

    The `Dockerfile` in `src/DualMind.API/` builds the .NET 8 app. The `docker-compose.yml` maps port 8080→80.
  </Tab>
</Tabs>

### Environment variables (Azure)

Set these in **Azure App Service → Configuration → Application settings**:

| Variable                    | Required    | Description                      |
| --------------------------- | ----------- | -------------------------------- |
| `SUPABASE_URL`              | Yes         | Supabase project URL             |
| `SUPABASE_SERVICE_ROLE_KEY` | Yes         | Service role key for DB access   |
| `JWT_SECRET`                | Yes         | JWT secret for token validation  |
| `GROQ_API_KEY`              | Optional    | Groq API key (overrides DB keys) |
| `ASPNETCORE_ENVIRONMENT`    | Recommended | Set to `Production`              |

<Warning>Never store secrets in code or config files. Use Azure Application Settings or Key Vault.</Warning>

## Frontend deployment (Cloudflare Workers)

### Prerequisites

* Cloudflare account with Workers enabled
* `wrangler` CLI authenticated (`npx wrangler login`)

### Deploy

```bash filename="Terminal" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
cd DualMind_UI
npx wrangler deploy
```

### Configuration

Update `config.js` before deploying to ensure production URLs:

```javascript filename="config.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
// These should auto-detect, but verify:
// - apiBaseUrl resolves to 'https://api.dualmindlab.tech' in production
// - supabase.url and supabase.anonKey are set correctly
```

The Cloudflare Worker (`worker.js`) proxies `/api/*` requests to the backend and serves static files for everything else.

## Admin panel deployment

```bash filename="Terminal" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
cd DualMind_Admin-UI
npm run deploy       # staging
npm run deploy:prod  # production
```

Set `BACKEND_URL` in Cloudflare Workers environment:

```toml filename="wrangler.toml" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
[env.production.vars]
BACKEND_URL = "https://api.dualmindlab.tech"
```

## Supabase configuration

### Required tables

Ensure all tables exist in the `public` schema. See [Database Schema](/database/schema) for complete definitions:

* `users`, `ai_models`, `threads`, `thread_messages`
* `comparisons`, `model_votes`, `providers`, `provider_api_keys`
* `system_settings`

### Row-Level Security (RLS)

If RLS is enabled on tables, ensure the service role key bypasses RLS or appropriate policies are in place. The backend uses the service role key which bypasses RLS by default.

### Feature flags

Insert into `system_settings`:

```sql filename="Supabase SQL Editor" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
INSERT INTO system_settings (key, value) VALUES ('public_sharing', 'true');
```

## Monitoring

<CardGroup cols={3}>
  <Card title="Backend Logs" icon="scroll">
    Azure App Service → **Log Stream** for real-time logs. Each request logs correlation ID, method, path, duration, and status code.
  </Card>

  <Card title="Health Checks" icon="heart-pulse">
    * `GET /health` — basic API health
    * `GET /api/health` — alias endpoint
    * `GET /api/arena/ping` — arena subsystem
  </Card>

  <Card title="Swagger UI" icon="flask">
    Available at `/swagger` in all environments. Useful for quick API testing and exploration.
  </Card>
</CardGroup>

<Tip>Use the `X-Correlation-Id` response header to trace requests across logs.</Tip>
