# gnipbao/story-to-handdrawn-video architecture

> Architecture diagram of the GitHub repository gnipbao/story-to-handdrawn-video, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/gnipbao/story-to-handdrawn-video
- Repository: https://github.com/gnipbao/story-to-handdrawn-video

## Overview

The product turns Chinese stories or ordered images into silent 3:4 hand-drawn videos. Its main workflow is Agent-assisted story and style planning, image creation or image import, local page-asset processing, then Remotion composition and rendering. The graph includes the documented style-reference and custom-style capabilities. Some CLI and reference-style internals were not excerpted, so those documented relationships are cited to the README; implementation-level edges use the supplied source index or excerpts.

Main entry points: [`scripts/story-to-video.mjs`](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/story-to-video.mjs) (Story CLI), [`src/StoryVideo.tsx`](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/StoryVideo.tsx) (Story Video), [`src/Root.tsx`](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/Root.tsx) (Composition Registry), [`src/UploadedStoryVideo.tsx`](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/UploadedStoryVideo.tsx) (Uploaded Video)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_planning["Planning and Styles"]
  node_agent["Agent Skill<br/>[SKILL.md]"]
  node_planner["Story CLI<br/>[story-to-video.mjs]"]
  node_style_catalog[("Style Catalog")]
  node_style_resolver["Style Resolver"]
  node_reference_styles["Reference Styles"]
end

subgraph group_assets["Image Preparation"]
  node_import_generated["Generated Image Import"]
  node_import_uploaded["Uploaded Image Import"]
  node_page_assets["Page Asset Processor<br/>[page-assets.mjs]"]
end

subgraph group_rendering["Video Rendering"]
  node_root["Composition Registry<br/>[Root.tsx]"]
  node_story_video["Story Video<br/>[StoryVideo.tsx]"]
  node_uploaded_video["Uploaded Video"]
  node_scene["Scene Renderer<br/>[Scene.tsx]"]
  node_layer_wipe["Layer Reveal<br/>[LayerWipe.tsx]"]
  node_text_wipe["Text Reveal<br/>[TextWipe.tsx]"]
  node_easing["Reveal Timing<br/>[easing.ts]"]
end

subgraph group_data["Storyboard Data"]
  node_storyboard["Story Storyboard<br/>[storyboard.json]"]
  node_uploaded_storyboard["Uploaded Storyboard"]
end

node_user(("User"))
node_image_generator["Image Generator"]
node_video_file["Silent MP4"]

node_user -->|"requests video"| node_agent
node_agent -->|"invokes workflow"| node_planner
node_agent -->|"generates artwork"| node_image_generator
node_planner -->|"resolves styles"| node_style_resolver
node_style_resolver -->|"loads catalog"| node_style_catalog
node_planner -.->|"prepares references"| node_reference_styles
node_planner -->|"processes pages"| node_page_assets
node_planner -->|"imports generated"| node_import_generated
node_planner -->|"prepares scenes"| node_storyboard
node_import_generated -->|"uses processor"| node_page_assets
node_import_uploaded -->|"uses processor"| node_page_assets
node_user -->|"provides images"| node_import_uploaded
node_import_uploaded -->|"prepares scenes"| node_uploaded_storyboard
node_root -->|"registers composition"| node_story_video
node_root -->|"registers composition"| node_uploaded_video
node_root -->|"loads storyboard"| node_storyboard
node_root -->|"loads storyboard"| node_uploaded_storyboard
node_story_video -->|"renders scenes"| node_storyboard
node_story_video -->|"renders scene"| node_scene
node_uploaded_video -->|"reuses renderer"| node_story_video
node_uploaded_video -->|"loads scenes"| node_uploaded_storyboard
node_scene -->|"reveals art"| node_layer_wipe
node_scene -->|"reveals text"| node_text_wipe
node_layer_wipe -->|"uses timing"| node_easing
node_text_wipe -->|"uses timing"| node_easing
node_story_video -->|"times page flips"| node_easing
node_story_video -->|"renders MP4"| node_video_file
node_uploaded_video -->|"renders MP4"| node_video_file

