Lesson Animation Studio  ·  project briefLesson Animation Studio — Project Brief

Lesson Animation Studio — Project Brief

Lesson Animation Studio — Project Brief

Status: APPROVED, NOT STARTED. Deferred by the user (Sep 2026): *"this is for a separate

project.. not now."* Everything needed to start cold is in this document.

Locked decisions (user, Sep 2026):

  • 1. Form: a full browser Studio — author scenes, edit captions, preview, render from a UI.
  • 2. Sequencing: design directions first. Produce 2–3 animation design directions as
  • stills for approval *before* building the pipeline. (High design bar — do not build a

    pipeline around a look that hasn't been approved.)

  • 3. It is a separate project — not a feature bolted into Master B or any single product.
  • 4. TARGET THE FOREX PRODUCT FIRST. User, Sep 2026: *"we need to focus on forex because future
  • website was not completed."* Master B (futures) is an incomplete product — treat it as

    secondary and do not let it drive scope or sequencing. All design-direction work, token

    extraction and rollout planning should be forex-first.


    0. STEP 1 DELIVERABLE — design directions (BUILT, awaiting approval)

    https://animation-directions.srv1738752.hstgr.cloud — 3 directions, 22 plates, each with a

    4-frame storyboard (stills) and a live motion stage, all rendered in forex's own tokens from

    forex's own lesson content.

    #DirectionRegisterDefault for
    ADesk Blueprintmeasured, annotated schematic; left price axis; mono numerals; a live READOUT panel; cyan used only for the thing being taughtpattern, chart, formula, animatedSequence
    BLiquid Glassbuilt from the app's own parts: glass card, gradient wash, chip rail, navy→cyan rail, glow on the decisive candlemotionGraphic, liveChartDemo, simulatorEmbed, hero moments
    CEditorial Instructortype-led; navy rail; the lesson's own caption as the headline; one cyan underline; chart only as a specimencallout, proTip, socratic, openResponse (the long text)

    Recommended shape: A as default, B for hero/simulator, C for text-heavy lessons — three

    registers of one system, so 57 lessons of clips do not all look like a template.

    Built by directions/build.py (stdlib only) → directions/site/index.html, served from

    /var/www/animation-directions on VPS port 8144 (route animation-directions.yml).

    Still PNGs of every plate: .../frames/big2-*.png.

    Content provenance (nothing invented): the demo section is the lesson's *real*

    animatedSequence — M2 L3 "Hammer & Hanging Man", 4 steps with its own labels/captions — and the

    gate plate uses that lesson's *real* quiz entry ("The lower shadow of a Hammer should be at least

    …" → "2x the body length"). Formula plates use M5 L2's real Position Size formula and worked

    numbers. Tokens were re-read from the live CSS (:root verified 2026-09-12), not from this doc.

    Rules the directions encode (carry these into the engine):

  • The lesson's own caption text is the copy; never rewrite it for animation.
  • Cyan is the *single* attention accent. If cyan is on more than one thing per frame it is a bug.
  • Nothing is measured in prose that could be measured on screen (the Hammer's "2x the body"
  • becomes a bracketed measurement).

  • The mastery gate uses the lesson's own quiz array — no invented assessments.
  • A clip frame carries no meta/name-tag chrome; direction names belong in the review page.
  • Fixed candle grid across all steps, so nothing jumps when a step changes.

  • 1. The problem it solves (evidence, not conjecture)

    From the verified Master B deployment audit:

  • 26 interactiveVideo slots are dead. The live bundle contains 26 entries pointing at
  • https://www.youtube.com/watch?v=…, but the renderer builds a native

    <video src={data.url}> and there is zero YouTube/iframe/embed conversion anywhere in the

    build. None of the 26 has ever played.

  • The pausePoints mastery gate is implemented but used by zero content. The renderer fully
  • implements pause-at-timestamp + require-a-correct-answer-to-continue.

  • 11 rich section types are built, wired, and empty: motionGraphic, animatedSequence,
  • scrollyStory, liveChartDemo, simulatorEmbed, flashcard, tabbedDeepDive, chart,

    pattern, divider — each has 0 content using it.

  • Video is the stalest asset in the platform. Lesson content is baked into the JS bundle
  • (assets/index-*.js), so changing a lesson requires a full rebuild + redeploy.

  • The platform's own AnimatedSequencePlayer / AnimationStep model is pattern-cards, not
  • real animation.

    Net: a rich learning feature set with its entire animation and video tier either broken or

    unpopulated.

    ⚠️ This is MASTER B–SPECIFIC — forex is the opposite case

    Verified against the live forex app (Blue Monkee Trading,

    limegreen-eagle-892117.hostingersite.com). Do not generalise the Master B defects:

    Master B (futures)Forex / Blue Monkee
    Video section typeinteractiveVideo × 26videoOverview × 9
    Video sourceYouTube watch URLsself-hosted /media/videos/hank-*.mp4
    Do they play?No — a native <video src> cannot play a watch URLYes — real MP4s, files present in public/media/videos/
    YouTube URLs in bundle26 (all dead)0
    pausePointsimplemented in the renderer, 0 contentnot present at all
    Animation section typesdefined, 0 content eachactually usedmotionGraphic, animatedSequence, scrollyStory, liveChartDemo, simulatorEmbed, tabbedDeepDive (1 each)
    Section vocabulary21 typesricher — also audioReadalong, socratic, application, openResponse, skipCriteria, videoOverview, mindmap, infographic, slidedeck

    So forex already solved video the right way (self-hosted MP4s, no YouTube), and its animation

    slots are populated. The user's statement *"we don't use any youtube videos on the website"* is

    literally true for forex and effectively true for Master B (its YouTube links are dead).

    What forex still lacks — and why the Studio is still worth building for it:

  • 1. Its animatedSequence / motionGraphic are step cards ({label, caption, durationMs}),
  • not real animation — a carousel with SVG patterns.

  • 2. Its 9 MP4s are recorded (Hank's session recordings), not generated — not parameterised, and
  • they drift from lesson text over time.

  • 3. It has no mastery gate at all, even though Master B's code proves the gate works.
  • Net framing per product: Master B = *repair dead video slots and fill empty animation slots*.

    Forex = *upgrade step-cards to real animation, add gates to working video, and make video

    generatable instead of recorded.* Both point at the same Studio.

    Forex in numbers (the product we are actually targeting)

    9 modules · 57 lessons · ~2,400 lines of authored content. Section usage across the live app:

    TypeUsesNote
    text / multipleChoice / heading / callout220 / 177 / 154 / 49the backbone
    application33applied tasks — heavy, real usage
    flashcard24Master B: 0
    keyValue / comparison / proTip22 / 20 / 18
    chart / pattern11 / 10static SVG today
    audioReadalong / mindmap / infographic / slidedeck10 eachrich types, genuinely used
    videoOverview9real self-hosted MP4s
    skipCriteria / formula / fillInBlank / ordering / socratic8 / 6 / 4 / 3 / 3
    animatedSequence / motionGraphic / scrollyStory / liveChartDemo / simulatorEmbed / tabbedDeepDive / openResponse1 eachdefined, demonstrated once, essentially unused

    So forex's animation tier is a token presence, not a real one — one use each, as step cards.

    Meanwhile its non-animation rich types (flashcard, application, audioReadalong, mindmap,

    infographic, slidedeck) are the *actual* differentiators and are heavily used. The Studio's

    job on forex is to make the animation tier match that standard.

    Video assets: 9 MP4s, ~333 MB total (hank-*.mp4, 26–52 MB each).

    > ⚠️ Do NOT try to replace the 9 Hank videos with animation. They are **authentic recorded

    > trading sessions** — real footage of real sessions. Animation cannot substitute for that and an

    > attempt would be a downgrade. The Studio's value on forex is the animation *tier* (pattern,

    > chart, formula, the 1-each animation slots) plus adding the mastery gate — not replacing

    > footage.

    Forex's video section shape (no dedicated TS interface — inline):

    { type: "videoOverview", videoOverview: { videoUrl, title, description } }

    2. What the Studio is

    A separate pipeline + web app that turns lesson content into **branded, precise, gated

    animated clips, and publishes them so any product can consume them without a rebuild**.

    LayerOwns
    Design systemPer-product animation theme derived from that product's own design tokens. There is no single house style — each brand animates in its own palette/type.
    Scene libraryParameterised reusable primitives: candlestick, candle series, floor/ceiling, Fibonacci retracement, annotation callout, formula, timeline, comparison, order-ticket.
    Scene specsOne spec per lesson section, as data (YAML/JSON): primitive, params, captions, and pause-point timings. Content, not code.
    Render workermanim (Docker) on the VPS. Spec → MP4. Deterministic, batchable, no per-render cost.
    Manifest + review surfacePublishes {lesson, section, clipUrl, duration, pausePoints} plus a gallery URL to approve clips before they ship.
    Studio UIBrowser authoring: pick a scene, edit captions/copy, set pause points, preview, render, publish.

    The strategic point

    Consumers read the manifest at runtime, so publishing a clip is not a rebuild. This inverts

    the current model where video is baked into the bundle and 26 slots point at unplayable URLs.

    It is the same principle the user already applies everywhere else: *derive from the canonical

    source at render time, never embed a stale copy.*

    3. Design system requirements

    The first pilot clip was rejected on design — correctly. It used generic Tailwind green/red and

    manim's default LaTeX serif. The fix is grounding animation in each product's real tokens.

    Master B tokens (extracted from masterb-compass/src/index.css + tailwind.config.ts):

    TokenValue
    --background0 0% 7%
    --foreground0 0% 92%
    --card / --secondary / --muted0 0% 10% / 0 0% 16% / 0 0% 14%
    --primary0 72% 50%brand red
    --accent32 95% 55%amber
    --border0 2% 20%
    --chart-green142 76% 45%
    --chart-red0 72% 50%
    --chart-amber32 95% 55%
    --chart-blue205 80% 55%
    --chart-purple270 60% 55%
    --glass / --glass-border0 0% 8% / 0.85 / 0 0% 22%
    gradients--gradient-primary 135° red→red, --gradient-accent amber→amber, --gradient-hero subtle
    --shadow-glow0 0 24px red @ 0.2
    --radius0.375rem
    fontsRajdhani (display), Inter, JetBrains Mono

    Forex / Blue Monkee tokens — PRIMARY TARGET (extracted from /workspace/trade-compass)

    TokenValue
    background / foreground220 30% 98% / 222 35% 12%LIGHT theme
    card / popover0 0% 100%
    primary224 84% 34%deep navy
    accent224 84% 28%
    secondary / muted222 28% 94% / 220 26% 94%
    border222 20% 88%
    radius0.7rem
    chart-green / -red / -amber / -blue / -purple / -cyan158 84% 39% / 0 72% 51% / 38 92% 50% / 217 91% 60% / 262 65% 60% / 189 100% 45%
    glass / glass-border220 30% 98% / 0.85 / 222 20% 86%
    gradientsprimary navy→navy · accent cyan→navy · hero navy/cyan
    shadow-glow0 0 20px navy @ 0.14
    fontsInter (sans) + DM Sans + JetBrains Mono — *not* Rajdhani

    A dark variant also exists (background: 224 55% 8%, card: 224 48% 12%,

    foreground: 220 40% 95%), so the ideal theme is light-first and dark-capable.

    > ⚠️ Critical: forex is light-themed and Master B is dark-themed. An animation styled

    > for Master B (black canvas, red/amber accents, Rajdhani) will look wrong on forex. The two

    > brands share *no* type or palette — do not reuse a theme across them.

    Design implications:

  • Use Rajdhani, not LaTeX's Computer Modern, for all non-mathematical text. LaTeX stays only
  • for genuine formulas.

  • Use the chart-\* palette for market data, never generic greens/reds.
  • Use glass panels, the red/amber gradients, and the subtle glow so a clip reads as native to the
  • product.

  • Rajdhani is a Google font — it must be installed inside the manim Docker image (or shipped
  • as a .ttf and registered with Pango). Not present by default.

  • Other products (trade-compass/forex, Unified education, The Rec, Arnow) each need their own
  • token extraction; do not reuse Master B's theme across brands.

    4. Content model sketch

    # specs/masterb/m1-l2-candle-anatomy.yaml
    product: masterb
    lesson: {module: 1, id: 2}
    scene: candle_anatomy
    params:
      open: 0.30
      close: 1.50
      high: 1.90
      low: -0.50
      labels: [High, Closed, Opened, Low]
      definitions:
        - {text: "Highest price reached", token: chart-green}
        - {text: "Where the period ended", token: foreground}
        - {text: "Where the period started", token: chart-blue}
        - {text: "Lowest price reached", token: chart-red}
    beats:
      - {at: 6.5,  hold: 2.6}
      - {at: 12.5, hold: 4.2}
    pausePoints:
      - atSeconds: 6.5
        question: "\"Where the period ended\" refers to which point on the candle?"
        options: [Opened, Closed, High, Low]
        correctAnswer: Closed

    Rule: reuse the lesson's own quiz questions/options for pause points. Do not invent new

    assessments — pull from the existing quiz array wherever possible.

    Timing rule: every pause point needs a hold. A gate landing mid-animation gives the learner

    nothing to look at while answering. Holds of ~2.5–4 s per gate worked in the pilot.

    5. Render pipeline

  • manim Community v0.21 in Docker (manimcommunity/manim:stable), CPU only, no GPU
  • VPS: image already pulled (2.03 GB), render of two ~15 s scenes took ~35 s total
  • $0 per render, no API calls, fully deterministic
  • Target output: 1920×1080 @ 30 or 60 fps for production (pilot was 720p30)
  • --user root plus a world-writable bind mount is required (the image runs non-root) — see
  • ai-video-pipeline/references/manim-clinical-animation.md for the verified invocation and the

    full pitfall list

  • Serving: on the VPS use /opt/spa-range/spa_range_server.py (SPA fallback + HTTP Range).
  • On Hostinger/Apache, Range is native — only .htaccess SPA fallback is needed.

    6. Integration model

    Preferred (and the reason this is worth doing): runtime manifest fetch.

  • 1. Studio publishes clips + manifest.json to a host.
  • 2. Each product adds a thin hook that fetches its lessons' clips at runtime.
  • 3. Missing clip → falls back to the existing inline content (never a broken player).
  • 4. Adding/changing a clip = publish. No app rebuild.
  • This also repairs the 26 dead slots: they become manifest entries with real MP4 URLs, and their

    pausePoints finally become reachable.

    A fallback option (less good) is build-time bundling, which reintroduces the rebuild-to-change

    problem.

    7. Build sequencing

    Forex-first. Master B (futures) is an incomplete product — do not let it drive scope.

  • 1. Design directions (first, per locked decision) — 2–3 still-frame animation design
  • directions in the forex/Blue Monkee tokens: light canvas, navy 224 84% 34% primary,

    cyan 189 100% 45% accent, the chart-* palette, Inter/JetBrains Mono. Get approval.

    Reject/iterate before any pipeline work. (Optionally include one dark-variant frame, since

    forex ships a dark mode.)

  • 2. Engine: design tokens + scene library + spec parser + Docker render worker. Prove one
  • scene end-to-end from a spec file, themed for forex.

  • 3. Manifest + publish + gallery review surface.
  • 4. Studio UI: author/edit/preview/render/publish in the browser.
  • 5. Rollout on forex: target pattern (10), chart (11), formula (6) and the 1-each
  • animation slots first — these are the animation-shaped content. Wire the runtime integration.

    Do not replace the 9 Hank session videos.

  • 6. Master B only afterwards, once that product is actually finished.
  • 8. Already proven (reusable starting points)

    ThingWhere
    Working gated clip in a real lessonhttps://masterb-pilot.srv1738752.hstgr.cloud/learn/1/2
    Verified manim render recipe + pitfallsai-video-pipeline/references/manim-clinical-animation.md
    Master B deployment reality + bundle-patch preview techniquetrade-platform-builder/references/masterb-deployment-and-pilot.md
    Scene source (pilot)/workspace/manim-test/pilot_lesson2.py
    Scene source (demo clips)/workspace/manim-test/masterb_candles.py
    SPA + Range server/opt/spa-range/spa_range_server.py
    Rendered clips/workspace/masterb-pilot/videos/ (VPS), /root/manim-test/media/ (VPS)
    Runnable lesson previewVPS port 8142masterb-pilot.srv1738752.hstgr.cloud

    9. Constraints and gotchas

  • No Node in the acct1 container — a Vite/React build must happen on the VPS (node v22.23.1)
  • or elsewhere. manim renders fine because they run in Docker on the VPS.

  • manim is not a general video tool. It is for precise, annotated, formula/geometry
  • animation. Narrative film, photoreal footage, and people belong elsewhere (existing footage

    pipeline / NotebookLM). For anything the learner must *manipulate*, React wins — the platform

    already has LightweightChart + drawing tools and 4 games.

  • A Text() label read as fused in a low-res QC frame is usually a vision-model misread.
  • Re-render at -qh with a large font size before "fixing" anything.

  • QC frames only after animations settle, inside a self.wait(). Sampling mid-fade produces
  • false "missing element" / "low contrast" reports.

  • Pane/bundle caching: the trade platforms keep many stale build generations in assets/;
  • resolve the live chunk from index.html before grepping or you will read dead builds.

  • Sizing: Master B assets/ ≈ 11 MB; its legacy film sat-class-8222026.mp4 is 183 MB.
  • The dead Supabase project (avhyrrrmlcnynhddrtp.supabase.co, NXDOMAIN) still affects
  • Master B and is unresolved — held to the end by the user, along with moving Master B to the

    Hostinger shared account. See the trade-platform-builder reference for that plan.

    10. Open questions to settle at kickoff

  • 1. Hosting for clips + manifest — VPS behind Traefik, or the Hostinger account? (Affects
  • whether the runtime integration can use a same-origin path.)

  • 2. Which product ships first, and is the first rollout a whole curriculum or a slice?
  • 3. Studio auth — the Studio will render on the VPS; decide who can publish.
  • 4. Revision/versioning model — when a lesson's text changes, does the clip auto-invalidate
  • (recommended: store a content hash in the spec and flag drift in the gallery)?

  • 5. Audio — clips are currently silent. Voiceover would need the existing TTS pipeline, and
  • narration timing would then drive the pause points.