# jo-danyeong/fado architecture

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

- Interactive diagram: https://gitdiagram.com/jo-danyeong/fado
- Repository: https://github.com/jo-danyeong/fado

## Overview

FaDO lets users create, manage, and select pixel-art expressions for a Raspberry Pi OLED, with a studio workflow for live camera recognition and automatic expression display. The frontend provides studio, library, settings, and guide views; its workspace state persists locally, while expression actions upload PNGs and send display commands through the Spring backend. The backend bridges browser requests to the Raspberry Pi server and camera service. The Raspberry Pi server exposes camera and YOLO routes and stores uploaded expression images for display. Several UI pages and server modules are represented from the tree and index; their internal wiring is not shown in the excerpts, so uncertain links are omitted.

Main entry points: [`Frontend/src/App.jsx`](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/App.jsx) (App shell), [`RPiServer/main.py`](https://github.com/jo-danyeong/fado/blob/main/RPiServer/main.py) (FastAPI application), [`Frontend/src/context/WorkspaceContext.jsx`](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/context/WorkspaceContext.jsx) (Workspace state), [`Frontend/src/hooks/useDetection.js`](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/hooks/useDetection.js) (Detection workflow)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Frontend experience"]
  node_app["App shell<br/>[App.jsx]"]
  node_views["Studio, library, settings, guide"]
  node_editor["Expression editor"]
  node_actions["Expression actions"]
  node_workspace["Workspace state"]
  node_workspace_core["Workspace rules<br/>[workspace.js]"]
  node_browser_storage[("Browser persistence<br/>[storage.js]")]
  node_presets["Expression presets<br/>[presets.js]"]
  node_detection_hook["Detection workflow<br/>[useDetection.js]"]
  node_recognition["Recognition policy"]
  node_detection_service["Detection requests<br/>[detection.js]"]
  node_camera_service["Camera capture<br/>[camera.js]"]
  node_api_service["Device API client<br/>[api.js]"]
end

subgraph group_backend["Spring API bridge"]
  node_backend_controllers["Pi API controllers"]
  node_camera_controller["Camera proxy"]
  node_image_controller["Expression image API"]
  node_raspberry_client["Pi HTTP client"]
end

subgraph group_rpi_server["Pi inference server"]
  node_rpi_api["FastAPI application<br/>[main.py]"]
  node_camera_stream["Camera stream routes<br/>[camera_stream.py]"]
  node_yolo_api["YOLO inference routes<br/>[yolo_api.py]"]
  node_models["NCNN model runtime<br/>[main.py]"]
  node_expression_images[("Expression PNG files<br/>[main.py]")]
end

subgraph group_pi_device["Pi device"]
  node_display["OLED display helper<br/>[ImgTest.py]"]
end

node_user(("FaDO user"))
node_camera(("Raspberry Pi camera"))

node_user -->|"uses"| node_app
node_app -->|"routes to"| node_views
node_app -->|"opens"| node_editor
node_app -->|"creates"| node_actions
node_app -->|"reads state"| node_workspace
node_workspace -->|"reduces state"| node_workspace_core
node_workspace -->|"loads and saves"| node_browser_storage
node_workspace -->|"initializes from"| node_presets
node_detection_hook -->|"requests detection"| node_detection_service
node_detection_hook -->|"tracks results"| node_recognition
node_detection_hook -->|"captures frames"| node_camera_service
node_detection_hook -->|"selects expression"| node_actions
node_actions -->|"updates state"| node_workspace
node_actions -->|"uploads and sends"| node_api_service
node_user -->|"provides video"| node_camera
node_api_service -.->|"calls API"| node_backend_controllers
node_backend_controllers -->|"delegates Pi requests"| node_raspberry_client
node_camera_controller -->|"proxies detection"| node_camera
node_raspberry_client -->|"sends HTTP requests"| node_rpi_api
node_rpi_api -->|"registers routes"| node_camera_stream
node_rpi_api -->|"registers routes"| node_yolo_api
node_rpi_api -->|"reads and writes"| node_expression_images
node_rpi_api -->|"displays expression"| node_display
node_camera_stream -.->|"streams video"| node_camera
node_yolo_api -.->|"runs inference"| node_models

click node_app "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/App.jsx"
click node_views "https://github.com/jo-danyeong/fado/tree/main/Frontend/src/pages"
click node_editor "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/features/editor/ExpressionEditor.jsx"
click node_actions "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/features/useExpressionActions.js"
click node_workspace "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/context/WorkspaceContext.jsx"
click node_workspace_core "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/core/workspace.js"
click node_browser_storage "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/storage.js"
click node_presets "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/data/presets.js"
click node_detection_hook "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/hooks/useDetection.js"
click node_recognition "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/core/expressionRecognition.js"
click node_detection_service "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/detection.js"
click node_camera_service "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/camera.js"
click node_api_service "https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/api.js"
click node_backend_controllers "https://github.com/jo-danyeong/fado/tree/main/Backend/src/main/java/backend/server/RaspberryPi/API"
click node_camera_controller "https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/API/CameraController.java"
click node_image_controller "https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/API/ExpressionImageController.java"
click node_raspberry_client "https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/RaspberryClient.java"
click node_rpi_api "https://github.com/jo-danyeong/fado/blob/main/RPiServer/main.py"
click node_camera_stream "https://github.com/jo-danyeong/fado/blob/main/RPiServer/camera_stream.py"
click node_yolo_api "https://github.com/jo-danyeong/fado/blob/main/RPiServer/yolo_api.py"
click node_models "https://github.com/jo-danyeong/fado/blob/main/RPiServer/models/main.py"
click node_expression_images "https://github.com/jo-danyeong/fado/blob/main/RPiServer/main.py"
click node_display "https://github.com/jo-danyeong/fado/blob/main/RaspberryPi/ImgTest.py"

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_views,node_editor,node_actions,node_workspace,node_workspace_core,node_browser_storage,node_presets,node_detection_hook,node_recognition,node_detection_service,node_camera_service,node_api_service,node_user toneBlue
class node_backend_controllers,node_camera_controller,node_image_controller,node_raspberry_client toneAmber
class node_rpi_api,node_camera_stream,node_yolo_api,node_models,node_expression_images toneMint
class node_display toneRose
class node_camera toneIndigo
```

## Components

### Frontend experience

- [App shell](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/App.jsx): `Frontend/src/App.jsx`
- [Studio, library, settings, guide](https://github.com/jo-danyeong/fado/tree/main/Frontend/src/pages): `Frontend/src/pages`
- [Expression editor](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/features/editor/ExpressionEditor.jsx): `Frontend/src/features/editor/ExpressionEditor.jsx`
- [Expression actions](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/features/useExpressionActions.js): `Frontend/src/features/useExpressionActions.js`
- [Workspace state](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/context/WorkspaceContext.jsx): `Frontend/src/context/WorkspaceContext.jsx`
- [Workspace rules](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/core/workspace.js): `Frontend/src/core/workspace.js`
- [Browser persistence](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/storage.js): `Frontend/src/services/storage.js`
- [Expression presets](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/data/presets.js): `Frontend/src/data/presets.js`
- [Detection workflow](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/hooks/useDetection.js): `Frontend/src/hooks/useDetection.js`
- [Recognition policy](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/core/expressionRecognition.js): `Frontend/src/core/expressionRecognition.js`
- [Detection requests](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/detection.js): `Frontend/src/services/detection.js`
- [Camera capture](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/camera.js): `Frontend/src/services/camera.js`
- [Device API client](https://github.com/jo-danyeong/fado/blob/main/Frontend/src/services/api.js): `Frontend/src/services/api.js`

### Spring API bridge

- [Pi API controllers](https://github.com/jo-danyeong/fado/tree/main/Backend/src/main/java/backend/server/RaspberryPi/API): `Backend/src/main/java/backend/server/RaspberryPi/API`
- [Camera proxy](https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/API/CameraController.java): `Backend/src/main/java/backend/server/RaspberryPi/API/CameraController.java`
- [Expression image API](https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/API/ExpressionImageController.java): `Backend/src/main/java/backend/server/RaspberryPi/API/ExpressionImageController.java`
- [Pi HTTP client](https://github.com/jo-danyeong/fado/blob/main/Backend/src/main/java/backend/server/RaspberryPi/RaspberryClient.java): `Backend/src/main/java/backend/server/RaspberryPi/RaspberryClient.java`

### Pi inference server

- [FastAPI application](https://github.com/jo-danyeong/fado/blob/main/RPiServer/main.py): `RPiServer/main.py`
- [Camera stream routes](https://github.com/jo-danyeong/fado/blob/main/RPiServer/camera_stream.py): `RPiServer/camera_stream.py`
- [YOLO inference routes](https://github.com/jo-danyeong/fado/blob/main/RPiServer/yolo_api.py): `RPiServer/yolo_api.py`
- [NCNN model runtime](https://github.com/jo-danyeong/fado/blob/main/RPiServer/models/main.py): `RPiServer/models/main.py`
- [Expression PNG files](https://github.com/jo-danyeong/fado/blob/main/RPiServer/main.py): `RPiServer/main.py`

### Pi device

- [OLED display helper](https://github.com/jo-danyeong/fado/blob/main/RaspberryPi/ImgTest.py): `RaspberryPi/ImgTest.py`

### Other components

- **FaDO user**
- **Raspberry Pi camera**

## Connections

- FaDO user → App shell: uses
- App shell → Studio, library, settings, guide: routes to (evidence: `Frontend/src/App.jsx`)
- App shell → Expression editor: opens (evidence: `Frontend/src/App.jsx`)
- App shell → Expression actions: creates (evidence: `Frontend/src/App.jsx`)
- App shell → Workspace state: reads state (evidence: `Frontend/src/App.jsx`)
- Workspace state → Workspace rules: reduces state (evidence: `Frontend/src/context/WorkspaceContext.jsx`)
- Workspace state → Browser persistence: loads and saves (evidence: `Frontend/src/context/WorkspaceContext.jsx`)
- Workspace state → Expression presets: initializes from (evidence: `Frontend/src/context/WorkspaceContext.jsx`)
- Detection workflow → Detection requests: requests detection (evidence: `Frontend/src/hooks/useDetection.js`)
- Detection workflow → Recognition policy: tracks results (evidence: `Frontend/src/hooks/useDetection.js`)
- Detection workflow → Camera capture: captures frames (evidence: `Frontend/src/hooks/useDetection.js`)
- Detection workflow → Expression actions: selects expression (evidence: `Frontend/src/hooks/useDetection.js`)
- Expression actions → Workspace state: updates state (evidence: `Frontend/src/features/useExpressionActions.js`)
- Expression actions → Device API client: uploads and sends (evidence: `Frontend/src/features/useExpressionActions.js`)
- FaDO user → Raspberry Pi camera: provides video
- Device API client → Pi API controllers: calls API
- Pi API controllers → Pi HTTP client: delegates Pi requests (evidence: `Backend/src/main/java/backend/server/RaspberryPi/API/ExpressionImageController.java`)
- Camera proxy → Raspberry Pi camera: proxies detection (evidence: `Backend/src/main/java/backend/server/RaspberryPi/API/CameraController.java`)
- Pi HTTP client → FastAPI application: sends HTTP requests (evidence: `Backend/src/main/java/backend/server/RaspberryPi/RaspberryClient.java`)
- FastAPI application → Camera stream routes: registers routes (evidence: `RPiServer/main.py`)
- FastAPI application → YOLO inference routes: registers routes (evidence: `RPiServer/main.py`)
- FastAPI application → Expression PNG files: reads and writes (evidence: `RPiServer/main.py`)
- FastAPI application → OLED display helper: displays expression (evidence: `RPiServer/main.py`)
- Camera stream routes → Raspberry Pi camera: streams video
- YOLO inference routes → NCNN model runtime: runs inference
