Files
the-collective-hub/.github/instructions/deployment-guide.instructions.md
KungRaseri b192cd53ba docs(copilot): add Copilot instructions for The Collective Hub
- Add comprehensive project overview and core philosophy
- Document file structure reference for the codebase
- Create key files reference table for task-specific guidance
- Include multi-tenant guidelines and site resolution flow
2026-06-05 23:46:15 -07:00

133 lines
5.2 KiB
Markdown

---
description: 'Use when deploying a new site instance, setting up Coolify, configuring Docker, managing migrations, or troubleshooting deployment issues for The Collective Hub.'
applyTo: 'Dockerfile', 'docker-compose.yml', '.dockerignore', 'Coolify'
---
# Deployment Guide
## Deployment Model
The Collective Hub uses **multiple Coolify deployments** from a single Git repository. Each deployment runs the same Docker image but is configured with different environment variables — most importantly, a different `SITE_SLUG`.
```
Git Repo (main branch)
├── Coolify Deployment "bad-movies-theater"
│ ├── SITE_SLUG=bad-movies-theater
│ ├── PUBLIC_SITE_URL=https://badmovies.example.com
│ ├── OWNER_DISCORD_ID=... (site owner)
│ └── RUN_MIGRATIONS=false
├── Coolify Deployment "garbage-day"
│ ├── SITE_SLUG=garbage-day
│ ├── PUBLIC_SITE_URL=https://garbageday.example.com
│ ├── OWNER_DISCORD_ID=... (site owner)
│ └── RUN_MIGRATIONS=false
└── Coolify Deployment "primary" (migration runner)
├── SITE_SLUG=primary
├── PUBLIC_SITE_URL=https://primary.example.com
├── OWNER_DISCORD_ID=... (David's Discord ID)
└── RUN_MIGRATIONS=true
```
## Docker
The project uses a multi-stage Docker build (see [`Dockerfile`](Dockerfile)):
```dockerfile
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:22-alpine AS runner
WORKDIR /app
COPY --from=builder /app/build build/
COPY --from=builder /app/node_modules node_modules/
COPY package.json .
EXPOSE 3000
CMD ["node", "build"]
```
### Local Development with Docker Compose
See [`docker-compose.yml`](docker-compose.yml) for local development setup, which includes:
- Postgres database container
- The SvelteKit app container
- Proper environment variables for local dev
```bash
docker compose up
```
## Adding a New Site
To add a new community/theater site:
1. **Insert a site row in the database:**
```sql
INSERT INTO sites (slug, name) VALUES ('new-community', 'New Community');
INSERT INTO site_settings (site_id, settings) VALUES (
(SELECT id FROM sites WHERE slug = 'new-community'),
'{"branding":{"siteName":"New Community","tagline":"Coming soon"},"theme":{"preset":"dark","accentColor":"#e63946","backgroundColor":"#1a1a2e","textColor":"#eaeaea"},"homepage":{"heroTitle":"Welcome","heroSubtitle":"","aboutText":"","primaryButtonText":"Join us on Discord","primaryButtonLink":"","showNextEvent":true,"showSchedule":true},"layout":{"preset":"standard"}}'
);
```
Or use the seed script pattern.
2. **Create a new Coolify deployment:**
- Point to the same Git repo + branch
- Set `SITE_SLUG=new-community`
- Set `PUBLIC_SITE_URL=https://newcommunity.example.com`
- Set `OWNER_DISCORD_ID` to the site owner's Discord user ID
- Set `RUN_MIGRATIONS=false` (unless this is the designated migration runner)
3. **Configure DNS:** Point the domain to the Coolify deployment's IP/URL
## Environment Variables Per Deployment
Each deployment needs its own set of env vars. See [`docs/04-environment-variables.md`](docs/04-environment-variables.md) for the full reference.
**Rules:**
- Shared vars (`DATABASE_URL`, `DISCORD_CLIENT_ID`, `CDN_BASE_URL`) must be identical across all deployments
- Per-site vars (`SITE_SLUG`, `PUBLIC_SITE_URL`, `OWNER_DISCORD_ID`) are unique per deployment
- `RUN_MIGRATIONS=true` on exactly one deployment (the primary/migration runner)
## Migration Runner
The migration runner deployment is critical:
- It runs `RUN_MIGRATIONS=true` and executes schema migrations on startup
- It must be deployed **first** when schema changes are included in a release
- Other deployments should be deployed after the migration completes
- If the migration runner is down, other deployments still serve traffic (they just won't have schema changes)
## Coolify Configuration
In Coolify, each deployment:
- Uses the **same Git repository** and branch
- Has its own **unique environment variables**
- Can have its own **domain/SSL configuration**
- Is deployed independently (zero-downtime per deployment)
### Deploy Strategy
1. Deploy the migration runner first (`RUN_MIGRATIONS=true`)
2. Wait for it to be healthy (migrations complete)
3. Deploy other sites in any order
4. Each deployment is independent — one failing doesn't affect others
## Troubleshooting
| Symptom | Likely Cause | Fix |
|---------|-------------|-----|
| "Site not found" on load | No matching row in `sites` table for `SITE_SLUG` | Insert the site row or fix `SITE_SLUG` env var |
| Login redirects to wrong URL | `PUBLIC_SITE_URL` / `BETTER_AUTH_URL` mismatch | Ensure both match the deployment's actual URL |
| "Already exists" errors on deploy | Two deployments running migrations simultaneously | Check only one has `RUN_MIGRATIONS=true` |
| Images not loading | `CDN_BASE_URL` missing or wrong, or `cdnKey` starts with `/` | Ensure no leading slash on CDN keys |
| Auth callbacks failing | Discord OAuth redirect URI doesn't match deployment URL | Add the correct URL to Discord Developer Portal |