albertonline.org docs
Apps

cvm

Internal course video authoring tool for publishing metadata, descriptions, thumbnails, and social posts.

Overview

cvm (Course Video Manager) is an internal authoring tool for the course video publishing workflow — metadata, descriptions, thumbnails, and social posting. It is vendored from an upstream project (mattpocock/course-video-manager, snapshot SHA tracked in .upstream-sha) and ported from React Router v7 to Next.js. It's used by the course-production team, not end users.

Vendored components that haven't been refactored yet rely on a React Router compat shim (app/lib/router-compat.tsx); new code should use next/navigation directly.

Stack

  • Next.js 16 (App Router, Turbopack, React Compiler)
  • Effect 4.0.0-beta.94Context.Service<T>()(name, { make }) pattern, globalThis-cached ManagedRuntime at app/server/runtime.ts, route handlers via runRouteJson (app/server/route.ts)
  • Drizzle 1.0.0-rc.1 RQB — declarative where: { ... } DSL via defineRelations (@/db/schema)
  • Postgres + PGlitepostgres-js in production, in-process PGlite for tests (app/test-utils/pglite.ts)
  • AI SDK 6 + Anthropic, OpenAI, evalite, sandcastle

Develop

pnpm --filter cvm dev     # app + stream-deck-forwarder in parallel
pnpm --filter cvm dev:next  # app only, port 3010
pnpm --filter cvm build
pnpm --filter cvm typecheck
pnpm --filter cvm lint

App runs at http://localhost:3010. Copy .env.example to .env first — DATABASE_URL and ANTHROPIC_API_KEY are the minimum needed to render past the error page.

Test

pnpm --filter cvm test            # vitest run
pnpm --filter cvm test:watch
pnpm --filter cvm test:coverage
pnpm --filter cvm test:e2e        # playwright

Effect tests use @effect/vitest; integration tests compose layers with Layer.provide (order matters — ClipOperations.layer requires DrizzleService).

Build & deploy

pnpm --filter cvm build

Deployed on Vercel (albertonline-org-cvm) at cvm.albertonline.org. Internal tool — runtime needs real DATABASE_URL and API keys set as Vercel env vars.

Structure

  • app/api/ — Next.js Route Handlers (nodejs runtime)
  • app/courses/, app/videos/ — App Router pages (force-dynamic)
  • app/loaders/ — typed loader functions
  • app/features/ — reducer-driven UI domains (course-view, video-editor, …)
  • app/services/ — Effect services (DB functions, clip operations, video, AI, OBS)
  • app/server/ — runtime + route-handler helpers
  • app/lib/router-compat.tsx — React Router compat shim
  • db/ — Drizzle schema (cvmRelations)
  • test-utils/ — PGlite test DB harness, reducer tester

See the apps overview and the monorepo overview.

On this page