# asim-stha/punte architecture

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

- Interactive diagram: https://gitdiagram.com/asim-stha/punte
- Repository: https://github.com/asim-stha/punte

## Overview

Punte is a web-controlled desktop buddy robot. Users log in, choose web or robot mode, then chat or control the robot; the UI can recognize and save faces, retain memory, and relay robot camera and sensor events. The backend owns API routing, authentication, AI and voice requests, and WebSocket relays, with selectable persistence and separate speech services. README relationships establish the deployment topology; sampled source confirms key frontend/backend calls. Unshown subsystem details and some network wiring are represented only where explicitly documented.

Main entry points: [`backend/server.js`](https://github.com/asim-stha/punte/blob/main/backend/server.js) (API and WebSocket server), [`frontend/src/App.jsx`](https://github.com/asim-stha/punte/blob/main/frontend/src/App.jsx) (UI and routing), [`backend/lib/storage.js`](https://github.com/asim-stha/punte/blob/main/backend/lib/storage.js) (Storage selection), [`frontend/src/hooks/useBuddy.js`](https://github.com/asim-stha/punte/blob/main/frontend/src/hooks/useBuddy.js) (Buddy behavior)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web experience"]
  node_app["UI and routing<br/>[App.jsx]"]
  node_buddy["Buddy behavior<br/>[useBuddy.js]"]
  node_commands["Commands and chat logic<br/>[commands.js]"]
  node_panels["Chat, memory, settings"]
  node_robotview["Robot display<br/>[RobotView.jsx]"]
  node_robotart["Web robot rendering<br/>[PunteRobot.jsx]"]
  node_robot3d["3D model<br/>[punte3d.js]"]
  node_api["API client<br/>[api.js]"]
end

subgraph group_server["Backend services"]
  node_backend["API and WebSocket server<br/>[server.js]"]
  node_auth["Authentication<br/>[auth.js]"]
  node_ai["AI proxy<br/>[ai.js]"]
  node_voice["Text-to-speech<br/>[tts.js]"]
  node_hearing["Speech recognition client<br/>[stt.js]"]
  node_ttsservice["Piper speech service<br/>[server.py]"]
  node_sttservice["Whisper speech service<br/>[server.py]"]
end

subgraph group_device["Robot hardware"]
  node_robot["ESP32 body<br/>[desktop_body.ino]"]
  node_camera["ESP32 camera<br/>[esp32_cam.ino]"]
end

subgraph group_data["Persistence"]
  node_storeconfig["Storage selection<br/>[storage.js]"]
  node_postgres[("PostgreSQL storage")]
  node_supabase[("Supabase storage")]
  node_filestore[("File storage<br/>[storage-file.js]")]
  node_mirror["Mirrored storage<br/>[storage-mirror.js]"]
  node_database[("PostgreSQL database<br/>[init.sql]")]
end

node_user(("User"))

node_user -->|"uses"| node_app
node_app -->|"creates"| node_buddy
node_app -->|"renders"| node_panels
node_app -->|"renders"| node_robotview
node_app -->|"renders"| node_robotart
node_buddy -->|"requests"| node_api
node_buddy -->|"uses"| node_commands
node_robotart -->|"loads"| node_robot3d
node_api -->|"calls API"| node_backend
node_backend -->|"authenticates"| node_auth
node_backend -->|"requests chat"| node_ai
node_backend -.->|"requests speech"| node_voice
node_backend -->|"transcribes audio"| node_hearing
node_voice -.->|"calls service"| node_ttsservice
node_hearing -.->|"calls service"| node_sttservice
node_buddy -->|"sends commands"| node_robot
node_robot -->|"connects WebSocket"| node_backend
node_camera -->|"sends images"| node_backend
node_backend -->|"relays events"| node_robotview
node_backend -->|"routes data"| node_storeconfig
node_storeconfig -->|"selects"| node_postgres
node_storeconfig -->|"selects"| node_supabase
node_storeconfig -->|"selects"| node_filestore
node_storeconfig -->|"wraps stores"| node_mirror
node_mirror -->|"delegates"| node_postgres
node_mirror -->|"delegates"| node_supabase
node_postgres -->|"reads and writes"| node_database

click node_app "https://github.com/asim-stha/punte/blob/main/frontend/src/App.jsx"
click node_buddy "https://github.com/asim-stha/punte/blob/main/frontend/src/hooks/useBuddy.js"
click node_commands "https://github.com/asim-stha/punte/blob/main/frontend/src/lib/commands.js"
click node_panels "https://github.com/asim-stha/punte/tree/main/frontend/src/views"
click node_robotview "https://github.com/asim-stha/punte/blob/main/frontend/src/components/RobotView.jsx"
click node_robotart "https://github.com/asim-stha/punte/blob/main/frontend/src/components/PunteRobot.jsx"
click node_robot3d "https://github.com/asim-stha/punte/blob/main/frontend/src/lib/punte3d.js"
click node_api "https://github.com/asim-stha/punte/blob/main/frontend/src/api.js"
click node_backend "https://github.com/asim-stha/punte/blob/main/backend/server.js"
click node_auth "https://github.com/asim-stha/punte/blob/main/backend/lib/auth.js"
click node_ai "https://github.com/asim-stha/punte/blob/main/backend/lib/ai.js"
click node_voice "https://github.com/asim-stha/punte/blob/main/backend/lib/tts.js"
click node_hearing "https://github.com/asim-stha/punte/blob/main/backend/lib/stt.js"
click node_ttsservice "https://github.com/asim-stha/punte/blob/main/tts/server.py"
click node_sttservice "https://github.com/asim-stha/punte/blob/main/stt/server.py"
click node_robot "https://github.com/asim-stha/punte/blob/main/firmware/desktop_body/desktop_body.ino"
click node_camera "https://github.com/asim-stha/punte/blob/main/firmware/esp32_cam/esp32_cam.ino"
click node_storeconfig "https://github.com/asim-stha/punte/blob/main/backend/lib/storage.js"
click node_postgres "https://github.com/asim-stha/punte/blob/main/backend/lib/storage-postgres.js"
click node_supabase "https://github.com/asim-stha/punte/blob/main/backend/lib/storage-supabase.js"
click node_filestore "https://github.com/asim-stha/punte/blob/main/backend/lib/storage-file.js"
click node_mirror "https://github.com/asim-stha/punte/blob/main/backend/lib/storage-mirror.js"
click node_database "https://github.com/asim-stha/punte/blob/main/database/init.sql"

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_buddy,node_commands,node_panels,node_robotview,node_robotart,node_robot3d,node_api,node_user toneBlue
class node_backend,node_auth,node_ai,node_voice,node_hearing,node_ttsservice,node_sttservice toneAmber
class node_robot,node_camera toneMint
class node_storeconfig,node_postgres,node_supabase,node_filestore,node_mirror,node_database toneRose
```

## Components

### Web experience

- [UI and routing](https://github.com/asim-stha/punte/blob/main/frontend/src/App.jsx): `frontend/src/App.jsx`
- [Buddy behavior](https://github.com/asim-stha/punte/blob/main/frontend/src/hooks/useBuddy.js): `frontend/src/hooks/useBuddy.js`
- [Commands and chat logic](https://github.com/asim-stha/punte/blob/main/frontend/src/lib/commands.js): `frontend/src/lib/commands.js`
- [Chat, memory, settings](https://github.com/asim-stha/punte/tree/main/frontend/src/views): `frontend/src/views`
- [Robot display](https://github.com/asim-stha/punte/blob/main/frontend/src/components/RobotView.jsx): `frontend/src/components/RobotView.jsx`
- [Web robot rendering](https://github.com/asim-stha/punte/blob/main/frontend/src/components/PunteRobot.jsx): `frontend/src/components/PunteRobot.jsx`
- [3D model](https://github.com/asim-stha/punte/blob/main/frontend/src/lib/punte3d.js): `frontend/src/lib/punte3d.js`
- [API client](https://github.com/asim-stha/punte/blob/main/frontend/src/api.js): `frontend/src/api.js`

### Backend services

- [API and WebSocket server](https://github.com/asim-stha/punte/blob/main/backend/server.js): `backend/server.js`
- [Authentication](https://github.com/asim-stha/punte/blob/main/backend/lib/auth.js): `backend/lib/auth.js`
- [AI proxy](https://github.com/asim-stha/punte/blob/main/backend/lib/ai.js): `backend/lib/ai.js`
- [Text-to-speech](https://github.com/asim-stha/punte/blob/main/backend/lib/tts.js): `backend/lib/tts.js`
- [Speech recognition client](https://github.com/asim-stha/punte/blob/main/backend/lib/stt.js): `backend/lib/stt.js`
- [Piper speech service](https://github.com/asim-stha/punte/blob/main/tts/server.py): `tts/server.py`
- [Whisper speech service](https://github.com/asim-stha/punte/blob/main/stt/server.py): `stt/server.py`

### Robot hardware

- [ESP32 body](https://github.com/asim-stha/punte/blob/main/firmware/desktop_body/desktop_body.ino): `firmware/desktop_body/desktop_body.ino`
- [ESP32 camera](https://github.com/asim-stha/punte/blob/main/firmware/esp32_cam/esp32_cam.ino): `firmware/esp32_cam/esp32_cam.ino`

### Persistence

- [Storage selection](https://github.com/asim-stha/punte/blob/main/backend/lib/storage.js): `backend/lib/storage.js`
- [PostgreSQL storage](https://github.com/asim-stha/punte/blob/main/backend/lib/storage-postgres.js): `backend/lib/storage-postgres.js`
- [Supabase storage](https://github.com/asim-stha/punte/blob/main/backend/lib/storage-supabase.js): `backend/lib/storage-supabase.js`
- [File storage](https://github.com/asim-stha/punte/blob/main/backend/lib/storage-file.js): `backend/lib/storage-file.js`
- [Mirrored storage](https://github.com/asim-stha/punte/blob/main/backend/lib/storage-mirror.js): `backend/lib/storage-mirror.js`
- [PostgreSQL database](https://github.com/asim-stha/punte/blob/main/database/init.sql): `database/init.sql`

### Other components

- **User**

## Connections

- User → UI and routing: uses (evidence: `README.md`)
- UI and routing → Buddy behavior: creates (evidence: `frontend/src/App.jsx`)
- UI and routing → Chat, memory, settings: renders (evidence: `frontend/src/App.jsx`)
- UI and routing → Robot display: renders (evidence: `frontend/src/App.jsx`)
- UI and routing → Web robot rendering: renders (evidence: `frontend/src/App.jsx`)
- Buddy behavior → API client: requests (evidence: `frontend/src/hooks/useBuddy.js`)
- Buddy behavior → Commands and chat logic: uses (evidence: `frontend/src/hooks/useBuddy.js`)
- Web robot rendering → 3D model: loads (evidence: `frontend/src/components/PunteRobot.jsx`)
- API client → API and WebSocket server: calls API (evidence: `frontend/src/api.js`)
- API and WebSocket server → Authentication: authenticates (evidence: `backend/server.js`)
- API and WebSocket server → AI proxy: requests chat (evidence: `backend/server.js`)
- API and WebSocket server → Text-to-speech: requests speech (evidence: `backend/server.js`)
- API and WebSocket server → Speech recognition client: transcribes audio (evidence: `backend/server.js`)
- Text-to-speech → Piper speech service: calls service (evidence: `README.md`)
- Speech recognition client → Whisper speech service: calls service (evidence: `README.md`)
- Buddy behavior → ESP32 body: sends commands (evidence: `README.md`)
- ESP32 body → API and WebSocket server: connects WebSocket (evidence: `README.md`)
- ESP32 camera → API and WebSocket server: sends images (evidence: `README.md`)
- API and WebSocket server → Robot display: relays events (evidence: `backend/server.js`)
- API and WebSocket server → Storage selection: routes data (evidence: `backend/server.js`)
- Storage selection → PostgreSQL storage: selects (evidence: `backend/lib/storage.js`)
- Storage selection → Supabase storage: selects (evidence: `backend/lib/storage.js`)
- Storage selection → File storage: selects (evidence: `backend/lib/storage.js`)
- Storage selection → Mirrored storage: wraps stores (evidence: `backend/lib/storage.js`)
- Mirrored storage → PostgreSQL storage: delegates (evidence: `backend/lib/storage-mirror.js`)
- Mirrored storage → Supabase storage: delegates (evidence: `backend/lib/storage-mirror.js`)
- PostgreSQL storage → PostgreSQL database: reads and writes (evidence: `backend/lib/storage-postgres.js`)
