Learn how the system generates React/Remotion animation code using one-shot prompts and constants-first design.
The code generation system transforms natural language prompts into working React/Remotion animation components using a one-shot generation approach with structured system prompts and optional skill-specific guidance.
The base system prompt defines the component structure, coding rules, and available APIs. It’s the foundation that ensures consistent, high-quality output.
const SYSTEM_PROMPT = `You are an expert in generating React components for Remotion animations.## COMPONENT STRUCTURE1. Start with ES6 imports2. Export as: export const MyAnimation = () => { ... };3. Component body order: - Multi-line comment description (2-3 sentences) - Hooks (useCurrentFrame, useVideoConfig, etc.) - Constants (COLORS, TEXT, TIMING, LAYOUT) - all UPPER_SNAKE_CASE - Calculations and derived values - return JSX## CONSTANTS RULES (CRITICAL)ALL constants MUST be defined INSIDE the component body, AFTER hooks:- Colors: const COLOR_TEXT = "#000000";- Text: const TITLE_TEXT = "Hello World";- Timing: const FADE_DURATION = 20;- Layout: const PADDING = 40;This allows users to easily customize the animation.
From src/app/api/generate/route.ts:39-62
The constants-first design is critical for user customization. By defining all magic numbers and strings as named constants, users can quickly adjust colors, text, timing, and layout without hunting through JSX.
## ANIMATION RULES- Prefer spring() for organic motion (entrances, bounces, scaling)- Use interpolate() for linear progress (progress bars, opacity fades)- Always use { extrapolateLeft: "clamp", extrapolateRight: "clamp" }- Add stagger delays for multiple elements
## LAYOUT RULES- Use full width of container with appropriate padding- Never constrain content to a small centered box- Use Math.max(minValue, Math.round(width * percentage)) for responsive sizing
The system prompt lists all whitelisted libraries:
## AVAILABLE IMPORTS```tsximport { useCurrentFrame, useVideoConfig, AbsoluteFill, interpolate, spring, Sequence } from "remotion";import { TransitionSeries, linearTiming, springTiming } from "@remotion/transitions";import { fade } from "@remotion/transitions/fade";import { slide } from "@remotion/transitions/slide";import { Circle, Rect, Triangle, Star, Ellipse, Pie } from "@remotion/shapes";import { ThreeCanvas } from "@remotion/three";import { useState, useEffect } from "react";
From `src/app/api/generate/route.ts:78-86`### Reserved namesTo prevent variable shadowing bugs, the system warns about reserved names:```typescript## RESERVED NAMES (CRITICAL)NEVER use these as variable names - they shadow imports:- spring, interpolate, useCurrentFrame, useVideoConfig, AbsoluteFill, Sequence
## OUTPUT FORMAT (CRITICAL)- Output ONLY code - no explanations, no questions- Response must start with "import" and end with "};"- If prompt is ambiguous, make a reasonable choice - do not ask for clarification
From src/app/api/generate/route.ts:100-105This strict output format enables streaming text to be directly inserted into the code editor without parsing.
Follow-up edits use a different system prompt optimized for targeted changes:
const FOLLOW_UP_SYSTEM_PROMPT = `You are an expert at making targeted edits to React/Remotion animation components.Given the current code and a user request, decide whether to:1. Use targeted edits (for small, specific changes)2. Provide full replacement code (for major restructuring)## WHEN TO USE TARGETED EDITS (type: "edit")- Changing colors, text, numbers, timing values- Adding or removing a single element- Modifying styles or properties- Small additions (new variable, new element)- Changes affecting <30% of the code## WHEN TO USE FULL REPLACEMENT (type: "full")- Completely different animation style- Major structural reorganization- User asks to "start fresh" or "rewrite"- Changes affect >50% of the code## EDIT FORMATFor targeted edits, each edit needs:- old_string: The EXACT string to find (including whitespace/indentation)- new_string: The replacement stringCRITICAL:- old_string must match the code EXACTLY character-for-character- Include enough surrounding context to make old_string unique- If multiple similar lines exist, include more surrounding code- Preserve indentation exactly as it appears in the original
Targeted edits are applied using exact string matching with validation:
function applyEdits( code: string, edits: EditOperation[],): { success: boolean; result: string; error?: string; enrichedEdits?: EditOperation[]; failedEdit?: EditOperation;} { let result = code; const enrichedEdits: EditOperation[] = []; for (let i = 0; i < edits.length; i++) { const edit = edits[i]; const { old_string, new_string, description } = edit; // Check if the old_string exists if (!result.includes(old_string)) { return { success: false, result: code, error: `Edit ${i + 1} failed: Could not find the specified text`, failedEdit: edit, }; } // Check for multiple matches (ambiguous) const matches = result.split(old_string).length - 1; if (matches > 1) { return { success: false, result: code, error: `Edit ${i + 1} failed: Found ${matches} matches. The edit target is ambiguous.`, failedEdit: edit, }; } // Get line number before applying edit const lineNumber = getLineNumber(result, old_string); // Apply the edit result = result.replace(old_string, new_string); // Store enriched edit with line number enrichedEdits.push({ description, old_string, new_string, lineNumber, }); } return { success: true, result, enrichedEdits };}
From src/app/api/generate/route.ts:197-251
Edit operations require exact character-for-character matching. If the old string isn’t found or matches multiple locations, the edit fails and triggers error correction.
From src/app/api/generate/route.ts:388-392This allows the model to access specialized knowledge for charts, typography, 3D, etc. without bloating the base prompt.
If generated code has compilation errors or edit operations fail, the system automatically retries with error context:
let errorCorrectionNotice = "";if (errorCorrection) { const isEditFailure = errorCorrection.error.includes("Edit") && errorCorrection.error.includes("failed"); if (isEditFailure) { errorCorrectionNotice = `## EDIT FAILED (ATTEMPT ${errorCorrection.attemptNumber}/${errorCorrection.maxAttempts})${errorCorrection.error}CRITICAL: Your previous edit target was ambiguous or not found. To fix this:1. Include MORE surrounding code context in old_string to make it unique2. Make sure old_string matches the code EXACTLY (including whitespace)3. If the code structure changed, look at the current code carefully`; } else { errorCorrectionNotice = `## COMPILATION ERROR (ATTEMPT ${errorCorrection.attemptNumber}/${errorCorrection.maxAttempts})The previous code failed to compile with this error:${errorCorrection.error}CRITICAL: Fix this compilation error. Common issues include:- Syntax errors (missing brackets, semicolons)- Invalid JSX (unclosed tags, invalid attributes)- Undefined variables or imports- TypeScript type errorsFocus ONLY on fixing the error. Do not make other changes.`; }}
From src/app/api/generate/route.ts:418-462
The system provides specific guidance based on the error type (edit failure vs compilation error) to help the model self-correct.