# Multi-Application Architecture & Naming Conventions

**Audience**: DevOps Engineers, Infrastructure Team, Developers
**Status**: Architecture Reference Document
**Last Updated**: November 2025

---

## Overview

This document defines the **multi-application architecture** for Maple Open Technologies production infrastructure. The infrastructure is designed to support **multiple independent applications** (MaplePress, MapleFile, mapleopentech) sharing common infrastructure (Cassandra, Redis, Meilisearch) while maintaining clear boundaries and isolation.

---

## Architecture Principles

### 1. Shared Infrastructure, Isolated Applications

```
┌─────────────────────────────────────────────────────────────────┐
│                    SHARED INFRASTRUCTURE                         │
│  (Used by ALL apps: MaplePress, MapleFile, mapleopentech)          │
├─────────────────────────────────────────────────────────────────┤
│  Infrastructure Workers (1-5):                                   │
│    - Manager Node (worker-1): Redis                             │
│    - Cassandra Cluster (workers 2,3,4)                          │
│    - Meilisearch (worker 5)                                     │
│                                                                  │
│  Networks:                                                       │
│    - mapleopentech-private-prod (databases, cache, search)              │
│    - mapleopentech-public-prod (reverse proxies + backends)             │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    APPLICATION: MAPLEPRESS                       │
├─────────────────────────────────────────────────────────────────┤
│  Worker 6 - MaplePress Backend + Proxy:                         │
│    Stack: maplepress                                             │
│                                                                  │
│    Service: maplepress_backend                                   │
│      Hostname: maplepress-backend                                │
│      Port: 8000                                                  │
│      Networks: mapleopentech-private-prod + mapleopentech-public-prod           │
│      Connects to: Cassandra, Redis, Meilisearch, Spaces        │
│                                                                  │
│    Service: maplepress_backend-caddy                             │
│      Hostname: caddy                                             │
│      Domain: getmaplepress.ca (API)                              │
│      Proxies to: maplepress-backend:8000                         │
│                                                                  │
│  Worker 7 - MaplePress Frontend:                                │
│    Stack: maplepress-frontend                                    │
│    Service: maplepress-frontend_caddy                            │
│    Hostname: frontend-caddy                                      │
│    Domain: getmaplepress.com (Web UI)                            │
│    Serves: /var/www/maplepress-frontend/                        │
│    Calls: https://getmaplepress.ca (backend API)                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    APPLICATION: MAPLEFILE (Future)               │
├─────────────────────────────────────────────────────────────────┤
│  Worker 8 - MapleFile Backend + Proxy:                          │
│    Stack: maplefile                                              │
│                                                                  │
│    Service: maplefile_backend                                    │
│      Hostname: maplefile-backend                                 │
│      Port: 8000                                                  │
│      Networks: mapleopentech-private-prod + mapleopentech-public-prod           │
│      Connects to: Cassandra, Redis, Meilisearch, Spaces        │
│                                                                  │
│    Service: maplefile_backend-caddy                              │
│      Hostname: maplefile-backend-caddy                           │
│      Domain: maplefile.ca (API)                                  │
│      Proxies to: maplefile-backend:8000                          │
│                                                                  │
│  Worker 9 - MapleFile Frontend:                                 │
│    Stack: maplefile-frontend                                     │
│    Service: maplefile-frontend_caddy                             │
│    Hostname: maplefile-frontend-caddy                            │
│    Domain: maplefile.com (Web UI)                                │
│    Serves: /var/www/maplefile-frontend/                         │
│    Calls: https://maplefile.ca (backend API)                     │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                    APPLICATION: mapleopentech (Future)               │
├─────────────────────────────────────────────────────────────────┤
│  Worker 10 - mapleopentech Backend + Proxy:                         │
│    Stack: mapleopentech                                              │
│                                                                  │
│    Service: mapleopentech_backend                                    │
│      Hostname: mapleopentech-backend                                 │
│      Port: 8000                                                  │
│      Networks: mapleopentech-private-prod + mapleopentech-public-prod           │
│      Connects to: Cassandra, Redis, Meilisearch, Spaces        │
│                                                                  │
│    Service: mapleopentech_backend-caddy                              │
│      Hostname: mapleopentech-backend-caddy                           │
│      Domain: api.mapleopentech.io (API)                              │
│      Proxies to: mapleopentech-backend:8000                          │
│                                                                  │
│  Worker 11 - mapleopentech Frontend:                                │
│    Stack: mapleopentech-frontend                                     │
│    Service: mapleopentech-frontend_caddy                             │
│    Hostname: mapleopentech-frontend-caddy                            │
│    Domain: mapleopentech.io (Web UI)                                 │
│    Serves: /var/www/mapleopentech-frontend/                         │
│    Calls: https://api.mapleopentech.io (backend API)                 │
└─────────────────────────────────────────────────────────────────┘
```

