# 6can/television-controller architecture

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

- Interactive diagram: https://gitdiagram.com/6can/television-controller
- Repository: https://github.com/6can/television-controller

## Overview

Television Controller is a local-network Android TV/Google TV remote. The browser UI discovers or accepts a TV address, pairs with its on-screen code (or reconnects using saved credentials), then sends remote, text, and app-launch commands while receiving live status. README capabilities also include editable app shortcuts, keyboard control, and responsive themes. The main UI, route, and manager relationships are supported by excerpts; some frontend-to-API and backend runtime wiring is documented but not directly shown, so those links are dashed.

Main entry points: [`web/src/App.tsx`](https://github.com/6can/television-controller/blob/master/web/src/App.tsx) (Controller UI), [`web/src/lib/api.ts`](https://github.com/6can/television-controller/blob/master/web/src/lib/api.ts) (API client), [`web/src/components/remote/remote.tsx`](https://github.com/6can/television-controller/blob/master/web/src/components/remote/remote.tsx) (Remote controls), [`server/index.js`](https://github.com/6can/television-controller/blob/master/server/index.js) (HTTP server)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Browser controller"]
  node_app["Controller UI<br/>[App.tsx]"]
  node_connection["Connect and pair<br/>[connect.tsx]"]
  node_remote["Remote controls<br/>[remote.tsx]"]
  node_dpad["Directional pad<br/>[dpad.tsx]"]
  node_button["Remote button<br/>[remote-button.tsx]"]
  node_keypad["Number and search<br/>[keypad.tsx]"]
  node_launcher["App shortcuts<br/>[app-launcher.tsx]"]
  node_volume["Live volume<br/>[volume-bar.tsx]"]
  node_keyboard["Keyboard control"]
  node_apps_hook["Shortcut preferences<br/>[use-apps.ts]"]
  node_status_hook["Status subscription<br/>[use-tv-status.ts]"]
  node_api_client["API client<br/>[api.ts]"]
  node_theme["Theme provider<br/>[theme-provider.tsx]"]
  node_tv_apps["Foreground app matching<br/>[apps.ts]"]
end

subgraph group_api["Local API"]
  node_server["HTTP server<br/>[index.js]"]
  node_tv_routes["TV routes<br/>[tv.js]"]
  node_app_routes["Shortcut routes<br/>[apps.js]"]
  node_health["Health route<br/>[health.js]"]
end

subgraph group_tv["TV connection"]
  node_discovery["Network discovery<br/>[discovery.js]"]
  node_manager["Pairing and commands<br/>[manager.js]"]
  node_catalog["Shortcut catalog<br/>[apps.js]"]
end

subgraph group_state["Local state"]
  node_config[("Persistent config<br/>[config.js]")]
end

node_user(("Computer user"))
node_android_tv(("Android TV"))

node_user -->|"uses"| node_app
node_app -->|"renders"| node_connection
node_app -->|"renders"| node_remote
node_app -->|"renders"| node_keypad
node_app -->|"renders"| node_launcher
node_app -->|"renders"| node_volume
node_app -->|"registers"| node_keyboard
node_remote -->|"renders"| node_dpad
node_remote -->|"uses"| node_button
node_app -->|"reads status"| node_status_hook
node_app -->|"loads shortcuts"| node_apps_hook
node_app -->|"matches app"| node_tv_apps
node_connection -.->|"requests"| node_api_client
node_remote -.->|"sends commands"| node_api_client
node_keypad -.->|"sends text"| node_api_client
node_launcher -.->|"launches apps"| node_api_client
node_api_client -.->|"calls API"| node_server
node_server -->|"mounts"| node_tv_routes
node_server -->|"mounts"| node_app_routes
node_server -->|"mounts"| node_health
node_tv_routes -->|"discovers via"| node_discovery
node_tv_routes -->|"dispatches"| node_manager
node_app_routes -->|"normalizes with"| node_catalog
node_app_routes -->|"reads and writes"| node_config
node_health -->|"reads"| node_config
node_manager -->|"persists credentials"| node_config
node_manager -->|"pairs and controls"| node_android_tv
node_discovery -->|"finds devices"| node_android_tv
node_android_tv -.->|"emits live state"| node_manager
node_status_hook -.->|"subscribes"| node_api_client
node_app -.->|"reads theme"| node_theme
node_app -->|"labels foreground app"| node_tv_apps
node_launcher -.->|"edits shortcuts"| node_apps_hook

click node_app "https://github.com/6can/television-controller/blob/master/web/src/App.tsx"
click node_connection "https://github.com/6can/television-controller/blob/master/web/src/components/connect/connect.tsx"
click node_remote "https://github.com/6can/television-controller/blob/master/web/src/components/remote/remote.tsx"
click node_dpad "https://github.com/6can/television-controller/blob/master/web/src/components/remote/dpad.tsx"
click node_button "https://github.com/6can/television-controller/blob/master/web/src/components/remote/remote-button.tsx"
click node_keypad "https://github.com/6can/television-controller/blob/master/web/src/components/remote/keypad.tsx"
click node_launcher "https://github.com/6can/television-controller/blob/master/web/src/components/remote/app-launcher.tsx"
click node_volume "https://github.com/6can/television-controller/blob/master/web/src/components/remote/volume-bar.tsx"
click node_keyboard "https://github.com/6can/television-controller/blob/master/web/src/hooks/use-keyboard-remote.ts"
click node_apps_hook "https://github.com/6can/television-controller/blob/master/web/src/hooks/use-apps.ts"
click node_status_hook "https://github.com/6can/television-controller/blob/master/web/src/hooks/use-tv-status.ts"
click node_api_client "https://github.com/6can/television-controller/blob/master/web/src/lib/api.ts"
click node_server "https://github.com/6can/television-controller/blob/master/server/index.js"
click node_tv_routes "https://github.com/6can/television-controller/blob/master/server/routes/tv.js"
click node_app_routes "https://github.com/6can/television-controller/blob/master/server/routes/apps.js"
click node_health "https://github.com/6can/television-controller/blob/master/server/routes/health.js"
click node_discovery "https://github.com/6can/television-controller/blob/master/server/tv/discovery.js"
click node_manager "https://github.com/6can/television-controller/blob/master/server/tv/manager.js"
click node_catalog "https://github.com/6can/television-controller/blob/master/server/tv/apps.js"
click node_config "https://github.com/6can/television-controller/blob/master/server/config.js"
click node_theme "https://github.com/6can/television-controller/blob/master/web/src/components/theme-provider.tsx"
click node_tv_apps "https://github.com/6can/television-controller/blob/master/web/src/lib/apps.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_connection,node_remote,node_dpad,node_button,node_keypad,node_launcher,node_volume,node_keyboard,node_apps_hook,node_status_hook,node_api_client,node_theme,node_tv_apps,node_user toneBlue
class node_server,node_tv_routes,node_app_routes,node_health toneAmber
class node_discovery,node_manager,node_catalog toneMint
class node_config toneRose
class node_android_tv toneIndigo
```

## Components

### Browser controller

- [Controller UI](https://github.com/6can/television-controller/blob/master/web/src/App.tsx): `web/src/App.tsx`
- [Connect and pair](https://github.com/6can/television-controller/blob/master/web/src/components/connect/connect.tsx): `web/src/components/connect/connect.tsx`
- [Remote controls](https://github.com/6can/television-controller/blob/master/web/src/components/remote/remote.tsx): `web/src/components/remote/remote.tsx`
- [Directional pad](https://github.com/6can/television-controller/blob/master/web/src/components/remote/dpad.tsx): `web/src/components/remote/dpad.tsx`
- [Remote button](https://github.com/6can/television-controller/blob/master/web/src/components/remote/remote-button.tsx): `web/src/components/remote/remote-button.tsx`
- [Number and search](https://github.com/6can/television-controller/blob/master/web/src/components/remote/keypad.tsx): `web/src/components/remote/keypad.tsx`
- [App shortcuts](https://github.com/6can/television-controller/blob/master/web/src/components/remote/app-launcher.tsx): `web/src/components/remote/app-launcher.tsx`
- [Live volume](https://github.com/6can/television-controller/blob/master/web/src/components/remote/volume-bar.tsx): `web/src/components/remote/volume-bar.tsx`
- [Keyboard control](https://github.com/6can/television-controller/blob/master/web/src/hooks/use-keyboard-remote.ts): `web/src/hooks/use-keyboard-remote.ts`
- [Shortcut preferences](https://github.com/6can/television-controller/blob/master/web/src/hooks/use-apps.ts): `web/src/hooks/use-apps.ts`
- [Status subscription](https://github.com/6can/television-controller/blob/master/web/src/hooks/use-tv-status.ts): `web/src/hooks/use-tv-status.ts`
- [API client](https://github.com/6can/television-controller/blob/master/web/src/lib/api.ts): `web/src/lib/api.ts`
- [Theme provider](https://github.com/6can/television-controller/blob/master/web/src/components/theme-provider.tsx): `web/src/components/theme-provider.tsx`
- [Foreground app matching](https://github.com/6can/television-controller/blob/master/web/src/lib/apps.ts): `web/src/lib/apps.ts`

### Local API

- [HTTP server](https://github.com/6can/television-controller/blob/master/server/index.js): `server/index.js`
- [TV routes](https://github.com/6can/television-controller/blob/master/server/routes/tv.js): `server/routes/tv.js`
- [Shortcut routes](https://github.com/6can/television-controller/blob/master/server/routes/apps.js): `server/routes/apps.js`
- [Health route](https://github.com/6can/television-controller/blob/master/server/routes/health.js): `server/routes/health.js`

### TV connection

- [Network discovery](https://github.com/6can/television-controller/blob/master/server/tv/discovery.js): `server/tv/discovery.js`
- [Pairing and commands](https://github.com/6can/television-controller/blob/master/server/tv/manager.js): `server/tv/manager.js`
- [Shortcut catalog](https://github.com/6can/television-controller/blob/master/server/tv/apps.js): `server/tv/apps.js`

### Local state

- [Persistent config](https://github.com/6can/television-controller/blob/master/server/config.js): `server/config.js`

### Other components

- **Computer user**
- **Android TV**

## Connections

- Computer user → Controller UI: uses (evidence: `README.md`)
- Controller UI → Connect and pair: renders (evidence: `web/src/App.tsx`)
- Controller UI → Remote controls: renders (evidence: `web/src/App.tsx`)
- Controller UI → Number and search: renders (evidence: `web/src/App.tsx`)
- Controller UI → App shortcuts: renders (evidence: `web/src/App.tsx`)
- Controller UI → Live volume: renders (evidence: `web/src/App.tsx`)
- Controller UI → Keyboard control: registers (evidence: `web/src/App.tsx`)
- Remote controls → Directional pad: renders (evidence: `web/src/components/remote/remote.tsx`)
- Remote controls → Remote button: uses (evidence: `web/src/components/remote/remote.tsx`)
- Controller UI → Status subscription: reads status (evidence: `web/src/App.tsx`)
- Controller UI → Shortcut preferences: loads shortcuts (evidence: `web/src/App.tsx`)
- Controller UI → Foreground app matching: matches app (evidence: `web/src/App.tsx`)
- Connect and pair → API client: requests
- Remote controls → API client: sends commands
- Number and search → API client: sends text
- App shortcuts → API client: launches apps
- API client → HTTP server: calls API
- HTTP server → TV routes: mounts (evidence: `server/index.js`)
- HTTP server → Shortcut routes: mounts (evidence: `server/index.js`)
- HTTP server → Health route: mounts (evidence: `server/index.js`)
- TV routes → Network discovery: discovers via (evidence: `server/routes/tv.js`)
- TV routes → Pairing and commands: dispatches (evidence: `server/routes/tv.js`)
- Shortcut routes → Shortcut catalog: normalizes with (evidence: `server/routes/apps.js`)
- Shortcut routes → Persistent config: reads and writes (evidence: `server/routes/apps.js`)
- Health route → Persistent config: reads (evidence: `server/routes/health.js`)
- Pairing and commands → Persistent config: persists credentials (evidence: `server/tv/manager.js`)
- Pairing and commands → Android TV: pairs and controls (evidence: `server/tv/manager.js`)
- Network discovery → Android TV: finds devices (evidence: `server/tv/discovery.js`)
- Android TV → Pairing and commands: emits live state
- Status subscription → API client: subscribes
- Controller UI → Theme provider: reads theme
- Controller UI → Foreground app matching: labels foreground app (evidence: `web/src/App.tsx`)
- App shortcuts → Shortcut preferences: edits shortcuts
