docs: promote multi-style boards to core architecture

All four styles are board renderers over one shared store, not color
themes. Renderer contract (Board/Section/Item/Widget) lands in Phase 1;
Cards ships in v0.1.0 to validate the seam early, Index and Console
follow in v0.3.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>
This commit is contained in:
Tomas Dvorak committed 2026-09-17 20:29:21 +02:00
1 parent 3edadb613d
commit e7f32949e9
2 files changed
+48 -25

No files matched your search

+21 -17
View File
@@ -9,20 +9,21 @@ Stack: **Go + Gin + SQLite** (single static binary, embeds frontend) · **React
## 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.
Multiple board styles are a core feature: same system, same functionality,
different UI structure per style. A **renderer** supplies the layout; board
state, drag-drop, popovers, and dialogs are shared primitives underneath.
Alternate view themes ship post-MVP on the same data model (Phase 3.5):
| Theme | Source mockup | Character |
| Renderer | Source mockup | Ships |
|---|---|---|
| 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 |
| Bento (default) | `d-bento-mono.html` | v0.1.0 — mixed-size grid, widgets inline |
| Cards | `a-vercel-mono.html` | v0.1.0 — uniform compact grid; validates the seam early |
| Index | `e-editorial.html` | v0.3.0 — serif headers, list rows, stat strip |
| Console | `f-console.html` | v0.3.0 — terminal panels, `[ up ]` tags |
Rule: themes change the renderer, never the data or the interactions.
Contract: `renderers/<name>/{BoardView, SectionView, ItemView, WidgetView}`.
Tokens (`--bg`, `--surface`, `--border`, …) shared; dark/light is orthogonal.
User picks renderer in settings; persisted. Renderers never reimplement dnd
or popover logic.
---
@@ -59,13 +60,15 @@ The product's spine: sections, services, drag-drop, multi-URL.
- [ ] Schema: `sections`, `items`, `urls`, `settings` (fractional `position REAL` ordering)
- [ ] REST API: CRUD for sections/items/urls, `reorder` endpoints, icon upload, `settings`, `export`/`import` JSON
- [ ] Board UI (Bento Mono): section headers (label, count, hairline, chevron), service tiles (icon, name, host, status chip)
- [ ] Renderer contract: shared board store + `BoardView`/`SectionView`/`ItemView`/`WidgetView` seam, dnd + popover as shared primitives
- [ ] **Bento** renderer (default): mixed-size grid, hairline section headers, tiles with status chips
- [ ] **Cards** renderer: uniform compact grid — second renderer proves the seam while code is small
- [ ] 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
- [ ] Dark/light toggle (persisted), renderer picker in settings, responsive to ~360px
- [ ] Status ping: server-side HEAD request per service URL, cached ~60s → `up`/`down` chip
**Exit:** create sections, add services with icons and dual URLs, drag everything, reload — state persists. `docker run` single image works. Export/import round-trips.
@@ -84,11 +87,12 @@ The product's spine: sections, services, drag-drop, multi-URL.
**Exit:** Pi-hole widget shows real data; adding a new integration = one Go file + one React component.
## Phase 3 — Themes & ergonomics → v0.3.0
## Phase 3 — Renderers & 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
- [ ] **Index** renderer: serif section headers, full-width rows, masthead stat strip
- [ ] **Console** renderer: bordered panels/tables, JetBrains Mono, `[ up ]` tags
- [ ] Renderer switcher polished (instant swap, per-renderer preview in settings)
- [ ] ⌘K command palette: jump to service, add service, toggle theme, switch renderer
- [ ] dashboard-icons auto-suggest in icon picker (name → icon URL)
- [ ] User services list → prioritized widget backlog (owner-supplied list pending)
+27 -8
View File
@@ -86,21 +86,40 @@ Frontend never hand-writes API types — generated client from `openapi.yaml`.
- `CommandPalette` (⌘K) — Phase 3
- dnd-kit `DndContext` at board level; sections and items both sortable
## 7. UI direction — DECIDED 2026-09-16
## 7. UI system — DECIDED 2026-09-16
**Primary: `d-bento-mono.html`** — bento grid on the monochrome zinc palette. Geist + Geist Mono, hairline borders, no glow, status chips carry the only color (green/amber semantic).
**The app ships multiple layouts, not one.** Same board state, same interactions (drag-drop, collapse, URL popover, add/edit), different structure per style. This is a core feature, not a theme afterthought.
**Alternate view themes** (same data model, different renderers — post-MVP theme system):
**Primary renderer: `d-bento-mono.html`** — bento grid on the monochrome zinc palette. Geist + Geist Mono, hairline borders, no glow, status chips carry the only color (green/amber semantic).
| Mockup | Theme | Character |
**Full renderer set:**
| Renderer | Source mockup | Structure |
|---|---|---|
| `a-vercel-mono.html` | Mono Cards | uniform card grid, quietest |
| `e-editorial.html` | Index | serif headers, full-width rows, stat strip |
| `f-console.html` | Console | JetBrains Mono, bordered panels, `[ up ]` tags |
| Bento (default) | `d-bento-mono.html` | mixed-size grid, widgets inline as large tiles |
| Cards | `a-vercel-mono.html` | uniform compact card grid, widgets as cards |
| Index | `e-editorial.html` | serif section headers, full-width rows, masthead stat strip |
| Console | `f-console.html` | bordered panels/tables, JetBrains Mono, `[ up ]` tags |
Rejected and deleted: bento-with-glow (B), casa glass (C).
Implementation note: design tokens (CSS vars → Tailwind theme) shared across all themes; layout renderer is the only per-theme component. Token structure must be decided in Phase 0 so alternates stay cheap.
### Renderer contract (architectural requirement)
```
renderers/
<name>/
BoardView (grid/list arrangement, section placement)
SectionView (header chrome: label, count, collapse, drag handle)
ItemView (tile/card/row anatomy: icon, name, host, status, popover anchor)
WidgetView (widget tile/panel/strip-cell anatomy)
```
- Board state (sections, items, order, collapse) lives in one store, renderer-agnostic.
- Interactions (dnd-kit, popover, dialogs) are provided by shared primitives the renderer composes — renderers never reimplement dnd or popover logic.
- Design tokens (`--bg`, `--surface`, `--border`, `--text`, …) are shared CSS vars; each renderer maps them to its own chrome. Dark/light stays orthogonal to renderer choice.
- Setting: `settings.renderer` — user picks layout in settings; persisted like theme.
Building the second renderer (Cards) inside Phase 1 is deliberate: it validates the seam while the code is still small.
## 8. Roadmap