147 lines
9.7 KiB
Markdown
147 lines
9.7 KiB
Markdown
# Feature Landscape
|
|
|
|
**Domain:** Container image update monitoring dashboard (self-hosted)
|
|
**Researched:** 2026-03-23
|
|
**Confidence note:** Web search and WebFetch tools unavailable in this session. Findings are based on training-data knowledge of Portainer, Watchtower, Dockcheck-web, Diun, Uptime Kuma, and the self-hosted container tooling ecosystem. Confidence levels reflect this constraint.
|
|
|
|
---
|
|
|
|
## Table Stakes
|
|
|
|
Features users expect from any container monitoring dashboard. Missing any of these and the tool feels unfinished or untrustworthy.
|
|
|
|
| Feature | Why Expected | Complexity | Notes |
|
|
|---------|--------------|------------|-------|
|
|
| Persistent update list (survives page reload, container restart) | Core value prop — the whole point is to not lose track of what needs updating | Low | Already exists but broken by SQLite bugs; fixing it is table stakes |
|
|
| Individual acknowledge/dismiss per image | Minimum viable workflow to mark "I dealt with this" | Low | Already exists |
|
|
| Bulk acknowledge — dismiss all | Without this, users with 20+ images must click 20+ times; abandonment is near-certain | Medium | Flagged in CONCERNS.md as missing; very high priority |
|
|
| Bulk acknowledge — dismiss by group/tag | If you've tagged a group and updated everything in it, dismissing one at a time is painful | Medium | Depends on tag feature existing (already does) |
|
|
| Search / filter by image name | Standard affordance in any list of 10+ items | Medium | Missing; flagged in PROJECT.md as active requirement |
|
|
| Filter by status (pending update vs acknowledged) | Separating signal from noise is core to the "nag until you fix it" value prop | Low | Missing; complements search |
|
|
| New-update indicator (badge, counter, or highlight) | Users need to know at a glance "something new arrived since I last checked" | Medium | Flagged in PROJECT.md as active requirement |
|
|
| Page/tab title update count | Gives browser-tab visibility without opening the page — "DiunDashboard (3)" in the tab | Low | Tiny implementation, high perceived value |
|
|
| Data integrity across restarts | If the DB loses data on restart, trust collapses | Medium | High-priority bug: INSERT OR REPLACE + missing FK pragma |
|
|
| PostgreSQL option for non-SQLite users | Self-hosters who run Postgres expect it as an option for persistent services | High | Flagged in PROJECT.md; dual-DB is the plan |
|
|
|
|
---
|
|
|
|
## Differentiators
|
|
|
|
Features not universally expected but meaningfully better than the baseline. Build these after table stakes are solid.
|
|
|
|
| Feature | Value Proposition | Complexity | Notes |
|
|
|---------|-------------------|------------|-------|
|
|
| Filter by tag/group | Users who've organized images into groups want to scope their view | Low | Tag infrastructure already exists; filter is a frontend-only change |
|
|
| Visual "new since last visit" highlight (session-based) | Distinguish newly arrived updates from ones you've already seen | Medium | Requires client-side tracking of "last seen" timestamp (localStorage) |
|
|
| Toast / in-page notification on new update arrival (during polling) | Passive, non-intrusive signal when updates arrive while the tab is open | Medium | Uses existing 5-second poll; could compare prior state |
|
|
| Browser notification API on new update | Reaches users when the tab is backgrounded | High | Requires permission prompt; risky UX if over-notified; defer |
|
|
| Sort order controls (newest first, image name, registry) | Power-user need once list grows beyond 20 images | Low | Pure frontend sort; no backend change needed |
|
|
| Filter by registry | Useful for multi-registry setups | Low | Derived from image name; no schema change needed |
|
|
| Keyboard shortcuts (bulk dismiss with keypress, focus search) | Power users strongly value keyboard-driven UIs | Medium | Rarely table stakes for self-hosted tools but appreciated |
|
|
| Light / dark theme toggle (currently hardcoded dark) | Respects system preferences; accessibility baseline | Low | Flagged in CONCERNS.md; CSS variable change + prefers-color-scheme |
|
|
| Drag handle always visible (not hover-only) | Accessibility: keyboard and touch users need discoverable reordering | Low | Flagged in CONCERNS.md |
|
|
| Alternative to drag-and-drop for tag assignment | Dropdown select for assigning tags; removes dependency on pointer hover | Medium | Fixes accessibility gap in CONCERNS.md |
|
|
| Data retention / auto-cleanup of old acknowledged entries | Prevents unbounded DB growth over months/years | Medium | Configurable TTL for acknowledged records |
|
|
|
|
---
|
|
|
|
## Anti-Features
|
|
|
|
Features to deliberately NOT build in this milestone.
|
|
|
|
| Anti-Feature | Why Avoid | What to Do Instead |
|
|
|--------------|-----------|-------------------|
|
|
| Auto-triggering image pulls or container restarts from the dashboard | This app is a viewer, not an orchestrator; acting on the host would require Docker socket access and creates a significant security surface | Remain read-only; users run `docker pull` / Coolify update themselves |
|
|
| Notification channel management UI (email, Slack, webhook routing) | DIUN already manages notification channels; duplicating this is wasted effort and creates config drift | Keep DIUN as the notification layer; this dashboard is the persistent record |
|
|
| OAuth / multi-user accounts | Single-user self-hosted tool; auth complexity is disproportionate to the use case | Document "don't expose to the public internet"; optional basic auth via reverse proxy is sufficient |
|
|
| Real-time WebSocket / SSE updates | The 5-second poll is adequate for this use case; SSE/WS adds complexity without meaningful UX gain for a low-frequency signal | Improve the poll with ETag/If-Modified-Since to reduce wasted bandwidth instead |
|
|
| Mobile-native / PWA features | Web-first responsive design is sufficient; self-hosters rarely need a fully offline-capable PWA for an internal tool | Ensure the layout is responsive for mobile browser access |
|
|
| Auto-grouping by Docker stack / Compose project | Requires Docker socket access or DIUN metadata changes; significant scope increase | Defer to a dedicated future milestone per PROJECT.md |
|
|
| DIUN config management UI | Requires DIUN bundling; out of scope for this milestone | Defer per PROJECT.md |
|
|
| Changelog or CVE lookups per image | Valuable but requires external API integrations (Docker Hub, Trivy, etc.); different product scope | Document as a possible future phase |
|
|
| Undo for dismiss actions | Adds state complexity; accidental dismisses are recoverable by the next DIUN scan | Keep dismiss as final; communicate this in the UI |
|
|
|
|
---
|
|
|
|
## Feature Dependencies
|
|
|
|
```
|
|
Data integrity fixes (SQLite upsert + FK pragma)
|
|
→ must precede all UX features (broken data undermines everything)
|
|
|
|
PostgreSQL support
|
|
→ depends on struct-based refactor (global state → Server struct)
|
|
→ struct refactor is also a prerequisite for safe parallel tests
|
|
|
|
Bulk acknowledge (all)
|
|
→ no dependencies; purely additive API + frontend work
|
|
|
|
Bulk acknowledge (by group)
|
|
→ depends on tag feature (already exists)
|
|
|
|
Search / filter by image name
|
|
→ no backend dependency; frontend filter on existing GET /api/updates payload
|
|
|
|
Filter by status
|
|
→ no backend dependency; frontend filter
|
|
|
|
Filter by tag
|
|
→ depends on tag data being returned by GET /api/updates (already is)
|
|
|
|
New-update indicator (badge/counter)
|
|
→ depends on frontend comparing poll results across cycles
|
|
→ no backend change needed
|
|
|
|
Page title update count
|
|
→ depends on update count being derivable from GET /api/updates (already is)
|
|
|
|
Toast notification on new arrival
|
|
→ depends on new-update indicator logic (same poll comparison)
|
|
→ can share implementation
|
|
|
|
Sort controls
|
|
→ no dependencies; pure frontend
|
|
|
|
Data retention / TTL
|
|
→ depends on PostgreSQL support OR can be added to SQLite path independently
|
|
→ no frontend dependency
|
|
|
|
Light/dark theme
|
|
→ no dependencies; CSS + localStorage
|
|
|
|
Drag handle accessibility fix
|
|
→ no dependencies
|
|
|
|
Alternative tag assignment (dropdown)
|
|
→ no dependencies
|
|
```
|
|
|
|
---
|
|
|
|
## MVP Recommendation for This Milestone
|
|
|
|
The milestone goal is: bug fixes, dual DB, and UX improvements (bulk actions, filtering, search, new-update indicators).
|
|
|
|
Prioritize in this order:
|
|
|
|
1. **Fix SQLite data integrity** (UPSERT + FK pragma) — trust foundation; nothing else matters if data is lost
|
|
2. **Bulk acknowledge (all + by group)** — the single highest-impact UX addition; drops manual effort from O(n) to O(1)
|
|
3. **Search + filter by name/status/tag** — table stakes for any list of >10 items
|
|
4. **New-update indicator + page title count** — completes the "persistent visibility" core value with in-page signal
|
|
5. **PostgreSQL support** — requires struct refactor; large but well-scoped; enables users who need it
|
|
6. **Light/dark theme + accessibility fixes** — low complexity; removes known complaints
|
|
|
|
Defer to next milestone:
|
|
- **Data retention / TTL**: Real but not urgent; unbounded growth is a future problem for most users
|
|
- **Toast notifications**: Nice to have but the badge + title count cover the signal adequately
|
|
- **Alternative tag assignment (dropdown)**: Accessibility improvement but drag-and-drop exists and works
|
|
- **Browser notification API**: High complexity, UX risk, very low reward vs. the badge approach
|
|
|
|
---
|
|
|
|
## Sources
|
|
|
|
- Project context: `.planning/PROJECT.md` (validated requirements and constraints)
|
|
- Codebase audit: `.planning/codebase/CONCERNS.md` (confirmed gaps: bulk ops, search, indicators, FK bugs)
|
|
- Training-data knowledge of: Portainer CE, Watchtower (no UI), Dockcheck-web, Diun native notifications, Uptime Kuma (comparable self-hosted monitoring dashboard UX patterns) — **MEDIUM confidence** (cannot be verified in this session due to tool restrictions; findings should be spot-checked against current Portainer docs and community forums before roadmap finalization)
|