---

## Naming Conventions

### Pattern: **Option C - Hybrid Stacks**

**Strategy**:
- Backend + Backend Caddy in **one stack** (deployed together)
- Frontend Caddy in **separate stack** (independent deployment)

**Why this pattern?**
- Backend and its reverse proxy are tightly coupled → deploy together
- Frontend is independent → deploy separately
- Avoids redundant naming like `maplepress-backend_backend`
- Clean service names: `maplepress_backend`, `maplepress_backend-caddy`, `maplepress-frontend_caddy`

### Stack Names

| Application | Stack Name            | Services in Stack               | Purpose                              |
|-------------|-----------------------|---------------------------------|--------------------------------------|
| MaplePress  | `maplepress`          | `backend`, `backend-caddy`      | Backend API + reverse proxy          |
| MaplePress  | `maplepress-frontend` | `caddy`                         | Frontend static files                |
| MapleFile   | `maplefile`           | `backend`, `backend-caddy`      | Backend API + reverse proxy          |
| MapleFile   | `maplefile-frontend`  | `caddy`                         | Frontend static files                |
| mapleopentech   | `mapleopentech`           | `backend`, `backend-caddy`      | Backend API + reverse proxy          |
| mapleopentech   | `mapleopentech-frontend`  | `caddy`                         | Frontend static files                |

### Service Names (Docker Auto-Generated)

Docker Swarm automatically creates service names from: `{stack-name}_{service-name}`

| Stack Name            | Service in YAML  | Full Service Name           | Purpose                         |
|-----------------------|------------------|-----------------------------|----------------------------------|
| `maplepress`          | `backend`        | `maplepress_backend`        | Go backend API                   |
| `maplepress`          | `backend-caddy`  | `maplepress_backend-caddy`  | Backend reverse proxy            |
| `maplepress-frontend` | `caddy`          | `maplepress-frontend_caddy` | Frontend static file server      |
| `maplefile`           | `backend`        | `maplefile_backend`         | Go backend API                   |
| `maplefile`           | `backend-caddy`  | `maplefile_backend-caddy`   | Backend reverse proxy            |
| `maplefile-frontend`  | `caddy`          | `maplefile-frontend_caddy`  | Frontend static file server      |

**View services:**
```bash
docker service ls
# Output:
# maplepress_backend              1/1
# maplepress_backend-caddy        1/1
# maplepress-frontend_caddy       1/1
# maplefile_backend               1/1
# maplefile_backend-caddy         1/1
# maplefile-frontend_caddy        1/1
```

### Hostnames (DNS Resolution Within Networks)

Hostnames are defined in the stack YAML (`hostname: ...`) and used for container-to-container communication.

| Application | Component       | Hostname                      | Used By                          |
|-------------|-----------------|-------------------------------|----------------------------------|
| MaplePress  | Backend         | `maplepress-backend`          | Caddy proxy, other services      |
| MaplePress  | Backend Caddy   | `caddy`                       | Internal reference (rarely used) |
| MaplePress  | Frontend Caddy  | `frontend-caddy`              | Internal reference (rarely used) |
| MapleFile   | Backend         | `maplefile-backend`           | Caddy proxy, other services      |
| MapleFile   | Backend Caddy   | `caddy`                       | Internal reference (rarely used) |
| MapleFile   | Frontend Caddy  | `frontend-caddy`              | Internal reference (rarely used) |

**Example - Caddyfile for MaplePress backend:**
```caddy
getmaplepress.ca www.getmaplepress.ca {
    reverse_proxy maplepress-backend:8000  # Uses hostname, not service name
}
```

**Example - Caddyfile for MapleFile backend:**
```caddy
maplefile.ca www.maplefile.ca {
    reverse_proxy maplefile-backend:8000
}
```

### Docker Configs (Auto-Generated with Stack Prefix)

| Stack Name              | Config in YAML | Full Config Name                    |
|-------------------------|----------------|-------------------------------------|
| `maplepress`            | `caddyfile`    | `maplepress_caddyfile`              |
| `maplepress-frontend`   | `caddyfile`    | `maplepress-frontend_caddyfile`     |
| `maplefile`             | `caddyfile`    | `maplefile_caddyfile`               |
| `maplefile-frontend`    | `caddyfile`    | `maplefile-frontend_caddyfile`      |

