# Phase 15: Dashboard & Tablos - Context

**Gathered:** 2026-05-16
**Status:** Ready for planning

<domain>
## Phase Boundary

Replace the current top-nav shell + simple card list with a sidebar-based app layout (`AppLayout`) and project-card grid that matches the go-backend visual design. Phase 15 delivers:
- New `AppLayout` templ with sidebar (brand, nav items, tablo list section, user footer)
- Tablo dashboard restyled as a 3-column project-card grid
- Tablo empty state uses the `ui.EmptyState` component
- All existing tablo CRUD handler tests pass unchanged

Does NOT include: tablo detail restyling (Phase 16), chat/planning restyling (Phase 17), sidebar collapse JS interaction, mobile-responsive sidebar breakpoints.

</domain>

<decisions>
## Implementation Decisions

### App Layout Shell
- **D-L01:** Create a new `AppLayout(title string, user *auth.User, csrfToken string, activePath string, tablos []sqlc.Tablo)` templ in `backend/templates/`. All authenticated dashboard pages use `AppLayout`. The old `Layout` templ is preserved but no longer used by dashboard pages (it becomes dead code, can be removed in a future cleanup).
- **D-L02:** `AppLayout` uses the `.dashboard-shell` CSS grid (sidebar + main columns) from `go-backend/internal/web/ui/app.css`. Port `.dashboard-shell`, `.dashboard-sidebar`, `.sidebar-nav-shell`, all `.sidebar-*` CSS, `.sidebar-organization`, and `.dashboard-main` into `backend/internal/web/ui/app.css` (a new CSS file, not auth.css).
- **D-L03:** Active nav item: `AppLayout` receives `activePath string`. A helper function (pure Go, not templ) returns `"is-active"` class when a nav item's href matches `activePath`. Handlers pass the current route path explicitly (e.g., `"/"`, `"/planning"`, `"/tablos"`).
- **D-L04:** Scripts: `AppLayout` loads `htmx.min.js`, `sortable.min.js`, and `discussion-sse.js` — same as the current `Layout`. No change to script loading.

### Sidebar Nav Items
- **D-N01:** Match go-backend nav item set: Dashboard (`/`), Tablos (`/` or tablo overview — same as Dashboard for now), Tasks, Planning (`/planning`), Chat, Files, Settings. Use go-backend's `dashboard_components.templ` icon SVGs verbatim.
- **D-N02:** Routes that exist in the backend get real `href` values: Dashboard (`/`), Planning (`/planning`). Routes not yet built as standalone pages (Tasks, Files, Settings) render as visual nav items with no `href` attribute (display only, `cursor: default` on the item).
- **D-N03:** Chat is per-tablo (linked from tablo detail, not a top-level nav destination). In the sidebar nav, Chat links to `/` (dashboard) as a placeholder, or is rendered as a visual-only item like Tasks — Claude's discretion.
- **D-N04:** Sidebar-projects section: shows the user's tablos as a list with a colored circle icon (derived from tablo color field) + truncated title. Each item links to `/tablos/{id}`. Section label: "Projects" (English, matching backend convention).

### Tablo Project Cards
- **D-C01:** Tablo dashboard uses the `.project-grid` 3-column CSS grid layout from go-backend. Port `.project-grid`, `.project-card`, `.project-card-top`, and related CSS into the new `app.css`.
- **D-C02:** Each project card shows (matching go-backend exactly): colored circle avatar (top-left) + title + edit icon button (top-right) + delete icon button (top-right) + creation date (bottom row).
- **D-C03:** Color avatar: use `tablo.Color` field when set. When null/empty, show a default neutral/gray circle (no derived color, no initials). The circle renders via a small `<span>` styled with background-color, matching go-backend's `.sidebar-project-icon` pattern.
- **D-C04:** Edit and delete action icons use `@ui.IconButton(...)` from the design system (Phase 13 component). The HTMX attributes for edit (`hx-get=/tablos/{id}/edit`) and delete (`hx-delete=/tablos/{id}`) are preserved from the current `TabloCard` implementation.
- **D-C05:** The "New tablo" button and inline create form slot (`#create-form-slot`) move to a section header above the grid, matching go-backend's `.overview-section-heading` pattern.

### Tablo Empty State
- **D-E01:** When no tablos exist, use `@ui.EmptyState(ui.EmptyStateProps{...})` — the Phase 13 component. Replace the current raw HTML empty state in `TablosEmptyState()`. Title: "No tablos yet". Description: "Create your first tablo to get started." Action: "New tablo" button.

### Sidebar Footer (User/Account)
- **D-F01:** Include a sidebar footer matching go-backend's `.sidebar-organization` section. Shows: avatar circle (first letter of email, colored background) + user email + a small account link. Logout is moved from the old top-nav into this footer area.
- **D-F02:** The account/settings page doesn't exist yet, so the footer button/link only shows the email + logout button. No settings navigation for Phase 15. The `.organization-button` wraps a simple display element, not a dropdown.
- **D-F03:** Port `.sidebar-organization`, `.organization-button`, `.organization-avatar`, `.organization-name`, `.organization-meta` CSS from go-backend into `app.css`.

