Domains & architecture
Canopi runs as several coordinated services on *.canopi.live. This page is the public map for integrators and operators.
Domain map
| Domain | Role | Backend |
|---|---|---|
| canopi.live | Marketing redirect → app | nginx 301 |
| app.canopi.live | Next.js dashboard + embed loader paths | port 4000 (Next.js), port 3002 (API routes) |
| api.canopi.live | Primary REST + WebSocket API | port 3002 (Express) |
| docs.canopi.live | Static documentation (this site) | nginx static |
| share.canopi.live | Share / deep-link landing | port 3002 |
| timeline.canopi.live | User & community timelines | port 3002 |
| view.canopi.live | Read-only message / anchor views | port 3002 |
Request routing on app.canopi.live
Nginx sends API-shaped paths to the Express backend (localhost:3002). Everything else goes to the Next.js app (localhost:4000).
Paths proxied to Express (3002):
/api/— REST API/v1/— versioned API surface/embed/— embed assets and sidepanel/extension/— extension distribution files/ws— WebSocket (presence, realtime)/health— health check
Paths served by Next.js (4000):
/— marketing home/my-canopis— dashboard- Other app UI routes
High-level architecture
┌─────────────────────────────────────────────────────────────┐
│ Browser extension │ Web embed (customer site) │
└──────────┬──────────┴──────────────┬────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ api.canopi.live / app.canopi.live (Express, port 3002) │
│ Auth · Messages · Embeds · Communities · Presence · WS │
└──────────┬──────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ PostgreSQL (Prisma) · Supabase Auth · file uploads │
└─────────────────────────────────────────────────────────────┘PM2 processes (production)
| Process | Port | Description |
|---|---|---|
canopi-prod | 3002 | Express API (app.js) |
canopi-app | 4000 | Next.js (/home/ubuntu/canopi/app) |
Embed script origin
Production embed loader:
html
<script
src="https://app.canopi.live/embed/v1.js"
data-canopi-id="YOUR_INSTANCE_ID"
async
></script>Public instance config is fetched from:
GET https://api.canopi.live/api/embeds/config/{canopiId}CORS
CORS headers are set by the Node application, not nginx. Do not duplicate Access-Control-Allow-Origin in nginx for api.canopi.live — duplicate headers break browser preflight.
Related
- Domains & endpoints reference — full endpoint list
- Web Embed API
- Internal ops:
docs/CANOPI_APP_DEPLOY.mdin the repo