**View configs:**
```bash
docker config ls
# Output:
# maplepress_caddyfile
# maplepress-frontend_caddyfile
# maplefile_caddyfile
# maplefile-frontend_caddyfile
```

### File Paths

| Application | Component | Path                                  |
|-------------|-----------|---------------------------------------|
| MaplePress  | Frontend  | `/var/www/maplepress-frontend/`       |
| MaplePress  | Backend   | `/var/www/monorepo/cloud/mapleopentech-backend/` |
| MapleFile   | Frontend  | `/var/www/maplefile-frontend/`        |
| MapleFile   | Backend   | `/var/www/monorepo/cloud/mapleopentech-backend/` |

---

## Resource Allocation

### Workers 1-5: Shared Infrastructure (ALL Apps)

| Worker | Role                  | Services                              | Shared By      |
|--------|-----------------------|---------------------------------------|----------------|
| 1      | Manager + Redis       | Swarm manager, Redis cache            | All apps       |
| 2      | Cassandra Node 1      | cassandra-1                           | All apps       |
| 3      | Cassandra Node 2      | cassandra-2                           | All apps       |
| 4      | Cassandra Node 3      | cassandra-3                           | All apps       |
| 5      | Meilisearch           | meilisearch (full-text search)        | All apps       |

### Workers 6-7: MaplePress Application

| Worker | Role                       | Services                                    |
|--------|----------------------------|---------------------------------------------|
| 6      | MaplePress Backend + Proxy | maplepress_backend, maplepress_backend-caddy |
| 7      | MaplePress Frontend        | maplepress-frontend_caddy                   |

### Workers 8-9: MapleFile Application (Future)

| Worker | Role                      | Services                                   |
|--------|---------------------------|--------------------------------------------|
| 8      | MapleFile Backend + Proxy | maplefile_backend, maplefile_backend-caddy |
| 9      | MapleFile Frontend        | maplefile-frontend_caddy                   |

### Workers 10-11: mapleopentech Application (Future)

| Worker | Role                       | Services                                    |
|--------|----------------------------|---------------------------------------------|
| 10     | mapleopentech Backend + Proxy  | mapleopentech_backend, mapleopentech_backend-caddy |
| 11     | mapleopentech Frontend         | mapleopentech-frontend_caddy                   |

---

## Network Topology

### mapleopentech-private-prod (Shared by ALL Apps)

**Purpose**: Private backend services - databases, cache, search

**Services**:
- Cassandra cluster (3 nodes)
- Redis
- Meilisearch
- **All backend services** (maplepress-backend, maplefile-backend, mapleopentech-backend)

**Security**: No ingress ports, no internet access, internal-only

### mapleopentech-public-prod (Per-App Reverse Proxies + Backends)

**Purpose**: Internet-facing services - reverse proxies and backends

**Services**:
- **All backend services** (join both networks)
- **All Caddy reverse proxies** (backend + frontend)

**Security**: Ports 80/443 exposed on workers running Caddy

---

## Deployment Commands

### MaplePress

```bash
# Backend + Backend Caddy (deployed together in one stack)
docker stack deploy -c maplepress-stack.yml maplepress

# Frontend (deployed separately)
docker stack deploy -c maplepress-frontend-stack.yml maplepress-frontend
```

### MapleFile (Future)

```bash
# Backend + Backend Caddy (deployed together in one stack)
docker stack deploy -c maplefile-stack.yml maplefile

# Frontend (deployed separately)
docker stack deploy -c maplefile-frontend-stack.yml maplefile-frontend
```

### mapleopentech (Future)

```bash
# Backend + Backend Caddy (deployed together in one stack)
docker stack deploy -c mapleopentech-stack.yml mapleopentech

# Frontend (deployed separately)
docker stack deploy -c mapleopentech-frontend-stack.yml mapleopentech-frontend
```

---

## Verification Commands

### List All Stacks

```bash
docker stack ls
# Expected output:
# NAME                          SERVICES
# cassandra                     3
# maplepress                    2       (backend + backend-caddy)
# maplepress-frontend           1       (frontend caddy)
# maplefile                     2       (future)
# maplefile-frontend            1       (future)
# meilisearch                   1
# redis                         1
```

### List All Services

```bash
docker service ls | sort
# Expected output (partial):
# cassandra_cassandra-1                  1/1
# cassandra_cassandra-2                  1/1
# cassandra_cassandra-3                  1/1
# maplepress_backend                     1/1
# maplepress_backend-caddy               1/1
# maplepress-frontend_caddy              1/1
# meilisearch_meilisearch                1/1
# redis_redis                            1/1
```