### Claude's Discretion
- Exact set of SVG icons for each nav item (copy from go-backend `dashboard_components.templ` — no new icon design needed)
- Whether the sidebar-projects section is a separate templ component or inline in `AppLayout` (prefer separate `SidebarProjectsSection` for testability)
- Exact color for the neutral avatar fallback (use `--color-surface-muted` or similar design token)
- Whether sidebar-footer avatar background color is derived from email hash or a fixed brand color

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### Product Scope
- `.planning/ROADMAP.md` — Phase 15 goal, success criteria (5 criteria), requirements DASH-01/02/03
- `.planning/REQUIREMENTS.md` — DASH-01 (sidebar design), DASH-02 (project-card layout), DASH-03 (empty state)
- `.planning/PROJECT.md` — v3.0 scope: visual polish only, go-backend is the visual reference

### Reference Implementation (source of truth)
- `go-backend/internal/web/views/dashboard_components.templ` — `DashboardPage`, `DashboardSidebar`, `SidebarProjectsSection`, `SidebarNavItem`, `SidebarOrganization` — port structure from here
- `go-backend/internal/web/ui/app.css` — ALL dashboard/sidebar CSS: `.dashboard-shell`, `.dashboard-sidebar`, `.sidebar-nav-shell`, all `.sidebar-*` classes, `.sidebar-organization`, `.dashboard-main`, `.project-grid`, `.project-card`, `.project-card-top` — extract these sections only
- `go-backend/static/logo_dark.png` — brand logo already copied to `backend/static/` in Phase 14

### Current Backend (files being changed)
- `backend/templates/layout.templ` — current top-nav Layout; being superseded by AppLayout for dashboard pages
- `backend/templates/tablos.templ` — TablosDashboard, TabloCard, TablosEmptyState — all being restyled
- `backend/internal/web/handlers_tablos.go` (or equivalent) — handlers need to pass tablos list + activePath to AppLayout

### Design System (Phase 13 — already in backend)
- `backend/internal/web/ui/empty-state.css` + `backend/internal/web/ui/*.templ` — `ui.EmptyState`, `ui.IconButton`, `ui.Button` components already available
- `backend/internal/web/ui/base.css` — design tokens; all new CSS in `app.css` must use `var(--...)` tokens

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `ui.EmptyState` (Phase 13): Ready to use for `TablosEmptyState` — replace raw HTML with `@ui.EmptyState(ui.EmptyStateProps{Title, Description, Icon, Action})`
- `ui.IconButton` (Phase 13): Use for edit + delete icon buttons on project cards — replaces any raw icon buttons
- `ui.Button` (Phase 13): "New tablo" button stays as `@ui.Button(...)` with same HTMX attrs
- `backend/static/logo_dark.png`: Already exists (Phase 14) — use for sidebar brand logo

### Established Patterns
- `AuthLayout` pattern (Phase 14): New `AppLayout` should follow the same package + templ structure — `package templates`, explicit param list, children via `{ children... }`
- `sqlc.Tablo` type: Has `Color pgtype.Text` (nullable), `Title string`, `ID pgx.UUID`, `CreatedAt pgtype.Timestamptz` — all needed for sidebar-projects and project cards
- Handler pattern: Handlers currently call `Layout(title, user, csrfToken)` — will change to `AppLayout(title, user, csrfToken, activePath, tablos)` requiring handlers to fetch tablos list

### Integration Points
- `backend/internal/web/handlers_tablos.go`: TablosDashboardHandler fetches tablos for display; needs to also pass tablos to AppLayout for the sidebar-projects section (already has them)
- Other handlers (PlanningHandler, ChatHandler, etc.): Will need to fetch the user's tablos list to populate the sidebar — this is a cross-handler concern worth factoring into a shared helper

</code_context>

<specifics>
## Specific Ideas

- Sidebar visual: match go-backend's `DashboardSidebar` structure verbatim — brand logo (logo_dark.png, 4rem×4rem rounded), "XTablo" title, nav list, projects section, footer
- Project card: match go-backend `.project-card` + `.project-card-top` layout — white card, 1rem border-radius, 1rem padding, edit/delete icon buttons in top-right corner
- Sidebar footer: full `.sidebar-organization` treatment — avatar circle with first letter + email + logout button inside `.organization-button`

</specifics>

<deferred>
## Deferred Ideas

- Sidebar collapse toggle (JS interaction) — requires client-side JS to persist collapsed state; deferred to a future polish phase
- Mobile-responsive sidebar (hamburger menu, slide-in drawer) — deferred; Phase 15 desktop-first only
- Tablo color picker in the create/edit form — the color field exists in the DB but no UI to set it; deferred to a future enhancement
- Tasks, Files, Settings as standalone pages — nav items shown as visual-only until those pages are built

</deferred>

---

*Phase: 15-dashboard-tablos*
*Context gathered: 2026-05-16*
