Skip to content

Domains & architecture

Canopi runs as several coordinated services on *.canopi.live. This page is the public map for integrators and operators.

Domain map

DomainRoleBackend
canopi.liveMarketing redirect → appnginx 301
app.canopi.liveNext.js dashboard + embed loader pathsport 4000 (Next.js), port 3002 (API routes)
api.canopi.livePrimary REST + WebSocket APIport 3002 (Express)
docs.canopi.liveStatic documentation (this site)nginx static
share.canopi.liveShare / deep-link landingport 3002
timeline.canopi.liveUser & community timelinesport 3002
view.canopi.liveRead-only message / anchor viewsport 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)

ProcessPortDescription
canopi-prod3002Express API (app.js)
canopi-app4000Next.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.

Canopi — Metaweb coordination layer for community-aware presence and messaging.