click node_agent "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/skill-package/story-to-handdrawn-video/SKILL.md"
click node_planner "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/story-to-video.mjs"
click node_style_catalog "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/references/handdrawn-style-library.json"
click node_style_resolver "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/handdrawn-style-library.mjs"
click node_reference_styles "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/reference-style.mjs"
click node_import_generated "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/import-codex-images.mjs"
click node_import_uploaded "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/import-uploaded-pages.mjs"
click node_page_assets "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/page-assets.mjs"
click node_storyboard "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/storyboard.json"
click node_uploaded_storyboard "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/storyboard.uploaded.json"
click node_root "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/Root.tsx"
click node_story_video "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/StoryVideo.tsx"
click node_uploaded_video "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/UploadedStoryVideo.tsx"
click node_scene "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/Scene.tsx"
click node_layer_wipe "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/LayerWipe.tsx"
click node_text_wipe "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/TextWipe.tsx"
click node_easing "https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/easing.ts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_agent,node_planner,node_style_catalog,node_style_resolver,node_reference_styles,node_user toneBlue
class node_import_generated,node_import_uploaded,node_page_assets toneAmber
class node_root,node_story_video,node_uploaded_video,node_scene,node_layer_wipe,node_text_wipe,node_easing toneMint
class node_storyboard,node_uploaded_storyboard toneRose
class node_image_generator,node_video_file toneIndigo
```

## Components

### Planning and Styles

- [Agent Skill](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/skill-package/story-to-handdrawn-video/SKILL.md): `skill-package/story-to-handdrawn-video/SKILL.md`
- [Story CLI](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/story-to-video.mjs): `scripts/story-to-video.mjs`
- [Style Catalog](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/references/handdrawn-style-library.json): `references/handdrawn-style-library.json`
- [Style Resolver](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/handdrawn-style-library.mjs): `scripts/handdrawn-style-library.mjs`
- [Reference Styles](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/reference-style.mjs): `scripts/reference-style.mjs`

### Image Preparation

- [Generated Image Import](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/import-codex-images.mjs): `scripts/import-codex-images.mjs`
- [Uploaded Image Import](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/import-uploaded-pages.mjs): `scripts/import-uploaded-pages.mjs`
- [Page Asset Processor](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/scripts/page-assets.mjs): `scripts/page-assets.mjs`

### Video Rendering

- [Composition Registry](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/Root.tsx): `src/Root.tsx`
- [Story Video](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/StoryVideo.tsx): `src/StoryVideo.tsx`
- [Uploaded Video](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/UploadedStoryVideo.tsx): `src/UploadedStoryVideo.tsx`
- [Scene Renderer](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/Scene.tsx): `src/Scene.tsx`
- [Layer Reveal](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/LayerWipe.tsx): `src/LayerWipe.tsx`
- [Text Reveal](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/TextWipe.tsx): `src/TextWipe.tsx`
- [Reveal Timing](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/src/easing.ts): `src/easing.ts`

### Storyboard Data

- [Story Storyboard](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/storyboard.json): `storyboard.json`
- [Uploaded Storyboard](https://github.com/gnipbao/story-to-handdrawn-video/blob/main/storyboard.uploaded.json): `storyboard.uploaded.json`

### Other components

- **User**
- **Image Generator**
- **Silent MP4**

## Connections

- User → Agent Skill: requests video (evidence: `README.md`)
- Agent Skill → Story CLI: invokes workflow (evidence: `README.md`)
- Agent Skill → Image Generator: generates artwork (evidence: `README.md`)
- Story CLI → Style Resolver: resolves styles (evidence: `scripts/story-to-video.mjs`)
- Style Resolver → Style Catalog: loads catalog (evidence: `scripts/handdrawn-style-library.mjs`)
- Story CLI → Reference Styles: prepares references
- Story CLI → Page Asset Processor: processes pages (evidence: `scripts/story-to-video.mjs`)
- Story CLI → Generated Image Import: imports generated (evidence: `README.md`)
- Story CLI → Story Storyboard: prepares scenes (evidence: `README.md`)
- Generated Image Import → Page Asset Processor: uses processor (evidence: `scripts/import-codex-images.mjs`)
- Uploaded Image Import → Page Asset Processor: uses processor (evidence: `scripts/import-uploaded-pages.mjs`)
- User → Uploaded Image Import: provides images (evidence: `README.md`)
- Uploaded Image Import → Uploaded Storyboard: prepares scenes (evidence: `README.md`)
- Composition Registry → Story Video: registers composition (evidence: `src/Root.tsx`)
- Composition Registry → Uploaded Video: registers composition (evidence: `src/Root.tsx`)
- Composition Registry → Story Storyboard: loads storyboard (evidence: `src/Root.tsx`)
- Composition Registry → Uploaded Storyboard: loads storyboard (evidence: `src/Root.tsx`)
- Story Video → Story Storyboard: renders scenes (evidence: `src/StoryVideo.tsx`)
- Story Video → Scene Renderer: renders scene (evidence: `src/StoryVideo.tsx`)
- Uploaded Video → Story Video: reuses renderer (evidence: `src/UploadedStoryVideo.tsx`)
- Uploaded Video → Uploaded Storyboard: loads scenes (evidence: `src/UploadedStoryVideo.tsx`)
- Scene Renderer → Layer Reveal: reveals art (evidence: `src/Scene.tsx`)
- Scene Renderer → Text Reveal: reveals text (evidence: `src/Scene.tsx`)
- Layer Reveal → Reveal Timing: uses timing (evidence: `src/LayerWipe.tsx`)
- Text Reveal → Reveal Timing: uses timing (evidence: `src/TextWipe.tsx`)
- Story Video → Reveal Timing: times page flips (evidence: `src/StoryVideo.tsx`)
- Story Video → Silent MP4: renders MP4 (evidence: `README.md`)
- Uploaded Video → Silent MP4: renders MP4 (evidence: `README.md`)
