Founder case study · AI video production

One prompt in.A finished video out.Nothing lost in between.

Idea to Motion is a prompt-to-video production system, designed and built solo across 462 commits: AI plans the script, verifies its claims, voices it, writes real motion-graphics code and renders the video, while a human approves the two moments that matter. This page explains how it works in plain language, then shows the actual code that keeps it honest.

RoleFounder, solo build
TimelineApr-Aug 2026, 462 commits
StackTypeScript, Next.js, Express, BullMQ, Remotion, Postgres, Redis
SurfaceLive studio app + MCP server for external agents

If you read nothing else

  • What it is. Type a topic; get a scripted, fact-checked, voiced, animated and rendered video. Every step is visible and editable in a live studio, so the result is a project you shaped, not a black-box clip.
  • The hard problem. Probabilistic models, AI-written executable code, long media jobs and human review have to cooperate without one failure destroying the project. The answer is a checkpointed state machine: every stage is a persisted checkpoint in Postgres, and any crash resumes exactly where it stopped.
  • The trust problem. The AI writes real React code for every scene, and that code is treated as untrusted input. It must pass eight numbered static checks beginning with an esbuild compile, a sandboxed three-frame test render with a five-second kill switch, and a layout audit before it may join the video.
  • The open factory. The whole pipeline is also exposed over MCP with 26 tools and OAuth 2.1. An external agent can bring its own model for the script, the direction and the code, and every submission still passes the same gates.
01Compose

The product, from the creator's seat

One idea.
One production workspace.

Choose the format, voice, and visual language. The system turns that intent into a reviewable video project, not one opaque AI request.

NEW EXPLAINERideatomotion.com / studio
WHAT SHOULD THE VIDEO EXPLAIN?Why do distributed systems fail in surprising ways?
FORMATReel · 9:16
DURATION60 seconds
THEMEStudio
VOICEAria
02Review before render

The work stays
visible.

Five reader-facing phases. One project moves forward without hiding the decisions.

The product streams a scene-based script, verifies claims, generates voice and visual direction, reveals scene previews progressively, then lets the creator edit and approve the composition before rendering.

03Recover

Pull the process.
Keep the work.

The worker is temporary. The project state is not.

When a code-generation worker fails at stage eight, PostgreSQL retains the current stage and completed artifacts. BullMQ retries that stage, and buffered events help a reconnecting browser catch up before returning to live progress.

PROCESS LOST
POSTGRES CHECKPOINTStage 07 + completed artifacts remain
NEW WORKERResume code generation
04Validate

Code is a proposal.
Not permission.

Every scene crosses explicit gates before it joins the video.

All generated scene code is compiled with esbuild and inspected for known hazards. MCP client scene submissions additionally render the first, middle, and final frame in an isolated worker thread with a five-second timeout.

INPUTGenerated JSX<Scene progress={frame} />
GATE 01Compileesbuild parses JSX
GATE 02Inspectknown runtime hazards
OUTPUTComposejoin the timeline
MCP SUBMISSIONS ONLY3-frame smoke render
0½1
isolated worker · 5s ceiling
05Connect · create · render

Your AI brings the brain.
Idea to Motion brings the studio.

One MCP entry in the client you already use. Your assistant supplies the reasoning; the server keeps the contracts, and every script, direction and scene it submits passes the same gates as the web app.

IDEA TO MOTIONMCP CONNECTED
Idea to Motion connect page: pick an MCP client, then add the server with one command
RENDERED · MP4 READY

From one prompt — typed in the studio, or spoken to your own agent — to an editable, recoverable production workspace.

Open live product

The pipeline, precisely.

The chapters above compress what is really eleven stages on the narrated route. These are the actual stage names from the code, in the order the state machine allows them to run.

01Script

Researches the topic and writes a scene-by-scene script, streamed to the browser token by token.

script_generation
02Fact check

Verifies claims against live Google Search. Contradicted lines are rewritten against the evidence; if the checker itself fails, the script continues to review marked unverified.

fact_check
03Script review

The creator edits and approves the script before any money is spent producing it.

script_review
04Voice

ElevenLabs or Cartesia — on the creator's own API key — or a local GPU voice sidecar with the identical contract, speaks the script and returns word-level timing.

tts_generation
05Transcription

Facecam footage is transcribed with word timestamps; faceless videos skip the call because voice timing already exists.

transcription
06Timestamp map

Every script line is pinned to exact start and end times on the voice track.

timestamp_mapping
07Direction

Timed lines become visual direction: beats, layouts, brand assets and motion for each scene.

direction_generation
08Code

An agent writes real React/Remotion code per scene. Every file faces the validation gates before composition.

code_generation
09Preview

The creator works the real composition in a scene-based editor with a timeline, tweaks it by chat or direct manipulation, and approves the render.

preview
10Render

Headless Chromium renders h264 at 30fps, at the resolution tier the account allows; audio is loudness-normalized to the -14 LUFS social standard.

rendering
11Done

MP4, a midpoint-frame thumbnail and generated social metadata land in object storage.

done

