Cleanup: delete dead top-level pages + update docs (Slice 11)

Delete the old top-level page files whose content was migrated into
service-page tabs in slices 5-9:
- pages/Media.tsx, Applications.tsx (-> MediaTab)
- pages/FileBrowser.tsx, FileBrowser.impl.tsx (-> FilesTab)
- pages/Actions.tsx (-> ActionsTab)
- pages/Users.tsx, UsersPage.impl.tsx (replaced by Authentik tabs)
- components/BackupsPage.tsx (-> JobsTab)
- components/ObservabilityPage.tsx (split into Alerts/Links/Metrics tabs)
- hooks/useUsers.ts (orphaned after Users page deletion)
- the corresponding page test files (Media, FileBrowser, Applications,
  Actions, UsersPage) that tested the deleted pages directly.

The service-tab components are the live implementations; ServicePage
renders them. No live code references the deleted files.

Docs: append an Information Architecture section to REQUIREMENTS.md
documenting the services-as-hub model (nav shape, service-page tabs,
service type registry, Users->Authentik, Observability split, legacy
route 404s, empty state). Add a CHANGELOG entry under [Unreleased].

92 frontend tests pass (was 112; -20 deleted page tests); 271 backend
tests pass; lint/build green.

Refs openspec/changes/services-as-hub-ia/ (tasks slice 11).
This commit is contained in:
Developer
2026-06-26 20:11:02 +00:00
parent ec57eff59a
commit a8dfbd5dc6
45 changed files with 3441 additions and 4711 deletions
+40
View File
@@ -468,3 +468,43 @@ The system receives backup execution reports from an external backup tool via HT
- Backup tool uses auto-generated Bearer API key
- Frontend uses existing OIDC/JWT auth
## Information Architecture (services-as-hub)
The app is organized around **services as the hub**. The top-level navigation
contains a small always-visible core plus conditional per-type entries and
user-created named dashboards.
### Top-level navigation
- **Main Dashboard** (`/`) — always visible, special (not deletable, default landing).
- **Named dashboards** (`/d/:slug`) — one top-level entry each, user-controlled order, composed of pinned service links (and widgets in a follow-up).
- **Conditional service-type entries** — appear only when at least one enabled instance of the type exists: `jellyfin`→Media, `ssh_tasks`→Files+Actions, `alertmanager`→Alerts, `grafana`→Grafana, `prometheus`→Prometheus, `backups`→Backups, `authentik`→Users. `nextcloud` contributes no entry.
- **Services** (`/services`) — always visible admin hub for managing service instances and named dashboards.
- **Settings** (`/settings`) — always visible.
### Service page
Every service page uses the tab skeleton `[Overview | type-specific content tabs | Widgets | Config]`. Content tabs per type: jellyfin=Media+Requests, ssh_tasks=Files+Actions, backups=Jobs, authentik=Users+Messaging, alertmanager=Alerts, grafana=Links, prometheus=Metrics. When >1 enabled instance of a type exists, an instance switcher appears at the top.
Routing: `/services/:type/:id` (specific instance), `/services/:type` (resolves first enabled instance, redirects).
### Service type registry
Eight types: `alertmanager`, `authentik`, `backups`, `grafana`, `jellyfin`, `nextcloud`, `prometheus`, `ssh_tasks`. `jellyseerr` was absorbed into Jellyfin config (optional `jellyseerr_url`/`jellyseerr_api_key` fields); existing Jellyseerr service instances were migrated at startup. `backups` and `authentik` are new.
### Users → Authentik
The Jellyfin-backed Users page is removed. Authentik is the user-directory source (OIDC auth unchanged). The Authentik service page has a Users tab (directory) and a Messaging tab (compose via the existing SMTP/mail queue).
### Observability split
The cross-service Observability page is removed. Alertmanager/Grafana/Prometheus each have their own service-type tabs. Users who want a cross-service overview build it via widgets on a named dashboard.
### Legacy routes
`/media`, `/files`, `/actions`, `/users`, `/observability`, `/backups` return 404 (no redirects). Bookmarks must be updated.
### Empty state
A fresh install lands on the Main Dashboard with an "Add a service" CTA until services are configured.