feat: HLS streaming, transcripts, agent course generation & landing-page course previews (#663)

New features:
- HLS video encoding/streaming (hls routes, hls-encoder) and a media
  transcripts pipeline (transcripts route + media-transcript queries)
- AI assistant chat vs. run model: agent-course-generation worker/queue,
  run-monitor pane, chat-changes card, content ask-ai bar
- Per-theme course-page previews across org landing-page themes (bold,
  classic, corporate, editorial, etc.) with a shared course token/component set
- View-as-student mode and login-link / link-invite invite flows

Refactor:
- Extract packages/core consolidating config (env, storage, dashboard-url),
  services and utils previously duplicated under apps/api/src/config
- Remove legacy agent service modules (chat-tools, chat-context,
  context-window, document, fetch-url, lesson-content)
- Relax Cross-Origin-Resource-Policy to allow cross-origin media embedding
- Add format script to tenant-router so turbo run format covers it
This commit is contained in:
Rotimi Best
2026-06-07 18:43:05 +01:00
committed by GitHub
parent a2e70779a0
commit d5b07d356e
496 changed files with 19050 additions and 8312 deletions
+3 -3
View File
@@ -1,11 +1,11 @@
---
title: Welcome to ClassroomIO
description: A flexible, user-friendly platform for creating, managing, and delivering courses for companies and training organisations.
description: Learn how to create customer academies, partner certification programs, and employee training workflows in ClassroomIO.
---
<img
alt="A flexible, user-friendly platform for creating, managing, and delivering courses for companies and training organisations"
src="https://brand.cdn.clsrio.com/og/classroomio-og.png"
alt="ClassroomIO documentation for customer, partner, and employee education"
src="https://brand.cdn.clsrio.com/og/classroomio-opengraph.png"
/>
Welcome to the ClassroomIO documentation—your comprehensive guide to streamlining training for everyone. Our all-in-one platform empowers bootcamps, educators, and businesses to manage training programs easily. Run multiple classes and cohorts from a single UI with our mobile-first application, ensuring students can access all published content from any device.
@@ -31,7 +31,7 @@ cd classroomio
cp .env.example .env
```
Open `.env` and set `PUBLIC_SERVER_URL`, `TRUSTED_ORIGINS`, and `BETTER_AUTH_SECRET` for your domain. For local development the defaults work as-is.
Open `.env` and set `DASHBOARD_ORIGIN` and `BETTER_AUTH_SECRET` for your domain. For local development the defaults work as-is.
3. Start the full stack:
@@ -65,8 +65,6 @@ Docker self-hosting uses a single root `.env` file. Every `docker compose` comma
| `POSTGRES_DB` | Database name | `classroomio` |
| `POSTGRES_USER` | Database user | `postgres` |
| `POSTGRES_PASSWORD` | Database password | `postgres` |
| `PUBLIC_SERVER_URL` | Public API URL (browser requests) | `http://localhost:3081` |
| `TRUSTED_ORIGINS` | Comma-separated CORS origins | `http://localhost:3082` |
| `BETTER_AUTH_SECRET` | Auth session signing secret | — |
| `AUTH_BEARER_TOKEN` | API bearer token | Auto-generated |
| `PRIVATE_SERVER_KEY` | Dashboard-to-API auth key (same in both) | Auto-generated |
@@ -74,6 +72,15 @@ Docker self-hosting uses a single root `.env` file. Every `docker compose` comma
| `PRIVATE_SERVER_URL` | Internal API URL for SSR (Docker network) | `http://api:3081` |
| `DASHBOARD_ORIGIN` | Dashboard origin for invite links, email links, etc. | `http://localhost:3082` |
#### Optional — Direct API Access
Dashboard browser requests use same-origin `/proxy/*` and `/api/auth/*` paths, then the dashboard forwards them to `PRIVATE_SERVER_URL`. Set these only when browsers or third-party clients need to call the API origin directly.
| Variable | Description | Local Default |
|----------|-------------|---------------|
| `PUBLIC_SERVER_URL` | Canonical public API URL / direct API fallback | `http://localhost:3081` |
| `TRUSTED_ORIGINS` | Comma-separated CORS origins for direct browser-to-API calls | — |
#### CSP Domains (Runtime)
CSP domain variables are **runtime** — set them in your `.env` or `docker-compose.yaml` `environment:` section. No image rebuild is needed when changing them.
@@ -89,7 +96,7 @@ CSP domain variables are **runtime** — set them in your `.env` or `docker-comp
| `CSP_MEDIA_SRC_DOMAINS` | Domains allowed in `img-src` and `media-src` |
<Callout type="warn" title="CSP Domains">
When `PUBLIC_IS_SELFHOSTED=true`, the dashboard starts with only `'self'` allowed. Set `ALLOWED_EXTERNAL_DOMAINS` (or the per-directive vars) with your CDN, API, video, and font domains. Since these are runtime env vars, you can change them by restarting the container — no rebuild required.
When `PUBLIC_IS_SELFHOSTED=true`, the dashboard starts with only `'self'` allowed. Set `ALLOWED_EXTERNAL_DOMAINS` (or the per-directive vars) with your CDN, video, and font domains. The API does not need to be added for normal dashboard traffic because requests are proxied same-origin. Since these are runtime env vars, you can change them by restarting the container — no rebuild required.
</Callout>
#### Optional — Email
@@ -127,7 +134,6 @@ Use `./run-docker-full-stack.sh --no-minio` to exclude MinIO if you do not need
| Variable | Description |
|----------|-------------|
| `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` | Google OAuth |
| `AUTH_COOKIE_DOMAIN` | Root domain for cross-subdomain cookies (e.g. `.yourdomain.com`) |
| `PRIVATE_APP_HOST`, `PRIVATE_APP_SUBDOMAINS` | Multi-subdomain routing |
| `UNSPLASH_API_KEY` | Unsplash image search |
| `LICENSE_KEY` | Enterprise features (SSO, token-auth, no-tracking) |
@@ -197,8 +203,6 @@ The quickest hosted deployment is the [Railway Template](https://railway.app/tem
```zsh title="env"
DATABASE_URL="${{db.DATABASE_URL}}"
REDIS_URL="${{Redis.REDIS_URL}}"
PUBLIC_SERVER_URL="https://api.yourdomain.com"
TRUSTED_ORIGINS="https://api.yourdomain.com,https://app.yourdomain.com"
BETTER_AUTH_SECRET="random-secure-key"
AUTH_BEARER_TOKEN="some-key"
PRIVATE_SERVER_KEY="same-key-for-api-and-dashboard"
@@ -207,8 +211,10 @@ PUBLIC_IS_SELFHOSTED="true"
# Dashboard URL for invite/email links (e.g. https://app.yourdomain.com)
DASHBOARD_ORIGIN="https://app.yourdomain.com"
# Required for auth cookies when API and dashboard use different subdomains — set to your root domain, e.g. yourdomain.com
AUTH_COOKIE_DOMAIN="yourdomain.com"
# Optional direct public API URL. Normal dashboard auth/API calls use the
# dashboard proxy and do not require API/dashboard cookie-domain matching.
PUBLIC_SERVER_URL="https://api.yourdomain.com"
TRUSTED_ORIGINS=
# Email (configure one)
SMTP_HOST=
@@ -225,21 +231,17 @@ CLOUDFLARE_BUCKET_DOMAIN=
CLOUDFLARE_IMAGE_BUCKET_DOMAIN=
```
<Callout type="warn" title="AUTH_COOKIE_DOMAIN (Railway)">
When API and dashboard use different subdomains, set `AUTH_COOKIE_DOMAIN` to your root domain (e.g. `yourdomain.com`). Without it, Better Auth cookies will not be set and login will fail.
</Callout>
Optional: add `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` for OAuth, `UNSPLASH_API_KEY` for image search, or `LICENSE_KEY` for enterprise features.
### cio-dashboard
```zsh title="env"
ALLOWED_EXTERNAL_DOMAINS="https://*.yourdomain.com,https://api.yourdomain.com,https://fonts.googleapis.com"
ALLOWED_EXTERNAL_DOMAINS="https://*.yourdomain.com,https://fonts.googleapis.com"
PRIVATE_APP_HOST="https://app.yourdomain.com"
PRIVATE_SERVER_KEY="same-key-for-api-and-dashboard"
PUBLIC_IS_SELFHOSTED="true"
PRIVATE_SERVER_URL="http://${{api.RAILWAY_PRIVATE_DOMAIN}}:8080"
PUBLIC_SERVER_URL="https://api.yourdomain.com"
ORIGIN="https://app.yourdomain.com"
```
Optional: add `PUBLIC_APP_TITLE`, `PUBLIC_APP_DESCRIPTION`, `PUBLIC_OG_IMAGE_URL` for custom branding. You can also use per-directive CSP vars (`CSP_SCRIPT_SRC_DOMAINS`, `CSP_MEDIA_SRC_DOMAINS`, etc.) instead of `ALLOWED_EXTERNAL_DOMAINS` for finer control.
@@ -258,4 +260,4 @@ For hosted deployments, Cloudflare R2 handles object storage. See the [Cloudflar
### SSO (Enterprise)
SSO requires a license key. Set `LICENSE_KEY` in your API environment and add your IdP domains to `TRUSTED_ORIGINS`. [Book a call](http://cal.com/classroomio/enterprise) to get a license.
SSO requires a license key. Set `LICENSE_KEY` in your API environment. [Book a call](http://cal.com/classroomio/enterprise) to get a license.