The stage enum holds eighteen values, not eleven: facecam projects insert facecam_editing and facecam_review after Voice, and uploaded-footage projects take a separate creator route through creator_ingest, creator_edit_direction, creator_composite, creator_preview and creator_render. Silent motion graphics skip voice and transcription entirely. The enum is append-only so database indices stay stable across migrations: the transition map, not the enum order, is the real graph.

Read the actual code.

Four excerpts quoted from the private repository, with paths, so the claims on this page stay checkable rather than atmospheric.

the state machine says nopipeline/domain/entities/pipeline-job.ts
if (!this.props.stage.canTransitionTo(targetStage)) {
  return Result.fail(
    new ValidationError(
      `Cannot transition from "${this.props.stage.value}"
       to "${targetStageValue}"`,
      "INVALID_TRANSITION",
    ),
  );
}
The domain entity owns the workflow. A worker cannot skip a stage, and artifact setters are stage-guarded too: generated code can only be attached during code_generation. Failures return typed Results; exceptions are never used for control flow.
retries follow economicspipeline/infrastructure/queue/pipeline-queue.ts
/* abridged: per-stage BullMQ policy */
script_generation:    { attempts: 3, delay: 2000 },
direction_generation: { attempts: 3, delay: 5000 },
transcription:        { attempts: 1, delay: 1000 },
rendering:            { attempts: 1, delay: 1000 },
Flaky LLM stages get three attempts with exponential backoff. Expensive, billable stages like rendering and transcription get exactly one: a failed job is resumed deliberately from its checkpoint, never silently re-billed.
locks sized to realitypipeline/infrastructure/queue/worker-registry.ts
// BullMQ defaults: lockDuration=30s, stalledInterval=30s.
// Our facecam editing stage (Scribe transcription) can
// take 2-5 minutes for long videos, so a default lock
// would mark a healthy worker as stalled.
lockDuration: 600_000,   // 10 minutes
stalledInterval: 300_000 // 5 minutes
Media jobs are long. The lock is sized for that, long stages extend it mid-flight, and a worker-level failure listener persists the failed state and emits a final progress event, so the browser never spins forever, even after an out-of-memory kill.
untrusted code, bounded blast radiuspipeline/infrastructure/services/remotion-client-scene-code.service.ts
const SMOKE_RENDER_TIMEOUT_MS = 5000;

const frames = [0, Math.floor(durationInFrames / 2),
  durationInFrames - 1];
for (const frame of frames) {
  currentFrame = frame;
  renderToStaticMarkup(
    React.createElement(Main, { scene, scenePlan }));
}
Externally submitted scene code executes inside a worker thread with mocked Remotion globals, rendered at the first, middle and final frame. A five-second ceiling kills infinite loops without ever blocking the API event loop.

Technical depth

Under
the hood.

Exact architecture, the reliability mechanisms, and the decision record with tradeoffs stated, closing with the boundary of what this page does and does not claim.

17AI agentsPer-agent model + temperature
86Use-casesApplication layer, Result-typed
210Test files55 property-based suites
60Animation themesStudio to Neo-Brutalist
A / Architecture

Four layers.
One protected workflow.

01

Presentation

HTTP, SSE, UI, controllers

Next.js feature modules and Express controllers translate product actions into use-case requests. Server-sent events stream progress with sequence ids and 15-second heartbeats, and interactive MCP Apps render the same state inside an agent's chat.

presentation/controllers · SSE helpers · MCP routes
02

Application

Use cases and orchestration

86 use-cases coordinate repositories, queues, model ports, storage and streaming, returning explicit Result values instead of using exceptions for control flow.

application/use-cases · Result<T, E> everywhere
03

Domain

Rules, state, invariants

PipelineJob owns legal stage transitions, stage-guarded artifact setters, progress state and failure state. Infrastructure cannot redefine the workflow's business rules.

PipelineJob.transitionTo() · setGeneratedCode() guards
04

Infrastructure

Providers and persistence

Prisma, 14 BullMQ workers, Redis, five routable model providers, two TTS backends, object storage, Remotion and FFmpeg sit behind interfaces, wired at explicit composition roots. Rendering itself is a swappable provider: in-process, or a separate HTTP render service.

repositories · workers · service adapters · ModelRegistry
B / Reliability

Failure is bounded,
not denied.

R1

Checkpoint the work, not just the status

One Postgres row per job stores the script, fact-check report, audio path, transcript, scene directions, generated code and rendered asset paths. Every worker saves immediately after each legal transition, so the database advances in lockstep with the state machine and any job can be understood from durable state alone.

PostgreSQL · Prisma upsert
R2

Retry according to stage economics

Per-stage BullMQ policy: three attempts with exponential backoff where models are flaky, exactly one where output is expensive or billable. Failed jobs are cleared and resumed from their checkpointed stage rather than restarted.

BullMQ · per-stage policy
R3

Replay progress after a disconnect

Progress events publish live over Redis and append to a durable list. A reconnecting browser replays the buffer in order, then rejoins the live channel; buffers expire an hour after completion. Once a stage is durable, Postgres, not the buffer, is the source of truth, so a refresh can never resurrect pre-edit content.

