# wumblecat/naruto-handsigns-battle architecture

> Architecture diagram of the GitHub repository wumblecat/naruto-handsigns-battle, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/wumblecat/naruto-handsigns-battle
- Repository: https://github.com/wumblecat/naruto-handsigns-battle

## Overview

Jutsu Duel is a desktop webcam/keyboard hand-sign fighting game. A player chooses an input mode, registers signs to cast jutsu, and fights a bot; the battle controller coordinates detection, sign stabilization, the deterministic engine and opponent, then results can be saved and viewed in history. The repository also documents practice, a jutsu reference, settings, account support, and a Python model-training workflow. Relationships are limited to README statements and shown source/index references; unsampled implementation details are represented at their documented subsystem paths.

Main entry points: [`src/app/router.tsx`](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/app/router.tsx) (Routes and pages), [`src/pages/BattlePage.tsx`](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/BattlePage.tsx) (Battle screen), [`src/features/battle/BattleController.ts`](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/battle/BattleController.ts) (Battle controller), [`src/pages/PlayPage.tsx`](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/PlayPage.tsx) (Play setup)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App and play"]
  node_routes["Routes and pages<br/>[router.tsx]"]
  node_play["Play setup<br/>[PlayPage.tsx]"]
  node_practice["Practice<br/>[PracticePage.tsx]"]
  node_jutsubook["Jutsu book<br/>[JutsuBookPage.tsx]"]
  node_settings["Settings<br/>[SettingsPage.tsx]"]
  node_battlepage["Battle screen<br/>[BattlePage.tsx]"]
  node_results["Match results<br/>[ResultsPage.tsx]"]
end

subgraph group_input["Sign input"]
  node_camera["Camera access<br/>[useCamera.ts]"]
  node_tracker["Hand tracking<br/>[mediapipe.ts]"]
  node_classifier["Sign recognition<br/>[model.ts]"]
  node_keyboard["Keyboard detector<br/>[keyboard.ts]"]
  node_recorder["Training recorder<br/>[RecorderPage.tsx]"]
end

subgraph group_battle["Battle runtime"]
  node_content["Game content<br/>[content.config.ts]"]
  node_balance["Game balance<br/>[balance.config.ts]"]
  node_controller["Battle controller"]
  node_stabilizer["Sign stabilizer<br/>[stabilizer.ts]"]
  node_engine["Battle engine<br/>[engine.ts]"]
  node_bot["Bot opponent<br/>[bot.ts]"]
end

subgraph group_account["Accounts and records"]
  node_save["Save match<br/>[useSaveMatch.ts]"]
  node_history["Match history<br/>[useMatchHistory.ts]"]
  node_auth["Authentication<br/>[AuthProvider.tsx]"]
  node_settingsync["Settings sync<br/>[useSettingsSync.ts]"]
  node_store[("Local settings<br/>[store.ts]")]
end

subgraph group_ml["Model training"]
  node_trainer["Model trainer<br/>[train.py]"]
  node_modelartifact["Recognition model<br/>[model.ts]"]
end

node_player(("Player"))
node_supabase[("Supabase")]

node_player -->|"opens game"| node_routes
node_routes -->|"routes to"| node_play
node_routes -->|"routes to"| node_practice
node_routes -->|"routes to"| node_jutsubook
node_routes -->|"routes to"| node_settings
node_routes -->|"routes to"| node_battlepage
node_routes -->|"routes to"| node_results
node_play -.->|"selects webcam"| node_camera
node_camera -->|"provides video"| node_tracker
node_tracker -->|"feeds landmarks"| node_classifier
node_play -.->|"selects keyboard"| node_keyboard
node_battlepage -->|"creates battle"| node_controller
node_battlepage -->|"checks model"| node_classifier
node_controller -->|"stabilizes signs"| node_stabilizer
node_controller -->|"registers signs"| node_engine
node_controller -->|"starts opponent"| node_bot
node_engine -->|"uses rules"| node_balance
node_battlepage -->|"renders themed UI"| node_content
node_engine -->|"emits battle events"| node_battlepage
node_results -->|"saves outcome"| node_save
node_save -->|"writes match"| node_supabase
node_history -->|"loads matches"| node_supabase
node_auth -.->|"uses auth service"| node_supabase
node_settings -->|"syncs preferences"| node_settingsync
node_settingsync -->|"reads and writes"| node_store
node_settingsync -->|"syncs account settings"| node_supabase
node_recorder -->|"captures hand data"| node_tracker
node_trainer -->|"exports model"| node_modelartifact
node_modelartifact -.->|"provides inference model"| node_classifier

