Files
manage/openspec/changes/configurable-dashboard-widgets/apply-progress.md
T
Developer 200d319fb0 feat(widgets): add backend CRUD, registry, and default seeding
Introduce a closed, compile-time widget registry and backend CRUD for
dashboard widget instances.

- Add dashboard_widgets SQLite table in SettingsStore with CRUD helpers and
  default seeding (Jellyfin + Backups) on first install.
- Add Pydantic models with credential-key and secret-value rejection.
- Add widgets router: /api/widgets/sources, /types, /instances CRUD.
- Call ensure_defaults() in app lifespan so fresh installs seed defaults.
- Add backend tests covering registry, CRUD, validation, and seeding.
- Include SDD artifacts: exploration, proposal, spec, design, tasks.
2026-06-19 20:07:47 +00:00

3.1 KiB

Apply Progress: Configurable Dashboard Widgets

Change: configurable-dashboard-widgets
Apply run: PR 1 / Slice 1 — Backend CRUD and default seeding
Date: 2026-06-19

Completed tasks (Slice 1)

All Slice 1 tasks are marked - [x] in tasks.md:

  • 1.1 Create widget Pydantic models
  • 1.2 Create backend widget registry
  • 1.3 Implement widgets router (CRUD + metadata)
  • 1.4 Extend SettingsStore for dashboard_widgets
  • 1.5 Register widgets router in main.py
  • 1.6 Add backend tests for registry, CRUD, and seeding
  • 1.7 Verify backend slice

Files changed

New files

  • backend/src/media_library_viewer_api/models/widgets.py — Pydantic models: WidgetInstance, WidgetInstanceInput, WidgetTypeInfo, WidgetDataResponse, plus credential-key/secret-value validators.
  • backend/src/media_library_viewer_api/widgets/__init__.py — Package marker.
  • backend/src/media_library_viewer_api/widgets/registry.py — Closed WIDGET_REGISTRY for six Phase 1 widget types, source-type listing, type metadata, and lightweight config-schema validation.
  • backend/src/media_library_viewer_api/routers/widgets.py — REST endpoints for /api/widgets/sources, /types, /instances, and instance CRUD.
  • backend/tests/test_widgets.py — 12 tests covering registry, CRUD, validation, and seeding.

Modified files

  • backend/src/media_library_viewer_api/services/settings_store.py — Added dashboard_widgets table, index, CRUD helpers, default seeding, and refactored ensure_defaults() to seed widgets independently of machine seeding.
  • backend/src/media_library_viewer_api/main.py — Registered widgets_router.

Verification

Commands run:

cd backend
.venv/bin/python -m ruff check .              # All checks passed
PYTHONPATH=src .venv/bin/python -m pytest     # 185 passed, 2 warnings
cd ../frontend
npm run lint                                  # 2 pre-existing warnings, 0 errors
npm run build                                 # Built successfully

Focused widget test output: 12 passed.

Deviations from design

  • None significant for Slice 1. The implementation follows the design's backend CRUD layout.
  • Used HTTP_422_UNPROCESSABLE_CONTENT instead of the deprecated HTTP_422_UNPROCESSABLE_ENTITY.

Remaining work

  • Slice 2: Backend source adapters + GET /api/widgets/instances/{id}/data
  • Slice 3: Frontend types/API/hooks/registry/components
  • Slice 4: Dashboard loop + configuration UI + addon pages

PR boundary

This slice is PR 1 of 4 in the approved stacked-to-main chain. It is backend-only and leaves the frontend build/lint green.

Actual changed-line count: ~780 added lines across production code and tests (new files: ~597 lines; modified files: ~181 insertions). This is above the nominal ~400-line review budget, but Slice 1 is the smallest coherent backend unit: removing the CRUD router, store helpers, or tests would leave the slice non-functional or unverifiable. If the reviewer prefers a smaller blast radius, the store helpers (~90 lines) could be split into a preceding PR, though that PR would not be independently user-visible.