Initial commit: The Collective Hub planning documentation

This commit is contained in:
2026-06-05 22:49:03 -04:00
commit 293415f349
29 changed files with 4551 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
# Environment Variables Document — The Collective Hub
## Overview
Environment variables are the only difference between deployments. Each Coolify deployment has its own set of env vars, but all deployments share the same database, CDN, and Discord OAuth app.
---
## Variable Reference
### Required for Every Deployment
| Variable | Example | Description | Shared or Per-Site? |
|----------|---------|-------------|---------------------|
| `SITE_SLUG` | `bad-movies-theater` | Identifies which site this deployment serves. Must match a `slug` in the `sites` table. | **Per-site** |
| `PUBLIC_SITE_URL` | `https://badmovies.example.com` | The public URL of this deployment. Used for auth callbacks, canonical URLs. | **Per-site** |
| `DATABASE_URL` | `postgresql://user:pass@host:5432/collective_hub` | Postgres connection string. | **Shared** (same for all) |
| `BETTER_AUTH_SECRET` | (generated) | Secret key for Better Auth session signing. | **Shared** (same for all) |
| `BETTER_AUTH_URL` | `https://badmovies.example.com` | Base URL for auth callbacks. Must match `PUBLIC_SITE_URL`. | **Per-site** |
| `DISCORD_CLIENT_ID` | `123456789012345678` | Discord OAuth application client ID. | **Shared** |
| `DISCORD_CLIENT_SECRET` | `abc123...` | Discord OAuth application client secret. | **Shared** |
| `OWNER_DISCORD_ID` | `123456789012345678` | Discord user ID of the site owner. Used to bootstrap ownership on first login. | **Per-site** |
### Required for CDN (Phase 1)
| Variable | Example | Description | Shared or Per-Site? |
|----------|---------|-------------|---------------------|
| `CDN_BASE_URL` | `https://cdn.example.com` | Base URL for constructing CDN URLs. | **Shared** |
| `CDN_STORAGE_ENDPOINT` | `https://ny.storage.bunnycdn.com` | Storage API endpoint. | **Shared** |
| `CDN_ACCESS_KEY` | `abc123...` | Storage access key. | **Shared** |
| `CDN_SECRET_KEY` | (S3 only) | Secret key for S3-compatible storage. | **Shared** |
| `CDN_BUCKET` | `collective-hub` | Bucket or storage zone name. | **Shared** |
| `CDN_REGION` | `us-east-1` | Region for S3-compatible storage. | **Shared** |
### Super Admin
| Variable | Example | Description | Shared or Per-Site? |
|----------|---------|-------------|---------------------|
| `SUPER_ADMIN_DISCORD_IDS` | `123456789,987654321` | Comma-separated Discord user IDs with cross-site super admin access. | **Shared** |
### Migration Control
| Variable | Example | Description | Shared or Per-Site? |
|----------|---------|-------------|---------------------|
| `RUN_MIGRATIONS` | `true` | Whether this deployment should run database migrations on startup. Only one deployment should have this set to `true`. | **Per-site** (only one `true`) |
### Optional
| Variable | Example | Description | Shared or Per-Site? |
|----------|---------|-------------|---------------------|
| `NODE_ENV` | `production` | Node environment. | **Per-site** (usually `production`) |
| `LOG_LEVEL` | `info` | Logging verbosity. | **Per-site** |
| `FEATURE_FLAGS` | `events:on` | Comma-separated feature flags (future). | **Per-site** |
---
## Example: Full Deployment Env File
### Deployment: bad-movies-theater (primary — runs migrations)
```env
# Site Identity
SITE_SLUG=bad-movies-theater
PUBLIC_SITE_URL=https://badmovies.example.com
# Database (shared)
DATABASE_URL=postgresql://hub_app:password@db.example.com:5432/collective_hub
# Auth (Better Auth)
BETTER_AUTH_SECRET=generated-secret-value-here
BETTER_AUTH_URL=https://badmovies.example.com
# Discord OAuth (shared)
DISCORD_CLIENT_ID=123456789012345678
DISCORD_CLIENT_SECRET=your-discord-client-secret
# Ownership Bootstrap
OWNER_DISCORD_ID=123456789012345678
# Super Admin
SUPER_ADMIN_DISCORD_IDS=111111111111111111
# Migration Control
RUN_MIGRATIONS=true
# CDN (shared)
CDN_BASE_URL=https://cdn.example.com
CDN_STORAGE_ENDPOINT=https://ny.storage.bunnycdn.com
CDN_ACCESS_KEY=your-bunny-access-key
CDN_BUCKET=collective-hub
# Optional
NODE_ENV=production
LOG_LEVEL=info
```
### Deployment: garbage-day (secondary — skips migrations)
```env
# Site Identity
SITE_SLUG=garbage-day
PUBLIC_SITE_URL=https://garbageday.example.com
# Database (shared — same value)
DATABASE_URL=postgresql://hub_app:password@db.example.com:5432/collective_hub
# Auth (Better Auth)
BETTER_AUTH_SECRET=generated-secret-value-here
BETTER_AUTH_URL=https://garbageday.example.com
# Discord OAuth (shared — same value)
DISCORD_CLIENT_ID=123456789012345678
DISCORD_CLIENT_SECRET=your-discord-client-secret
# Ownership Bootstrap
OWNER_DISCORD_ID=987654321098765432
# Super Admin (same value)
SUPER_ADMIN_DISCORD_IDS=111111111111111111
# Migration Control
RUN_MIGRATIONS=false
# CDN (shared — same values)
CDN_BASE_URL=https://cdn.example.com
CDN_STORAGE_ENDPOINT=https://ny.storage.bunnycdn.com
CDN_ACCESS_KEY=your-bunny-access-key
CDN_BUCKET=collective-hub
# Optional
NODE_ENV=production
LOG_LEVEL=info
```
---
## What's Shared vs Per-Site
```
Shared across ALL deployments:
├── DATABASE_URL (one database)
├── BETTER_AUTH_SECRET (same session signing key)
├── DISCORD_CLIENT_ID (one Discord OAuth app)
├── DISCORD_CLIENT_SECRET
├── SUPER_ADMIN_DISCORD_IDS (system maintainers)
├── CDN_BASE_URL (one CDN bucket)
├── CDN_STORAGE_ENDPOINT
├── CDN_ACCESS_KEY
├── CDN_SECRET_KEY (if S3)
├── CDN_BUCKET
└── CDN_REGION (if S3)
Unique per deployment:
├── SITE_SLUG (which site this is)
├── PUBLIC_SITE_URL (its domain)
├── BETTER_AUTH_URL (must match PUBLIC_SITE_URL)
├── OWNER_DISCORD_ID (who owns this site)
└── RUN_MIGRATIONS (only one deployment = true)
```
---
## Notes & Warnings
### Discord OAuth: Shared App
All sites share one Discord OAuth application. This means:
- Users see the same app name when authorizing (e.g., "The Collective Hub")
- The OAuth redirect URL list must include every site's callback URL
- Discord has a limit on redirect URLs — manageable for a handful of sites
- If the system grows to many sites, each site may need its own Discord OAuth app, or a central auth domain pattern should be introduced
### Better Auth Secret
`BETTER_AUTH_SECRET` must be the same across all deployments because sessions are signed with it. This enables super admins to potentially navigate between site admin panels with a single session (future enhancement).
### Database Migrations — Automated but Coordinated
Migrations run automatically on app startup, but only on the deployment with `RUN_MIGRATIONS=true`. All other deployments skip migrations (`RUN_MIGRATIONS=false`). This means:
- **Exactly one deployment** is designated as the migration runner
- That deployment must be deployed first when schema changes are made
- If the migration runner is down, other deployments still work (they just can't run new migrations)
- Choose a stable, low-traffic deployment as the migration runner (or the super admin dashboard deployment)
### Super Admin Access
`SUPER_ADMIN_DISCORD_IDS` is a comma-separated list of Discord user IDs. Users matching these IDs bypass site-scoped membership checks and can access any site's admin panel. This is intended for David (system maintainer) and should be kept to a minimal, trusted set of IDs.
### Sensitive Values
All secrets (database URL, auth secrets, Discord secrets, CDN keys) must be stored securely in Coolify's environment variable management — never committed to the repository.