SSE · Redis buffer · seq ids
R4

Never leave the interface spinning

A worker-level failure listener catches even out-of-memory kills, persists the failure and emits a terminal progress event. Locks run ten minutes with five-minute stall checks, and long stages extend their lock mid-flight.

Failure listener · 10-min lock
R5

Treat generated code as untrusted input

Every scene faces eight numbered checks, learned from real failures and beginning with an esbuild compile: lowercase img tags, dead logo CDNs, frame arithmetic bugs, unknown icon names, hallucinated identifiers and more. Errors return to the model as targeted repair hints; in preview, an agentic autofixer isolates the crashing scene and patches it surgically.

esbuild · 8 static gates · autofixer
R6

Bound runtime validation

Client-submitted scenes additionally render three frames inside an isolated worker thread with mocked Remotion globals and a five-second timeout, then pass a layout audit for unclamped animations and under-built scenes.

worker_threads · 5s ceiling
C / Decision record

Explicit choices.
Visible tradeoffs.

D-01

A state machine over a giant request

Context
Video generation crosses slow model calls, speech services, asset storage, code execution and headless rendering.
Decision
Model the product as durable stages owned by a domain entity and execute processing stages through a queue.
Tradeoff
More operational machinery and transition rules, in exchange for resumability, visibility and isolated failure.
D-02

Human review before expensive production

Context
A fluent script can still be wrong, off-brand, or simply not what the creator wants. Downstream audio and rendering amplify that mistake.
Decision
Fact-check generated claims, then pause for script approval; pause again at browser preview before export.
Tradeoff
The flow is not fully autonomous, but user judgment is applied at the two points where it prevents the most wasted work.
D-03

Provider routing per responsibility

Context
Seventeen agent roles, from script writing to thumbnail generation, have different model needs and cost profiles.
Decision
Resolve models by named agent through a ModelRegistry defaulting to the Vercel AI Gateway, with TTS, transcription, storage and image lookup behind ports; creators supply their own voice key, and a local GPU sidecar can replace paid TTS with an identical contract.
Tradeoff
Configuration becomes a system of its own, but provider changes never require rewriting the workflow or domain.
D-04

Share contracts with client-driven AI

Context
An MCP client can provide its own reasoning model, but bypassing server constraints would create a second, lower-quality pipeline.
Decision
Let client-driven jobs submit scripts, directions and scene code through the same schemas, validation gates, composition logic and persisted state, across 26 MCP tools with OAuth 2.1.
Tradeoff
The protocol is more involved, but the server keeps product invariants while the client supplies the intelligence.
D-05

Move rendering off the API box

Context
Headless Chromium and FFmpeg are the memory-hungriest things in the system, and they were OOM-killing the process that also had to answer HTTP.
Decision
Put rendering behind a RENDER_PROVIDER factory: in-process by default, or a separate render service reached over HTTP with cold-start retry and a mid-render heartbeat.
Tradeoff
One more deployable and a network hop on every export, in exchange for an API that stays responsive and export tiers that can scale on their own hardware.
D / Evidence boundary

Credibility includes
what is not claimed.

Repository demonstrates

  • A real multi-application product with domain boundaries and explicit composition roots
  • Persistent workflow state, queued execution, replayable progress and stage-aware recovery
  • Generated-code validation built from observed failure modes rather than a generic AI wrapper
  • Continuous evolution across UI, media infrastructure, AI providers, auth, billing, observability and deployment

Not claimed without product data

  • Production throughput, uptime, revenue or user adoption
  • A universal success-rate or quality benchmark
  • Independent source inspection while the application repository remains private
  • That every workflow follows one fixed number of stages

How it was built.

A hundred and thirty-one days from empty repository to a launched product with billing, accounts and an open agent protocol, in seven phases.

17 Apr

Architecture before features

Turborepo foundation, infrastructure services and a Clean Architecture scaffold.

18-20 Apr

From pipeline to recoverable pipeline

Core faceless flow, SSE progress, browser preview, job retry, code autofix and reconnect replay.

29 Apr-04 Jun

Observe and harden

Langfuse and OpenTelemetry tracing, code validation, render timeouts, live render progress and manual editing.

08-19 Jun

Expand the product surface

Uploaded-video and facecam workflows, retake control, background removal and creator-edit direction.

02-11 Jul

Expose the factory over MCP

Client-driven creation, OAuth 2.1, per-scene briefs, parity gates and interactive MCP Apps, then Chromium and memory fixes, retryable exports and script fact checking.

22 Jul-12 Aug

Become a product, not a project

Accounts and access tiers, a credits paywall with Dodo payments, an admin dashboard, bring-your-own voice keys, 4K export with per-resolution caching, and rendering split out into its own service.

17-26 Aug

Rebrand and open the front door

The ideatomotion.com cutover, a server-rendered marketing site with one-click Google sign-in, silent motion graphics, recorded-video workflows, bring-your-own music, and a scene-based timeline editor.