# kskkoushik/doodo architecture

> Architecture diagram of the GitHub repository kskkoushik/doodo, 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/kskkoushik/doodo
- Repository: https://github.com/kskkoushik/doodo

## Overview

Doodo is an AI whiteboard teacher: a learner asks a question, optionally with board content or an image, and receives a spoken explanation synchronized with drawn annotations. The browser captures board context and sends it to the lesson route; the server streams model output as DML, resolves vision and math work, and emits lesson events. The browser parses those events into audio and drawing beats, compiles drawing operations, and animates them on the board. The graph also shows editing, speech input, and handwriting. Some subsystem links reflect README descriptions or SOURCE INDEX references; unsampled internals are not assumed to have been inspected.

Main entry points: [`app/api/lesson/route.ts`](https://github.com/kskkoushik/doodo/blob/main/app/api/lesson/route.ts) (Lesson route), [`lib/client/runtime.ts`](https://github.com/kskkoushik/doodo/blob/main/lib/client/runtime.ts) (Lesson runtime), [`components/Board.tsx`](https://github.com/kskkoushik/doodo/blob/main/components/Board.tsx) (Board and editor), [`lib/client/player.ts`](https://github.com/kskkoushik/doodo/blob/main/lib/client/player.ts) (Beat player)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["Board interface"]
  node_app["Doodo app<br/>[DoodoApp.tsx]"]
  node_board["Board and editor<br/>[Board.tsx]"]
  node_toolbar["Toolbar<br/>[Toolbar.tsx]"]
  node_dock["Dock<br/>[Dock.tsx]"]
  node_store["Board state<br/>[store.ts]"]
end

subgraph group_lesson["Lesson runtime"]
  node_runtime["Lesson runtime<br/>[runtime.ts]"]
  node_player["Beat player<br/>[player.ts]"]
  node_animator["Stroke animator<br/>[animator.ts]"]
  node_audio["Audio engine<br/>[audio.ts]"]
  node_clock["Lesson clock<br/>[clock.ts]"]
  node_snapshot["Board snapshot<br/>[snapshot.ts]"]
end

subgraph group_language["DML and drawing"]
  node_parser["DML parser<br/>[parser.ts]"]
  node_tokenizer["DML tokenizer<br/>[tokenizer.ts]"]
  node_converter["DML converter<br/>[convert.ts]"]
  node_ops["Drawing operations<br/>[ops.ts]"]
  node_compiler["Board compiler<br/>[compile.ts]"]
  node_freehand["Freehand geometry<br/>[freehand.ts]"]
  node_svg["SVG renderer<br/>[svgRender.ts]"]
  node_font["Handwriting font<br/>[font.ts]"]
end

subgraph group_services["AI and media services"]
  node_lessonroute["Lesson route<br/>[route.ts]"]
  node_sttroute["Speech input route<br/>[route.ts]"]
  node_openrouter["OpenRouter client<br/>[openrouter.ts]"]
  node_ground["Image grounding<br/>[ground.ts]"]
  node_tts["Speech synthesis<br/>[tts.ts]"]
  node_tex["TeX rendering<br/>[tex.ts]"]
end

subgraph group_shared["Shared foundations"]
  node_protocol["Lesson protocol<br/>[protocol.ts]"]
  node_sse["SSE decoder<br/>[sse.ts]"]
  node_values["DML value scanners<br/>[values.ts]"]
  node_geometry["Geometry utilities<br/>[geom.ts]"]
  node_expressions["Expression parser<br/>[expr.ts]"]
  node_symbols["Glyph symbols<br/>[symbols.ts]"]
end

node_learner(("Learner"))
node_provider{{"AI providers"}}
node_sarvam{{"Sarvam AI"}}

node_learner -->|"asks or edits"| node_app
node_app -->|"shows board"| node_board
node_app -->|"shows controls"| node_toolbar
node_app -->|"shows dock"| node_dock
node_toolbar -->|"updates tools"| node_store
node_dock -->|"reads state"| node_store
node_board -->|"edits board"| node_store
node_board -->|"binds board"| node_runtime
node_board -->|"prepares uploads"| node_snapshot
node_board -->|"renders elements"| node_svg
node_runtime -->|"captures context"| node_snapshot
node_runtime -->|"posts lesson"| node_lessonroute
node_learner -->|"sends speech"| node_sttroute
node_sttroute -->|"requests transcription"| node_sarvam
node_lessonroute -->|"streams teacher model"| node_openrouter
node_openrouter -->|"calls model API"| node_provider
node_lessonroute -->|"parses model stream"| node_parser
node_parser -->|"tokenizes tags"| node_tokenizer
node_parser -->|"converts tags"| node_converter
node_converter -->|"produces operations"| node_ops
node_lessonroute -->|"resolves find ops"| node_ground
node_ground -->|"requests vision"| node_openrouter
node_lessonroute -->|"renders math"| node_tex
node_lessonroute -->|"synthesizes voice"| node_tts
node_tts -->|"streams speech"| node_sarvam
node_lessonroute -->|"emits lesson events"| node_protocol
node_runtime -->|"decodes events"| node_sse
node_runtime -->|"handles events"| node_protocol
node_runtime -->|"plays lesson"| node_player
node_player -->|"animates strokes"| node_animator
node_player -->|"plays audio"| node_audio
node_player -->|"synchronizes beats"| node_clock
node_player -->|"compiles operations"| node_compiler
node_compiler -->|"parses paths"| node_values
node_compiler -->|"calculates layout"| node_geometry
node_compiler -->|"compiles plots"| node_expressions
node_compiler -->|"lays out handwriting"| node_font
node_font -->|"uses glyphs"| node_symbols
node_animator -->|"draws ink"| node_freehand
node_animator -->|"creates stroke nodes"| node_svg
node_svg -->|"renders ink paths"| node_freehand

click node_app "https://github.com/kskkoushik/doodo/blob/main/components/DoodoApp.tsx"
click node_board "https://github.com/kskkoushik/doodo/blob/main/components/Board.tsx"
click node_toolbar "https://github.com/kskkoushik/doodo/blob/main/components/Toolbar.tsx"
click node_dock "https://github.com/kskkoushik/doodo/blob/main/components/Dock.tsx"
click node_store "https://github.com/kskkoushik/doodo/blob/main/lib/client/store.ts"
click node_runtime "https://github.com/kskkoushik/doodo/blob/main/lib/client/runtime.ts"
click node_player "https://github.com/kskkoushik/doodo/blob/main/lib/client/player.ts"
click node_animator "https://github.com/kskkoushik/doodo/blob/main/lib/client/animator.ts"
click node_audio "https://github.com/kskkoushik/doodo/blob/main/lib/client/audio.ts"
click node_clock "https://github.com/kskkoushik/doodo/blob/main/lib/client/clock.ts"
click node_snapshot "https://github.com/kskkoushik/doodo/blob/main/lib/client/snapshot.ts"
click node_lessonroute "https://github.com/kskkoushik/doodo/blob/main/app/api/lesson/route.ts"
click node_sttroute "https://github.com/kskkoushik/doodo/blob/main/app/api/stt/route.ts"
click node_openrouter "https://github.com/kskkoushik/doodo/blob/main/lib/server/openrouter.ts"
click node_ground "https://github.com/kskkoushik/doodo/blob/main/lib/server/ground.ts"
click node_tts "https://github.com/kskkoushik/doodo/blob/main/lib/server/tts.ts"
click node_tex "https://github.com/kskkoushik/doodo/blob/main/lib/server/tex.ts"
click node_parser "https://github.com/kskkoushik/doodo/blob/main/lib/dml/parser.ts"
click node_tokenizer "https://github.com/kskkoushik/doodo/blob/main/lib/dml/tokenizer.ts"
click node_converter "https://github.com/kskkoushik/doodo/blob/main/lib/dml/convert.ts"
click node_ops "https://github.com/kskkoushik/doodo/blob/main/lib/dml/ops.ts"
click node_compiler "https://github.com/kskkoushik/doodo/blob/main/lib/board/compile.ts"
click node_freehand "https://github.com/kskkoushik/doodo/blob/main/lib/board/freehand.ts"
click node_svg "https://github.com/kskkoushik/doodo/blob/main/lib/client/svgRender.ts"
click node_font "https://github.com/kskkoushik/doodo/blob/main/lib/hand/font.ts"
click node_protocol "https://github.com/kskkoushik/doodo/blob/main/lib/protocol.ts"
click node_sse "https://github.com/kskkoushik/doodo/blob/main/lib/sse.ts"
click node_values "https://github.com/kskkoushik/doodo/blob/main/lib/dml/values.ts"
click node_geometry "https://github.com/kskkoushik/doodo/blob/main/lib/geom.ts"
click node_expressions "https://github.com/kskkoushik/doodo/blob/main/lib/math/expr.ts"
click node_symbols "https://github.com/kskkoushik/doodo/blob/main/lib/hand/symbols.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_app,node_board,node_toolbar,node_dock,node_store toneBlue
class node_runtime,node_player,node_animator,node_audio,node_clock,node_snapshot toneAmber
class node_parser,node_tokenizer,node_converter,node_ops,node_compiler,node_freehand,node_svg,node_font toneMint
class node_lessonroute,node_sttroute,node_openrouter,node_ground,node_tts,node_tex toneRose
class node_protocol,node_sse,node_values,node_geometry,node_expressions,node_symbols,node_learner,node_provider,node_sarvam toneIndigo
```

## Components

### Board interface

- [Doodo app](https://github.com/kskkoushik/doodo/blob/main/components/DoodoApp.tsx): `components/DoodoApp.tsx`
- [Board and editor](https://github.com/kskkoushik/doodo/blob/main/components/Board.tsx): `components/Board.tsx`
- [Toolbar](https://github.com/kskkoushik/doodo/blob/main/components/Toolbar.tsx): `components/Toolbar.tsx`
- [Dock](https://github.com/kskkoushik/doodo/blob/main/components/Dock.tsx): `components/Dock.tsx`
- [Board state](https://github.com/kskkoushik/doodo/blob/main/lib/client/store.ts): `lib/client/store.ts`

### Lesson runtime

- [Lesson runtime](https://github.com/kskkoushik/doodo/blob/main/lib/client/runtime.ts): `lib/client/runtime.ts`
- [Beat player](https://github.com/kskkoushik/doodo/blob/main/lib/client/player.ts): `lib/client/player.ts`
- [Stroke animator](https://github.com/kskkoushik/doodo/blob/main/lib/client/animator.ts): `lib/client/animator.ts`
- [Audio engine](https://github.com/kskkoushik/doodo/blob/main/lib/client/audio.ts): `lib/client/audio.ts`
- [Lesson clock](https://github.com/kskkoushik/doodo/blob/main/lib/client/clock.ts): `lib/client/clock.ts`
- [Board snapshot](https://github.com/kskkoushik/doodo/blob/main/lib/client/snapshot.ts): `lib/client/snapshot.ts`

### DML and drawing

- [DML parser](https://github.com/kskkoushik/doodo/blob/main/lib/dml/parser.ts): `lib/dml/parser.ts`
- [DML tokenizer](https://github.com/kskkoushik/doodo/blob/main/lib/dml/tokenizer.ts): `lib/dml/tokenizer.ts`
- [DML converter](https://github.com/kskkoushik/doodo/blob/main/lib/dml/convert.ts): `lib/dml/convert.ts`
- [Drawing operations](https://github.com/kskkoushik/doodo/blob/main/lib/dml/ops.ts): `lib/dml/ops.ts`
- [Board compiler](https://github.com/kskkoushik/doodo/blob/main/lib/board/compile.ts): `lib/board/compile.ts`
- [Freehand geometry](https://github.com/kskkoushik/doodo/blob/main/lib/board/freehand.ts): `lib/board/freehand.ts`
- [SVG renderer](https://github.com/kskkoushik/doodo/blob/main/lib/client/svgRender.ts): `lib/client/svgRender.ts`
- [Handwriting font](https://github.com/kskkoushik/doodo/blob/main/lib/hand/font.ts): `lib/hand/font.ts`

### AI and media services

- [Lesson route](https://github.com/kskkoushik/doodo/blob/main/app/api/lesson/route.ts): `app/api/lesson/route.ts`
- [Speech input route](https://github.com/kskkoushik/doodo/blob/main/app/api/stt/route.ts): `app/api/stt/route.ts`
- [OpenRouter client](https://github.com/kskkoushik/doodo/blob/main/lib/server/openrouter.ts): `lib/server/openrouter.ts`
- [Image grounding](https://github.com/kskkoushik/doodo/blob/main/lib/server/ground.ts): `lib/server/ground.ts`
- [Speech synthesis](https://github.com/kskkoushik/doodo/blob/main/lib/server/tts.ts): `lib/server/tts.ts`
- [TeX rendering](https://github.com/kskkoushik/doodo/blob/main/lib/server/tex.ts): `lib/server/tex.ts`

### Shared foundations

- [Lesson protocol](https://github.com/kskkoushik/doodo/blob/main/lib/protocol.ts): `lib/protocol.ts`
- [SSE decoder](https://github.com/kskkoushik/doodo/blob/main/lib/sse.ts): `lib/sse.ts`
- [DML value scanners](https://github.com/kskkoushik/doodo/blob/main/lib/dml/values.ts): `lib/dml/values.ts`
- [Geometry utilities](https://github.com/kskkoushik/doodo/blob/main/lib/geom.ts): `lib/geom.ts`
- [Expression parser](https://github.com/kskkoushik/doodo/blob/main/lib/math/expr.ts): `lib/math/expr.ts`
- [Glyph symbols](https://github.com/kskkoushik/doodo/blob/main/lib/hand/symbols.ts): `lib/hand/symbols.ts`

### Other components

- **Learner**
- **AI providers**
- **Sarvam AI**

## Connections

- Learner → Doodo app: asks or edits (evidence: `README.md`)
- Doodo app → Board and editor: shows board (evidence: `components/DoodoApp.tsx`)
- Doodo app → Toolbar: shows controls (evidence: `components/DoodoApp.tsx`)
- Doodo app → Dock: shows dock (evidence: `components/DoodoApp.tsx`)
- Toolbar → Board state: updates tools (evidence: `components/Toolbar.tsx`)
- Dock → Board state: reads state (evidence: `components/Dock.tsx`)
- Board and editor → Board state: edits board (evidence: `components/Board.tsx`)
- Board and editor → Lesson runtime: binds board (evidence: `components/Board.tsx`)
- Board and editor → Board snapshot: prepares uploads (evidence: `components/Board.tsx`)
- Board and editor → SVG renderer: renders elements (evidence: `components/Board.tsx`)
- Lesson runtime → Board snapshot: captures context (evidence: `lib/client/runtime.ts`)
- Lesson runtime → Lesson route: posts lesson (evidence: `README.md`)
- Learner → Speech input route: sends speech (evidence: `README.md`)
- Speech input route → Sarvam AI: requests transcription (evidence: `app/api/stt/route.ts`)
- Lesson route → OpenRouter client: streams teacher model (evidence: `app/api/lesson/route.ts`)
- OpenRouter client → AI providers: calls model API (evidence: `lib/server/openrouter.ts`)
- Lesson route → DML parser: parses model stream (evidence: `app/api/lesson/route.ts`)
- DML parser → DML tokenizer: tokenizes tags (evidence: `lib/dml/parser.ts`)
- DML parser → DML converter: converts tags (evidence: `lib/dml/parser.ts`)
- DML converter → Drawing operations: produces operations (evidence: `lib/dml/convert.ts`)
- Lesson route → Image grounding: resolves find ops (evidence: `app/api/lesson/route.ts`)
- Image grounding → OpenRouter client: requests vision (evidence: `lib/server/ground.ts`)
- Lesson route → TeX rendering: renders math (evidence: `app/api/lesson/route.ts`)
- Lesson route → Speech synthesis: synthesizes voice (evidence: `app/api/lesson/route.ts`)
- Speech synthesis → Sarvam AI: streams speech (evidence: `lib/server/tts.ts`)
- Lesson route → Lesson protocol: emits lesson events (evidence: `app/api/lesson/route.ts`)
- Lesson runtime → SSE decoder: decodes events (evidence: `lib/client/runtime.ts`)
- Lesson runtime → Lesson protocol: handles events (evidence: `lib/client/runtime.ts`)
- Lesson runtime → Beat player: plays lesson (evidence: `lib/client/runtime.ts`)
- Beat player → Stroke animator: animates strokes (evidence: `lib/client/player.ts`)
- Beat player → Audio engine: plays audio (evidence: `lib/client/player.ts`)
- Beat player → Lesson clock: synchronizes beats (evidence: `lib/client/player.ts`)
- Beat player → Board compiler: compiles operations (evidence: `lib/client/player.ts`)
- Board compiler → DML value scanners: parses paths (evidence: `lib/board/compile.ts`)
- Board compiler → Geometry utilities: calculates layout (evidence: `lib/board/compile.ts`)
- Board compiler → Expression parser: compiles plots (evidence: `lib/board/compile.ts`)
- Board compiler → Handwriting font: lays out handwriting (evidence: `lib/board/compile.ts`)
- Handwriting font → Glyph symbols: uses glyphs (evidence: `lib/hand/font.ts`)
- Stroke animator → Freehand geometry: draws ink (evidence: `lib/client/animator.ts`)
- Stroke animator → SVG renderer: creates stroke nodes (evidence: `lib/client/animator.ts`)
- SVG renderer → Freehand geometry: renders ink paths (evidence: `lib/client/svgRender.ts`)
