Sign inStart creating

Architecture overview

Read this first. Every other doc assumes it.

The one-sentence version

The Media Graph is the memory; vibe directing is the interface; the Model Router is the swappable engine underneath. Everything else is a surface over those three.

Layering

                    ┌──────────────────────────────────────────┐
  SURFACES          │ Creator Studio · Film Studio · Theater ·  │
                    │ Publishing Hub · Admin console           │
                    └───────────────────┬──────────────────────┘
                                        │  server actions + API routes
                    ┌───────────────────▼──────────────────────┐
  SERVICES          │ auth · credits · graph · character ·      │
  (modular          │ script · shots · generation · continuity ·│
   monolith)        │ director · timeline · moderation ·        │
                    │ publishing · theater                     │
                    └───────────────────┬──────────────────────┘
                    ┌───────────────────▼──────────────────────┐
  ORCHESTRATION     │ Model Router — capability matching,       │
                    │ failover, scoring, benchmarking           │
                    └───────────────────┬──────────────────────┘
                    ┌───────────────────▼──────────────────────┐
  ADAPTERS          │ mock (always live) · fal · seedance ·     │
                    │ kling · runway · veo · gemini · audio     │
                    └───────────────────┬──────────────────────┘
                    ┌───────────────────▼──────────────────────┐
  PERSISTENCE       │ Prisma · SQLite (dev) / Postgres (target) │
                    │ + object storage + the GraphEdge table    │
                    └──────────────────────────────────────────┘

Dependencies point downward only. A service may call the Router; the Router must never import a service (it would create a cycle through generation). Adapters know nothing about projects, shots or credits — they receive a GenerationJob and return an AdapterResult.

The rules that keep this coherent

  1. No call site names a provider. Anything above the Router speaks in capabilities. The one deliberate exception is arena mode, which is explicitly a model comparison.
  2. Regeneration reads dependencies from the graph, never from the caller. composeShotPrompt(shotId) takes an id and nothing else; it resolves characters, state, wardrobe, props, location, style and camera itself.
  3. Credits are spent in exactly one placeservices/generation.ts. Reserve before, settle after, refund on failure.
  4. Assets are born in exactly one place — the same file. That is what makes provenance airtight.
  5. Anything the system cannot verify, it reports as unverified. Never "passed" for a check that did not run. This is a correctness rule, not a style preference; see docs/moderation.

Where to change things

I want to…Touch
Add a modelserver/models/registry.ts + a config in server/router/adapters/providers.ts
Add a stylelib/styles/catalog.ts, then reseed. Styles are data.
Change how a shot's prompt is builtserver/services/shots.tscomposeShotPrompt
Change what a cascade touchesserver/services/graph.tsresolveImpact / reindexShotEdges
Add a Director capabilityDIRECTOR_TOOLS + a planOperation case in server/services/director.ts
Change moderation behaviourserver/services/moderation.ts
Move to Postgresprisma/schema.prisma datasource, server/db.ts adapter, server/lib/json.ts, server/lib/vector.ts

Deliberate deviations from the spec

Both are flagged in the README and are reversible.

  • SQLite, not Postgres+pgvector. Zero-infrastructure startup. Schema is Postgres-compatible; three files isolate the difference.
  • One Next.js app, not Next.js + FastAPI. Part 8.1 prescribes "modular monolith first". Service boundaries are real, so extraction is mechanical.

A third, forced by the environment: this machine is Windows on ARM64 and Prisma ships no native engine for it, so the client uses the WASM query compiler over a better-sqlite3 driver adapter.

Request lifecycle: rendering one shot

UI (ShotBoard)
  → server action generateShotAction
    → services/generation.generateShotVideo
      → services/shots.composeShotPrompt      reads the graph
      → services/generation.enqueue           dedupe, estimate, RESERVE credits
        → router.route                        capability match → decision + fallbacks
      → generation.processGeneration
        → router.executeWithFailover          adapter chain, health marking
        → router.scoreGeneration              six-dimension score
        → asset write + provenance + C2PA
        → shot.renderedAssetId updated
        → continuity.lintShot                 amber/red flags
        → credits.settle                      refund the unused reservation
        → recordBenchmark                     Production Intelligence

Every arrow is a function boundary you can test in isolation. scripts/verify-pipeline.ts asserts across all of them.