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
@@ -1,105 +1,29 @@
import type { OrgLandingPageTheme } from './types';
import { baseTokenVars, type LandingThemeVars } from './theme-vars-base';
import { vars as minimalVars } from './minimal/vars';
import { vars as boldVars } from './bold/vars';
import { vars as classicVars } from './classic/vars';
import { vars as saasVars } from './saas/vars';
import { vars as techVars } from './tech/vars';
import { vars as studioVars } from './studio/vars';
import { vars as corporateVars } from './corporate/vars';
import { vars as terminalVars } from './terminal/vars';
import { vars as editorialVars } from './editorial/vars';
import { vars as vibrantVars } from './vibrant/vars';
export type LandingThemeVarName =
| '--landing-bg'
| '--landing-bg-section'
| '--landing-card'
| '--landing-card-soft'
| '--landing-fg'
| '--landing-fg-muted'
| '--landing-fg-faint'
| '--landing-border'
| '--landing-border-soft'
| '--landing-accent'
| '--landing-accent-fg'
| '--landing-button-primary-bg'
| '--landing-button-primary-fg'
| '--landing-button-primary-bg-hover'
| '--landing-button-secondary-bg'
| '--landing-button-secondary-fg'
| '--landing-button-secondary-border'
| '--landing-button-secondary-bg-hover'
| '--landing-button-tertiary-fg'
| '--landing-button-tertiary-bg-hover';
export type LandingThemeVars = Record<LandingThemeVarName, string>;
const baseTokenVars: LandingThemeVars = {
'--landing-bg': 'var(--background)',
'--landing-bg-section': 'var(--muted)',
'--landing-card': 'var(--card)',
'--landing-card-soft': 'var(--muted)',
'--landing-fg': 'var(--foreground)',
'--landing-fg-muted': 'var(--muted-foreground)',
'--landing-fg-faint': 'var(--muted-foreground)',
'--landing-border': 'var(--border)',
'--landing-border-soft': 'var(--border)',
'--landing-accent': 'var(--primary)',
'--landing-accent-fg': 'var(--primary-foreground)',
'--landing-button-primary-bg': 'var(--primary)',
'--landing-button-primary-fg': 'var(--primary-foreground)',
'--landing-button-primary-bg-hover': 'color-mix(in oklab, var(--primary) 88%, black)',
'--landing-button-secondary-bg': 'transparent',
'--landing-button-secondary-fg': 'var(--foreground)',
'--landing-button-secondary-border': 'var(--border)',
'--landing-button-secondary-bg-hover': 'var(--muted)',
'--landing-button-tertiary-fg': 'var(--primary)',
'--landing-button-tertiary-bg-hover': 'var(--muted)'
};
export type { LandingThemeVarName, LandingThemeVars } from './theme-vars-base';
export const LANDING_THEME_VARS: Record<OrgLandingPageTheme, LandingThemeVars> = {
minimal: baseTokenVars,
bold: baseTokenVars,
classic: baseTokenVars,
saas: baseTokenVars,
tech: baseTokenVars,
studio: baseTokenVars,
corporate: baseTokenVars,
vibrant: baseTokenVars,
terminal: {
'--landing-bg': '#06070a',
'--landing-bg-section': '#0c0e13',
'--landing-card': '#0f1218',
'--landing-card-soft': '#14171f',
'--landing-fg': '#e9eaed',
'--landing-fg-muted': '#9da1ab',
'--landing-fg-faint': '#61656f',
'--landing-border': '#1c1f28',
'--landing-border-soft': '#161922',
'--landing-accent': 'var(--primary)',
'--landing-accent-fg': 'var(--primary-foreground)',
'--landing-button-primary-bg': '#f4f5f7',
'--landing-button-primary-fg': '#0a0b0e',
'--landing-button-primary-bg-hover': '#ffffff',
'--landing-button-secondary-bg': 'rgba(255,255,255,0.04)',
'--landing-button-secondary-fg': '#e9eaed',
'--landing-button-secondary-border': '#262a35',
'--landing-button-secondary-bg-hover': 'rgba(255,255,255,0.08)',
'--landing-button-tertiary-fg': 'var(--primary)',
'--landing-button-tertiary-bg-hover': 'rgba(255,255,255,0.06)'
},
editorial: {
'--landing-bg': '#f4f3ed',
'--landing-bg-section': '#ebeae3',
'--landing-card': '#fafaf5',
'--landing-card-soft': '#ecebe5',
'--landing-fg': '#1a1a1a',
'--landing-fg-muted': '#76746c',
'--landing-fg-faint': '#98968e',
'--landing-border': '#d9d8d0',
'--landing-border-soft': '#e3e2da',
'--landing-accent': '#c25237',
'--landing-accent-fg': '#fafaf5',
'--landing-button-primary-bg': '#1a1a1a',
'--landing-button-primary-fg': '#fafaf5',
'--landing-button-primary-bg-hover': '#2c2b29',
'--landing-button-secondary-bg': 'transparent',
'--landing-button-secondary-fg': '#1a1a1a',
'--landing-button-secondary-border': '#d9d8d0',
'--landing-button-secondary-bg-hover': '#ebeae3',
'--landing-button-tertiary-fg': '#c25237',
'--landing-button-tertiary-bg-hover': '#ebeae3'
}
minimal: minimalVars,
bold: boldVars,
classic: classicVars,
saas: saasVars,
tech: techVars,
studio: studioVars,
corporate: corporateVars,
vibrant: vibrantVars,
terminal: terminalVars,
editorial: editorialVars
};
export function themeStyle(theme: OrgLandingPageTheme): string {