# Phase 3: Tablos CRUD - Context

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

<domain>
## Phase Boundary

A logged-in user can list, create, view, edit, and delete their own tablos end-to-end through HTMX-driven flows. The dashboard shows the user's tablos newest-first with a "Create your first tablo" empty state. All mutations (create, edit, delete) work without full page reloads; forms degrade gracefully when HTMX is unavailable.

Delivers TABLO-01..06. **Not** in scope: kanban tasks (Phase 4), file attachments (Phase 5), tablo sharing/permissions beyond owner-only, tablo reordering by user, rich text in description, slug-based URLs, color palette picker UI (color stored but picker UI is Claude's discretion).

</domain>

<decisions>
## Implementation Decisions

### Database Schema — tablos
- **D-01:** Hard-delete only — no `deleted_at` column. Matches the D-02 pattern from Phase 2 (users). Simpler queries — no `WHERE deleted_at IS NULL` filters needed throughout. Deletion is irreversible via the UI (confirmation required per D-04).
- **D-02:** `tablos` table columns: `id uuid PK DEFAULT gen_random_uuid()`, `user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE`, `title text NOT NULL`, `description text` (nullable), `color text` (nullable — hex string or Tailwind color name, e.g. `"#6366f1"` or `"indigo"`; validation at planner's discretion), `created_at timestamptz NOT NULL DEFAULT now()`, `updated_at timestamptz NOT NULL DEFAULT now()`. Index on `user_id` (for per-user list queries).
- **D-03:** Sort order is always `ORDER BY created_at DESC` (newest-first). No `position` column — user reordering is out of scope for Phase 3.

### URL Structure
- **D-04:** Tablo detail page URL: `/tablos/{uuid}` — use the `id` UUID primary key directly. No slug column, no slug generation logic. Opaque but simple. Non-owner (or unauthenticated) requests to `/tablos/{uuid}` return 404 (not 403 — no information leakage per TABLO-03).

### Create UX
- **D-05:** "New tablo" button on the dashboard expands an **inline form** above the tablo list via HTMX swap (`hx-swap="afterbegin"` into the list container, or a dedicated `#create-form` slot). On successful POST, the form collapses and the new tablo card is prepended to the list without a full page reload. On validation error, the inline form re-renders with field errors (same HTMX fragment pattern as Phase 2 signup).

### Edit UX
- **D-06:** Editing happens **inline on the tablo detail page**. Clicking the title or description swaps that element to an editable `<input>`/`<textarea>` via HTMX (`hx-get` to fetch an edit fragment). On save (`POST /tablos/{id}/edit` or `PATCH`), the input swaps back to the display element with the updated value. On cancel, restores original without a server round-trip (HTMX `hx-on:htmx:abort` or a cancel button that swaps back the original display fragment).

### Delete Confirmation
- **D-07:** Delete uses an **inline "Are you sure?" confirmation fragment** — no modal, no browser `confirm()`. The delete button (`DELETE /tablos/{id}`) swaps itself to a small confirmation row ("Delete tablo? **Yes** / Cancel") via HTMX. Confirming fires the actual DELETE; cancelling swaps back the original delete button. This keeps the pattern in Go/templ/HTMX with no JS and no new components.

### Claude's Discretion
- Exact Tailwind styling for tablo cards on the dashboard list — consistent with the Phase 1/2 design system (Card component, muted slate palette) but exact layout is Claude's call.
- Whether `color` is rendered as a dot/badge on the card or a left border accent — visual treatment is open.
- HTTP verb for edit: `POST /tablos/{id}/edit` (HTML form compatible) vs a RESTful `PATCH` routed through a `_method` override. Planner should pick whichever is cleaner with chi + HTML forms.
- The `updated_at` trigger: either a Postgres trigger or an explicit `SET updated_at = now()` in the UPDATE query — planner's choice.

</decisions>

<canonical_refs>
## Canonical References

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

### Prior Phase Context (locked decisions that constrain this phase)
- `.planning/phases/02-authentication/02-CONTEXT.md` — D-23/D-24 (chi route groups, middleware order), D-22 (logout POST form pattern), RequireAuth + RedirectIfAuthed middleware usage
- `.planning/phases/01-foundation/01-CONTEXT.md` — chi router + templ + sqlc + goose migration conventions established in Phase 1

### Requirements
- `.planning/REQUIREMENTS.md` §TABLO-01..06 — The 6 tablo requirements this phase delivers
- `.planning/PROJECT.md` — Core value statement and constraints (hard-delete default, HTMX-first, single binary)
- `.planning/ROADMAP.md` §Phase 3 — Success criteria and user-in-loop note

### Codebase Patterns (Go backend)
- `backend/internal/web/router.go` — Router structure, protected group pattern, AuthDeps injection
- `backend/internal/web/handlers_auth.go` — HTMX-aware handler pattern (HX-Request header detection, fragment vs full-page response)
- `backend/internal/web/ui/` — Existing Card, Button, Badge, CSRFField components
- `backend/templates/layout.templ` — Base layout, slot injection pattern
- `backend/internal/db/queries/users.sql` — sqlc query style reference
- `backend/migrations/0002_auth.sql` — Migration style reference (citext, uuid, indexes)

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `ui.Card`, `ui.Button`, `ui.Badge`, `ui.CSRFField` — all available in `backend/internal/web/ui/`. Tablo cards on the dashboard should use `ui.Card`.
- `auth.RequireAuth` middleware — wraps the entire tablos route group; no new auth code needed.
- `auth.Authed(ctx)` — extracts `*auth.User` from context for ownership checks.
- `templates.Layout` — base layout with logout header; tablo pages extend it.
- HTMX fragment pattern from signup (`HX-Request` header detection, 200+fragment vs 303+redirect) — reuse verbatim for create/edit error responses.

### Established Patterns
- sqlc queries in `backend/internal/db/queries/<domain>.sql`, generated output in `backend/internal/db/sqlc/`. Phase 3 adds `tablos.sql`.
- Handler functions return `http.HandlerFunc` from a constructor taking deps (e.g. `TablosDeps` struct) — mirrors `AuthDeps` pattern.
- Middleware order is locked (D-24 from Phase 2): `RequestID → RealIP → SlogLogger → Recoverer → ResolveSession → csrf.Protect → [route groups]`. Tablo routes go inside the `RequireAuth` group.
- goose migrations numbered sequentially: `0003_tablos.sql` is next.
- `templ generate` must be run after any `.templ` file change to regenerate `*_templ.go`.

### Integration Points
- `backend/internal/web/router.go` — add `/tablos*` routes inside the protected chi group.
- `backend/cmd/web/main.go` — pass `TablosDeps` (db pool) to `NewRouter` alongside existing `AuthDeps`.
- `backend/templates/index.templ` — current placeholder "Go + HTMX foundation" page becomes the tablo dashboard.

</code_context>

<specifics>
## Specific Ideas

- The `index.templ` root page (`GET /`) transforms into the tablo dashboard — replace the current HTMX demo card with the tablo list + create form.
- TABLO-06 explicitly requires HTMX-driven mutations ("no full page reloads for CRUD actions") — every mutating handler must handle both HX-Request and non-HX flows.

</specifics>

<deferred>
## Deferred Ideas

- **Tablo reordering by user** — drag-and-drop or button reorder. Not in TABLO requirements; would need a `position` column. Deferred to a future phase or v2.
- **Color palette picker UI** — The `color` column is stored in Phase 3, but a full color picker component is deferred; plain text input or a hardcoded set of swatches is fine in Phase 3.
- **Slug-based URLs** (`/tablos/my-project`) — discussed and deferred; UUID URLs are sufficient for v1.
- **Sharing / permissions beyond owner-only** — scoped out of v1 per PROJECT.md.

</deferred>

---

*Phase: 3-Tablos CRUD*
*Context gathered: 2026-05-14*
