Frontend architecture¶
The DUMB frontend is a Nuxt 4 application that renders the dashboard, service controls, and embedded UIs. It communicates with the DUMB API for configuration, logs, metrics, and service status.
Key directories¶
| Path | Purpose |
|---|---|
pages/ |
Route-driven pages (dashboard, settings, onboarding) |
components/ |
Reusable UI components |
composables/ |
Shared logic and API hooks |
stores/ |
Pinia stores for app state |
services/ |
API clients and service abstractions |
layouts/ |
Layout templates |
Data flow¶
%%{ init: { "flowchart": { "curve": "basis" } } }%%
flowchart LR
CLIENT([Browser UI or API client])
ST[Pinia stores]
FE[dmbdb server<br/>port 3005]
BE[[DUMB API<br/>127.0.0.1:8000]]
CLIENT ==>|UI state| ST
ST ==>|REST /api/*| FE
CLIENT ==>|external REST /api/*| FE
FE ==>|strip /api and forward| BE
CLIENT -.->|WebSocket /ws/*| FE
FE -.->|forward unchanged| BE
The frontend server is also the public API gateway. Its /api/* middleware
removes the leading /api and forwards the request to the backend-native route
on port 8000. For example, :3005/api/config becomes :8000/config.
WebSockets use /ws/* on both sides and are forwarded without that rewrite.
This same-origin design lets the browser avoid cross-origin API calls and means
the standard Compose deployment needs to publish only port 3005. External
automation can use the gateway too; backend authentication is still applied
after the request is forwarded.
Embedded service UIs¶
The frontend can embed service UIs in iframes when Traefik is enabled, keeping navigation and authentication within the DUMB experience.
Traefik paths
DUMB-owned embedded UIs use Traefik paths like http://<host>:18080/service/ui/radarr or http://<host>:18080/service/ui/sonarr when proxying is enabled. Inside dmbdb service pages, iframe traffic is routed through frontend /ui/<service> paths so root-style service apps can keep their own relative URLs.
Configuration UX¶
Configuration editing is performed in the settings UI, which:
- Reads service config from the API
- Validates changes client-side where possible
- Submits updates to the backend for persistence