### List All Configs

```bash
docker config ls
# Expected output:
# maplepress_caddyfile
# maplepress-frontend_caddyfile
```

---

## Adding a New Application

To add a new application (e.g., "MaplePortal"):

### 1. Update .env.template

```bash
# Add new section
# ==============================================================================
# MAPLEPORTAL APPLICATION
# ==============================================================================

# Backend Configuration
MAPLEPORTAL_BACKEND_DOMAIN=api.mapleportal.io
MAPLEPORTAL_SPACES_BUCKET=mapleportal-prod
MAPLEPORTAL_JWT_SECRET=CHANGEME
MAPLEPORTAL_IP_ENCRYPTION_KEY=CHANGEME

# Frontend Configuration
MAPLEPORTAL_FRONTEND_DOMAIN=mapleportal.io
MAPLEPORTAL_FRONTEND_API_URL=https://api.mapleportal.io
```

### 2. Create New Workers

```bash
# Worker 12 - Backend + Backend Caddy
# Worker 13 - Frontend Caddy
```

### 3. Follow Naming Convention

- Stack names: `mapleportal` (backend + backend-caddy), `mapleportal-frontend`
- Service names: `mapleportal_backend`, `mapleportal_backend-caddy`, `mapleportal-frontend_caddy`
- Hostnames: `mapleportal-backend`, `mapleportal-backend-caddy`, `mapleportal-frontend-caddy`
- Domains: `api.mapleportal.io` (backend), `mapleportal.io` (frontend)
- Paths: `/var/www/mapleportal-frontend/`

### 4. Deploy Services

```bash
# Backend + backend-caddy in one stack
docker stack deploy -c mapleportal-stack.yml mapleportal

# Frontend in separate stack
docker stack deploy -c mapleportal-frontend-stack.yml mapleportal-frontend
```

---

## Benefits of This Architecture

### 1. Clear Separation
- Each app has dedicated workers and services
- No naming conflicts between apps
- Easy to identify which services belong to which app

### 2. Shared Infrastructure Efficiency
- Single Cassandra cluster serves all apps
- Single Redis instance (or sharded by app)
- Single Meilisearch instance with app-prefixed indexes
- Cost savings: 5 workers for infrastructure vs 15+ if each app had its own

### 3. Independent Scaling
- Scale MaplePress without affecting MapleFile
- Deploy new apps without touching existing ones
- Remove apps without impacting infrastructure

### 4. Operational Clarity
```bash
# View only MaplePress services
docker service ls | grep maplepress

# View only MapleFile services
docker service ls | grep maplefile

# Restart MaplePress backend
docker service update --force maplepress_backend

# Remove MapleFile entirely (if needed)
docker stack rm maplefile
docker stack rm maplefile-frontend
```

### 5. Developer Friendly
- Developers instantly know which app they're working with
- No ambiguous "backend" or "frontend" names
- Service discovery is intuitive: `maplepress-backend:8000`

---

## Migration Checklist (For Existing Deployments)

If you deployed with old naming (`caddy`, `maplepress`, `frontend-caddy`), migrate like this:

### Step 1: Update Configuration Files Locally

```bash
cd ~/monorepo/cloud/infrastructure/production

# Update all YAML files to use new naming
# - maplepress → maplepress-backend
# - caddy → maplepress-backend-caddy
# - frontend-caddy → maplepress-frontend-caddy

# Update Caddyfiles to use new hostnames
# - backend:8000 → maplepress-backend:8000
```

### Step 2: Remove Old Stacks

```bash
# On manager node
docker stack rm maplepress
docker stack rm caddy
docker stack rm frontend-caddy

# Wait for cleanup
sleep 10

# Remove old configs
docker config rm caddy_caddyfile
docker config rm frontend-caddy_caddyfile
```

### Step 3: Deploy New Stacks

```bash
# Deploy with new names (Option C naming)
docker stack deploy -c maplepress-stack.yml maplepress
docker stack deploy -c maplepress-frontend-stack.yml maplepress-frontend
```

### Step 4: Verify

```bash
docker service ls
# Should show:
# maplepress_backend
# maplepress_backend-caddy
# maplepress-frontend_caddy

docker config ls
# Should show:
# maplepress_caddyfile
# maplepress-frontend_caddyfile
```

---

**Last Updated**: November 2025
**Maintained By**: Infrastructure Team
**Status**: Production Standard - Follow for All New Applications
