Primary renderer is D (bento grid, mono palette). A/E/F kept as alternate view themes on shared tokens. B and C deleted. Roadmap now maps phases to releases v0.1.0 -> v1.0.0. Generated with [Devin](https://devin.ai) Authored By: TDvorak <[email protected]> Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
6.0 KiB
Dash — Roadmap
A self-hosted homelab dashboard. CasaOS-grade ease of use, Vercel-grade design. Single container, UI-managed, no YAML, no auth required.
Stack: Go + Gin + SQLite (single static binary, embeds frontend) · React 18 + Vite + TS strict + Tailwind + shadcn/ui + dnd-kit · OpenAPI-generated client.
Design system
Primary renderer: Bento Mono (mockups/d-bento-mono.html) — bento grid on a
monochrome zinc palette, Geist + Geist Mono, hairline borders, semantic status
color only.
Alternate view themes ship post-MVP on the same data model (Phase 3.5):
| Theme | Source mockup | Character |
|---|---|---|
| Bento Mono (default) | d-bento-mono.html |
mixed-size grid, widgets inline |
| Mono Cards | a-vercel-mono.html |
uniform card grid, quietest |
| Index | e-editorial.html |
serif headers, list rows, stat strip |
| Console | f-console.html |
terminal panels, [ up ] tags |
Rule: themes change the renderer, never the data or the interactions.
Releases
| Version | Contents | Gate |
|---|---|---|
v0.1.0 |
Phase 0 + 1 — working MVP, single image | manual smoke test |
v0.2.0 |
Phase 2 — widget layer + first integrations | Pi-hole widget live |
v0.3.0 |
Phase 3 — alternate themes, search, icon packs | theme switcher works |
v1.0.0 |
Phase 4 — OSS polish, docs, importers, CI releases | public repo launch |
v1.x |
Phase 5 — demand-driven extras only | per-feature |
Phase 0 — Foundation → part of v0.1.0
Repo hygiene and pipelines before features.
- Monorepo scaffold (
apps/frontend,apps/backend,packages/api-client,infra/,data/) - MIT
LICENSE,README.md,.gitignore,AGENTS.md openapi.yamlstub → generated TS client (packages/api-client)- Backend skeleton: Gin router,
zaplogging,/api/healthz, SQLite open + goose migrations runner - Frontend skeleton: Vite + TS strict + Tailwind + shadcn/ui, theme tokens matching
d-bento-mono.htmlCSS vars - CI (GitHub Actions):
go build ./...,go vet ./...,go test ./...,tsc --noEmit,oxlint+ vendored anti-slop rules,npm run build - Multi-stage
Dockerfile(frontend build → Go build →FROM scratch/distroless,embed.FSserves UI) docker-compose.yml— one service,./data:/datavolume
Exit: docker compose up serves a blank board. CI green on main.
Phase 1 — MVP → v0.1.0
The product's spine: sections, services, drag-drop, multi-URL.
- Schema:
sections,items,urls,settings(fractionalposition REALordering) - REST API: CRUD for sections/items/urls,
reorderendpoints, icon upload,settings,export/importJSON - Board UI (Bento Mono): section headers (label, count, hairline, chevron), service tiles (icon, name, host, status chip)
- dnd-kit: reorder items in a section, move items between sections, reorder sections; persist on drop
- Collapse/expand sections (persisted)
UrlPopover: 1 URL → direct open, 2+ → chooser (local/external/custom tags)AddServiceDialog/EditServiceDialog(name, URLs+labels, icon URL or file upload)- Icon handling: upload to
data/icons/, remote URL passthrough, letter-tile fallback - Dark/light toggle (persisted), responsive to ~360px
- Status ping: server-side HEAD request per service URL, cached ~60s →
up/downchip
Exit: create sections, add services with icons and dual URLs, drag everything, reload — state persists. docker run single image works. Export/import round-trips.
Phase 2 — Widgets → v0.2.0
- Go widget registry:
Widgetinterface (Type(),Fetch(cfg)),GET /api/widgets/:id/datawith ~30s in-process TTL cache GET /api/widgets/types→ registry metadata drives the add-widget dialogWidgetHostcomponent: mapsconfig.type→ React component, polls with backoff- Widgets as grid items (same
itemstable,kind = 'widget',config JSON) - Clock/timezone widget (frontend-only)
- Pi-hole fetcher (blocked %, queries today, per-day bar series)
- AdGuard Home fetcher (blocked %, clients)
- Immich fetcher (photo count, library size)
- Per-widget config UI (endpoint URL, API key — stored in
config, never logged)
Exit: Pi-hole widget shows real data; adding a new integration = one Go file + one React component.
Phase 3 — Themes & ergonomics → v0.3.0
- Theme token layer finalized; view-theme switcher in settings
- Alternate renderers: Mono Cards, Index, Console
- ⌘K command palette: jump to service, add service, toggle theme
- dashboard-icons auto-suggest in icon picker (name → icon URL)
- User services list → prioritized widget backlog (owner-supplied list pending)
Exit: all four renderers work off the same board state; palette navigates everything.
Phase 4 — Open-source launch → v1.0.0
- Docs: install, configuration, widget development guide (
docs/) - Importers: Homepage
services.yml, Homarr JSON, Dashyconf.yml→ sections/items/urls README.mdhero: screenshots (4 themes), demo GIF,docker runone-liner- goreleaser → binaries; GHCR image on tag; semver +
CHANGELOG.md CONTRIBUTING.md, issue/PR templates, code of conduct, security policy- i18n scaffolding (en default)
- Public repo flip + announcement assets
Exit: a stranger can docker run, import their Homepage config, and have a working board in under two minutes.
Phase 5 — Post-1.0 (demand-driven only)
Build only what users actually ask for. Candidates, unordered:
- Optional auth (local password + OIDC) — most-requested, likely first
- Health-check history + uptime graphs
- Custom CSS / accent color / wallpaper
- Iframe/embed widgets, API-status widgets (generic JSON path)
- PWA install, mobile layout polish
- Multiple boards
Non-goals (v1)
Auth, Postgres/external DB, multi-user, mobile app, container lifecycle management, YAML-as-source-of-truth. Revisit only with evidence of demand.