Files
Catubba 68e52cff68 feat: dashboard health pill, per-card actions, failure visibility
- header pill now reports health: red with route and time when the last
  run failed, green all-OK with the next fire when it succeeded
- Run button on every route card; Run GC / Run verify on every PBS card,
  each opening the confirm dialog pre-targeted (no subject dropdown)
- Manual run panel and the backup-map legend removed; Upcoming runs
  fills the rail and shows roughly twice the schedule
- guests never backed up render amber with a count in the panel header
- action failures scroll their banner into view; a failed route toggle
  reports the reason instead of silently snapping back
- Enter submits the route modal; disclosure in run history is a real
  button; legend pills and route cards no longer focusable non-widgets
- 44px touch targets for power, chips and card buttons on phones
2026-08-08 18:55:31 +02:00
..
2026-07-02 20:46:57 +02:00
2026-08-05 16:20:41 +02:00
2026-07-02 20:46:57 +02:00

Joulenap frontend

React + TypeScript + Vite SPA for Joulenap, wired to the backend REST API.

Develop

cd frontend
npm ci
npm run dev        # Vite dev server on :5173, proxies /api -> http://localhost:8080

Run the backend (cd backend && joulenap or uvicorn app.main:create_app --factory) alongside it so the proxied API is available.

Build

npm run build      # type-checks (tsc --noEmit) then emits frontend/dist

The FastAPI backend serves frontend/dist as static files, so a production image just needs the built output present. dist/ is git-ignored.

Layout

  • src/api/ — typed client + response types for /api/*
  • src/auth/, src/config/ — auth + config React contexts
  • src/pages/Login, Dashboard (+ dashboard/ panels), Settings (+ settings/ panels, incl. the device editor)
  • src/wizard/ — the two device wizards (add a PVE, add a PBS) and the PBS steps they share
  • src/shell/ — header + authenticated app shell
  • src/components/, src/hooks/, src/utils/ — shared widgets/helpers
  • src/i18n/react-i18next setup; en.json is the base language, it.json the translation

i18n

English is the source language. The active language follows app.language from the backend config (the Localization settings panel changes it). Add a key to en.json first, then mirror it in it.json.