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