# hainrixz/open-carrusel architecture

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

- Interactive diagram: https://gitdiagram.com/hainrixz/open-carrusel
- Repository: https://github.com/hainrixz/open-carrusel

## Overview

Open Carrusel is a local-first Instagram carousel editor. The main workflow is to create or open a carousel, chat with Claude to generate or revise HTML slides, review and reorder them in the editor, then export dimension-specific PNGs. The README also documents brand setup, templates, style presets, reference images, captions, safe zones, and per-slide undo. Chat, upload, carousel, and several supporting API handlers were sampled; other feature links reflect documented capabilities and are kept at the API or library level where wiring was not sampled.

Main entry points: [`src/app/carousel/[id]/page.tsx`](https://github.com/hainrixz/open-carrusel/blob/main/src/app/carousel/%5Bid%5D/page.tsx) (Carousel editor), [`src/app/api/chat/route.ts`](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/chat/route.ts) (Chat stream API), [`src/lib/carousels.ts`](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/carousels.ts) (Carousel operations), [`src/lib/data.ts`](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/data.ts) (Local JSON data)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_experience["Editor experience"]
  node_dashboard["Carousel dashboard<br/>[page.tsx]"]
  node_editor["Carousel editor<br/>[page.tsx]"]
  node_chatui["Chat panel<br/>[ChatPanel.tsx]"]
  node_preview["Slide preview"]
  node_filmstrip["Slide filmstrip<br/>[SlideFilmstrip.tsx]"]
end

subgraph group_generation["AI generation"]
  node_chatapi["Chat stream API<br/>[route.ts]"]
  node_prompt["Prompt builder"]
end

subgraph group_editing["Carousel editing"]
  node_slidesapi["Slide operations API<br/>[route.ts]"]
  node_slideitemapi["Slide edit and undo API<br/>[route.ts]"]
  node_carouselapi["Carousel API<br/>[route.ts]"]
  node_carouseldata["Carousel operations<br/>[carousels.ts]"]
  node_captionapi["Caption generator API<br/>[route.ts]"]
  node_exportapi["PNG export API<br/>[route.ts]"]
  node_html["Slide HTML wrapper<br/>[slide-html.ts]"]
  node_exporter["Slide renderer and zipper<br/>[export-slides.ts]"]
end

subgraph group_assets["Brand and reuse"]
  node_brandapi["Brand API<br/>[route.ts]"]
  node_brandlib["Brand operations<br/>[brand.ts]"]
  node_uploadapi["Asset upload API<br/>[route.ts]"]
  node_templatesapi["Template API<br/>[route.ts]"]
  node_templates["Template operations<br/>[templates.ts]"]
  node_presetsapi["Style preset API<br/>[route.ts]"]
  node_presets["Style preset operations<br/>[style-presets.ts]"]
  node_referencesapi["Reference images API<br/>[route.ts]"]
end

subgraph group_local["Local services"]
  node_data[("Local JSON data<br/>[data.ts]")]
  node_uploads[("Local uploads")]
end

node_browser(("Browser user"))
node_claude["Claude CLI"]
node_puppeteer["Headless Chromium"]

node_browser -->|"opens"| node_dashboard
node_browser -->|"opens"| node_editor
node_dashboard -->|"manages"| node_carouselapi
node_editor -->|"hosts"| node_chatui
node_chatui -->|"sends prompts"| node_chatapi
node_chatapi -->|"loads context"| node_brandlib
node_chatapi -->|"loads context"| node_carouseldata
node_chatapi -->|"loads context"| node_presets
node_chatapi -->|"builds prompt"| node_prompt
node_chatapi -->|"spawns; streams"| node_claude
node_claude -.->|"posts slide HTML"| node_slidesapi
node_editor -->|"previews"| node_preview
node_editor -->|"organizes slides"| node_filmstrip
node_filmstrip -->|"edits and undoes"| node_slideitemapi
node_slidesapi -->|"updates slides"| node_carouseldata
node_slideitemapi -->|"updates slide"| node_carouseldata
node_carouselapi -->|"manages records"| node_carouseldata
node_editor -->|"requests captions"| node_captionapi
node_editor -->|"requests export"| node_exportapi
node_exportapi -->|"renders slides"| node_exporter
node_exporter -->|"wraps slide HTML"| node_html
node_exporter -->|"screenshots"| node_puppeteer
node_brandapi -->|"reads and updates"| node_brandlib
node_editor -->|"configures brand"| node_brandapi
node_editor -->|"uploads assets"| node_uploadapi
node_uploadapi -->|"writes files"| node_uploads
node_editor -->|"saves and reuses"| node_templatesapi
node_templatesapi -->|"loads carousel"| node_carouseldata
node_templatesapi -->|"manages templates"| node_templates
node_editor -->|"manages styles"| node_presetsapi
node_presetsapi -->|"manages presets"| node_presets
node_editor -->|"manages references"| node_referencesapi
node_carouseldata -->|"reads and writes"| node_data
node_brandlib -->|"reads and writes"| node_data
node_templates -->|"reads and writes"| node_data
node_presets -->|"reads and writes"| node_data

click node_dashboard "https://github.com/hainrixz/open-carrusel/blob/main/src/app/page.tsx"
click node_editor "https://github.com/hainrixz/open-carrusel/blob/main/src/app/carousel/%5Bid%5D/page.tsx"
click node_chatui "https://github.com/hainrixz/open-carrusel/blob/main/src/components/chat/ChatPanel.tsx"
click node_preview "https://github.com/hainrixz/open-carrusel/blob/main/src/components/editor/CarouselPreview.tsx"
click node_filmstrip "https://github.com/hainrixz/open-carrusel/blob/main/src/components/editor/SlideFilmstrip.tsx"
click node_chatapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/chat/route.ts"
click node_prompt "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/chat-system-prompt.ts"
click node_slidesapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/slides/route.ts"
click node_slideitemapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/slides/%5BslideId%5D/route.ts"
click node_carouselapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/route.ts"
click node_carouseldata "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/carousels.ts"
click node_captionapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/caption/route.ts"
click node_exportapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/export/route.ts"
click node_html "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/slide-html.ts"
click node_exporter "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/export-slides.ts"
click node_brandapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/brand/route.ts"
click node_brandlib "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/brand.ts"
click node_uploadapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/upload/route.ts"
click node_templatesapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/templates/route.ts"
click node_templates "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/templates.ts"
click node_presetsapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/style-presets/route.ts"
click node_presets "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/style-presets.ts"
click node_referencesapi "https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/references/route.ts"
click node_data "https://github.com/hainrixz/open-carrusel/blob/main/src/lib/data.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_dashboard,node_editor,node_chatui,node_preview,node_filmstrip,node_browser toneBlue
class node_chatapi,node_prompt toneAmber
class node_slidesapi,node_slideitemapi,node_carouselapi,node_carouseldata,node_captionapi,node_exportapi,node_html,node_exporter toneMint
class node_brandapi,node_brandlib,node_uploadapi,node_templatesapi,node_templates,node_presetsapi,node_presets,node_referencesapi toneRose
class node_data,node_uploads,node_claude,node_puppeteer toneIndigo
```

## Components

### Editor experience

- [Carousel dashboard](https://github.com/hainrixz/open-carrusel/blob/main/src/app/page.tsx): `src/app/page.tsx`
- [Carousel editor](https://github.com/hainrixz/open-carrusel/blob/main/src/app/carousel/%5Bid%5D/page.tsx): `src/app/carousel/[id]/page.tsx`
- [Chat panel](https://github.com/hainrixz/open-carrusel/blob/main/src/components/chat/ChatPanel.tsx): `src/components/chat/ChatPanel.tsx`
- [Slide preview](https://github.com/hainrixz/open-carrusel/blob/main/src/components/editor/CarouselPreview.tsx): `src/components/editor/CarouselPreview.tsx`
- [Slide filmstrip](https://github.com/hainrixz/open-carrusel/blob/main/src/components/editor/SlideFilmstrip.tsx): `src/components/editor/SlideFilmstrip.tsx`

### AI generation

- [Chat stream API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/chat/route.ts): `src/app/api/chat/route.ts`
- [Prompt builder](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/chat-system-prompt.ts): `src/lib/chat-system-prompt.ts`

### Carousel editing

- [Slide operations API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/slides/route.ts): `src/app/api/carousels/[id]/slides/route.ts`
- [Slide edit and undo API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/slides/%5BslideId%5D/route.ts): `src/app/api/carousels/[id]/slides/[slideId]/route.ts`
- [Carousel API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/route.ts): `src/app/api/carousels/route.ts`
- [Carousel operations](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/carousels.ts): `src/lib/carousels.ts`
- [Caption generator API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/caption/route.ts): `src/app/api/carousels/[id]/caption/route.ts`
- [PNG export API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/export/route.ts): `src/app/api/carousels/[id]/export/route.ts`
- [Slide HTML wrapper](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/slide-html.ts): `src/lib/slide-html.ts`
- [Slide renderer and zipper](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/export-slides.ts): `src/lib/export-slides.ts`

### Brand and reuse

- [Brand API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/brand/route.ts): `src/app/api/brand/route.ts`
- [Brand operations](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/brand.ts): `src/lib/brand.ts`
- [Asset upload API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/upload/route.ts): `src/app/api/upload/route.ts`
- [Template API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/templates/route.ts): `src/app/api/templates/route.ts`
- [Template operations](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/templates.ts): `src/lib/templates.ts`
- [Style preset API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/style-presets/route.ts): `src/app/api/style-presets/route.ts`
- [Style preset operations](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/style-presets.ts): `src/lib/style-presets.ts`
- [Reference images API](https://github.com/hainrixz/open-carrusel/blob/main/src/app/api/carousels/%5Bid%5D/references/route.ts): `src/app/api/carousels/[id]/references/route.ts`

### Local services

- [Local JSON data](https://github.com/hainrixz/open-carrusel/blob/main/src/lib/data.ts): `src/lib/data.ts`
- **Local uploads**

### Other components

- **Browser user**
- **Claude CLI**
- **Headless Chromium**

## Connections

- Browser user → Carousel dashboard: opens
- Browser user → Carousel editor: opens
- Carousel dashboard → Carousel API: manages
- Carousel editor → Chat panel: hosts
- Chat panel → Chat stream API: sends prompts
- Chat stream API → Brand operations: loads context
- Chat stream API → Carousel operations: loads context
- Chat stream API → Style preset operations: loads context
- Chat stream API → Prompt builder: builds prompt
- Chat stream API → Claude CLI: spawns; streams
- Claude CLI → Slide operations API: posts slide HTML
- Carousel editor → Slide preview: previews
- Carousel editor → Slide filmstrip: organizes slides
- Slide filmstrip → Slide edit and undo API: edits and undoes
- Slide operations API → Carousel operations: updates slides
- Slide edit and undo API → Carousel operations: updates slide
- Carousel API → Carousel operations: manages records
- Carousel editor → Caption generator API: requests captions
- Carousel editor → PNG export API: requests export
- PNG export API → Slide renderer and zipper: renders slides
- Slide renderer and zipper → Slide HTML wrapper: wraps slide HTML
- Slide renderer and zipper → Headless Chromium: screenshots
- Brand API → Brand operations: reads and updates
- Carousel editor → Brand API: configures brand
- Carousel editor → Asset upload API: uploads assets
- Asset upload API → Local uploads: writes files
- Carousel editor → Template API: saves and reuses
- Template API → Carousel operations: loads carousel
- Template API → Template operations: manages templates
- Carousel editor → Style preset API: manages styles
- Style preset API → Style preset operations: manages presets
- Carousel editor → Reference images API: manages references
- Carousel operations → Local JSON data: reads and writes
- Brand operations → Local JSON data: reads and writes
- Template operations → Local JSON data: reads and writes
- Style preset operations → Local JSON data: reads and writes