click node_routes "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/app/router.tsx"
click node_play "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/PlayPage.tsx"
click node_practice "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/PracticePage.tsx"
click node_jutsubook "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/JutsuBookPage.tsx"
click node_settings "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/SettingsPage.tsx"
click node_content "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/content/content.config.ts"
click node_balance "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/content/balance.config.ts"
click node_camera "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/camera/useCamera.ts"
click node_tracker "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/mediapipe.ts"
click node_classifier "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/model.ts"
click node_keyboard "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/keyboard.ts"
click node_controller "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/battle/BattleController.ts"
click node_stabilizer "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/engine/stabilizer.ts"
click node_engine "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/engine/engine.ts"
click node_bot "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/opponent/bot.ts"
click node_battlepage "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/BattlePage.tsx"
click node_results "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/ResultsPage.tsx"
click node_save "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/results/useSaveMatch.ts"
click node_history "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/history/useMatchHistory.ts"
click node_auth "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/auth/AuthProvider.tsx"
click node_settingsync "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/settings/useSettingsSync.ts"
click node_store "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/lib/settings/store.ts"
click node_recorder "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/dev/RecorderPage.tsx"
click node_trainer "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/ml/jutsu_ml/train.py"
click node_modelartifact "https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/model.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_routes,node_play,node_practice,node_jutsubook,node_settings,node_battlepage,node_results toneBlue
class node_camera,node_tracker,node_classifier,node_keyboard,node_recorder,node_supabase toneAmber
class node_content,node_balance,node_controller,node_stabilizer,node_engine,node_bot toneMint
class node_save,node_history,node_auth,node_settingsync,node_store toneRose
class node_trainer,node_modelartifact,node_player toneIndigo
```

## Components

### App and play

- [Routes and pages](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/app/router.tsx): `src/app/router.tsx`
- [Play setup](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/PlayPage.tsx): `src/pages/PlayPage.tsx`
- [Practice](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/PracticePage.tsx): `src/pages/PracticePage.tsx`
- [Jutsu book](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/JutsuBookPage.tsx): `src/pages/JutsuBookPage.tsx`
- [Settings](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/SettingsPage.tsx): `src/pages/SettingsPage.tsx`
- [Battle screen](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/BattlePage.tsx): `src/pages/BattlePage.tsx`
- [Match results](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/ResultsPage.tsx): `src/pages/ResultsPage.tsx`

### Sign input

- [Camera access](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/camera/useCamera.ts): `src/features/camera/useCamera.ts`
- [Hand tracking](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/mediapipe.ts): `src/detection/mediapipe.ts`
- [Sign recognition](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/model.ts): `src/detection/model.ts`
- [Keyboard detector](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/keyboard.ts): `src/detection/keyboard.ts`
- [Training recorder](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/pages/dev/RecorderPage.tsx): `src/pages/dev/RecorderPage.tsx`

### Battle runtime

- [Game content](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/content/content.config.ts): `src/content/content.config.ts`
- [Game balance](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/content/balance.config.ts): `src/content/balance.config.ts`
- [Battle controller](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/battle/BattleController.ts): `src/features/battle/BattleController.ts`
- [Sign stabilizer](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/engine/stabilizer.ts): `src/engine/stabilizer.ts`
- [Battle engine](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/engine/engine.ts): `src/engine/engine.ts`
- [Bot opponent](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/opponent/bot.ts): `src/opponent/bot.ts`

### Accounts and records

- [Save match](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/results/useSaveMatch.ts): `src/features/results/useSaveMatch.ts`
- [Match history](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/history/useMatchHistory.ts): `src/features/history/useMatchHistory.ts`
- [Authentication](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/auth/AuthProvider.tsx): `src/features/auth/AuthProvider.tsx`
- [Settings sync](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/features/settings/useSettingsSync.ts): `src/features/settings/useSettingsSync.ts`
- [Local settings](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/lib/settings/store.ts): `src/lib/settings/store.ts`

### Model training

- [Model trainer](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/ml/jutsu_ml/train.py): `ml/jutsu_ml/train.py`
- [Recognition model](https://github.com/wumblecat/naruto-handsigns-battle/blob/main/src/detection/model.ts): `src/detection/model.ts`

### Other components

- **Player**
- **Supabase**

## Connections

- Player → Routes and pages: opens game (evidence: `src/app/router.tsx`)
- Routes and pages → Play setup: routes to (evidence: `src/app/router.tsx`)
- Routes and pages → Practice: routes to (evidence: `src/app/router.tsx`)
- Routes and pages → Jutsu book: routes to (evidence: `src/app/router.tsx`)
- Routes and pages → Settings: routes to (evidence: `src/app/router.tsx`)
- Routes and pages → Battle screen: routes to (evidence: `src/app/router.tsx`)
- Routes and pages → Match results: routes to (evidence: `src/app/router.tsx`)
- Play setup → Camera access: selects webcam
- Camera access → Hand tracking: provides video
- Hand tracking → Sign recognition: feeds landmarks (evidence: `src/detection/mediapipe.ts`)
- Play setup → Keyboard detector: selects keyboard
- Battle screen → Battle controller: creates battle (evidence: `src/pages/BattlePage.tsx`)
- Battle screen → Sign recognition: checks model (evidence: `src/pages/BattlePage.tsx`)
- Battle controller → Sign stabilizer: stabilizes signs (evidence: `src/features/battle/BattleController.ts`)
- Battle controller → Battle engine: registers signs (evidence: `src/features/battle/BattleController.ts`)
- Battle controller → Bot opponent: starts opponent (evidence: `src/features/battle/BattleController.ts`)
- Battle engine → Game balance: uses rules (evidence: `src/engine/engine.ts`)
- Battle screen → Game content: renders themed UI (evidence: `src/pages/BattlePage.tsx`)
- Battle engine → Battle screen: emits battle events (evidence: `src/pages/BattlePage.tsx`)
- Match results → Save match: saves outcome (evidence: `src/features/results/useSaveMatch.ts`)
- Save match → Supabase: writes match (evidence: `src/features/results/useSaveMatch.ts`)
- Match history → Supabase: loads matches (evidence: `src/features/history/useMatchHistory.ts`)
- Authentication → Supabase: uses auth service
- Settings → Settings sync: syncs preferences (evidence: `src/features/settings/useSettingsSync.ts`)
- Settings sync → Local settings: reads and writes (evidence: `src/features/settings/useSettingsSync.ts`)
- Settings sync → Supabase: syncs account settings (evidence: `src/features/settings/useSettingsSync.ts`)
- Training recorder → Hand tracking: captures hand data (evidence: `src/pages/dev/RecorderPage.tsx`)
- Model trainer → Recognition model: exports model (evidence: `README.md`)
- Recognition model → Sign recognition: provides inference model (evidence: `src/detection/model.ts`)
