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
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
---
|
||||
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 |
|
||||
Reference in New Issue
Block a user