- 03-02-SUMMARY.md: TablosDeps, handler contracts, template contracts, 4/10 tests green, 6 RED for Plan 03, known stubs documented - STATE.md: 2 new decisions, plan 02 metrics row added, notes updated - ROADMAP.md: phase 3 progress updated (2/3 summaries)
7.5 KiB
phase: 03-tablos-crud plan: 02 subsystem: web-handlers + templates tags: [go, htmx, templ, chi, csrf, tablo-crud]
Dependency graph
requires:
- phase: 03-tablos-crud plan: 01 provides: tablos table migration, sqlc queries, TablosDeps stub, RED test scaffold, button CSS variants provides:
- TablosDashboard template (full page): heading, New-tablo button, create-form slot, card list
- TablosEmptyState template: "No tablos yet" + CTA with exact UI-SPEC copy
- TabloCard template: title, optional description/color dot, View link, .tablo-delete-zone wrapper
- TabloCreateFormFragment template: inline HTMX form with CSRF, field errors, Cancel link
- TabloCardWithOOBFormClear template: card + top-level OOB div clearing #create-form-slot
- TabloCreateForm + TabloCreateErrors form types (tablos_forms.go)
- TablosListHandler — GET / lists user tablos newest-first
- TablosNewHandler — GET /tablos/new returns create form fragment
- TablosCreateHandler — POST /tablos validates, inserts, dual-target HTMX swap or 303 redirect
- router.go: GET / → TablosListHandler, GET /tablos/new, POST /tablos registered
- layout.templ footer updated: "Phase 3 · Tablos"
- TestTabloList, TestTabloList_Empty, TestTabloCreate, TestTabloCreate_Validation: GREEN (4/10) affects: [03-03]
Tech tracking
tech-stack: added: [] patterns: - Dual-target HTMX swap: HX-Retarget + hx-swap-oob sibling in single response (Pattern 4) - OOB div as top-level sibling in templ component (Pitfall 5 handled) - r.PostFormValue only — gorilla/csrf body consumption guard (Pitfall 2) - pgtype.Text{String: s, Valid: s != ""} for nullable insert params - renderTabloCreateError helper mirrors renderSignupError pattern
key-files: created: - backend/templates/tablos.templ - backend/templates/tablos_forms.go modified: - backend/internal/web/handlers_tablos.go - backend/internal/web/handlers.go - backend/internal/web/router.go - backend/templates/layout.templ - backend/templates/index.templ
key-decisions:
- "index_templ.go deleted manually — templ generates broken import when .templ has no components"
- "IndexHandler removed from handlers.go; auth/csrf imports removed (now unused)"
- "index.templ reduced to bare package declaration rather than deleted — keeps file discoverable"
- "Non-HTMX validation error re-fetches tablos and renders full dashboard (no form state threading)"
patterns-established:
- "Pattern: TabloCardWithOOBFormClear emits OOB div as top-level sibling (Pitfall 5)"
- "Pattern: dual-target HTMX create swap via HX-Retarget + HX-Reswap headers"
- "Pattern: nullable pgtype.Text insert via Valid: s != '' guard"
requirements-completed:
- TABLO-01
- TABLO-02
- TABLO-06
Metrics
duration: ~4min completed: 2026-05-14
Phase 03 Plan 02: Tablos Dashboard + Create Slice Summary
tablos.templ dashboard/card/form components + TablosListHandler/NewHandler/CreateHandler wiring 4/10 integration tests green; HTMX dual-target create and non-HTMX 303 fallback both verified
Performance
- Duration: ~4 min
- Started: 2026-05-14T22:16:47Z
- Completed: 2026-05-14T22:20:30Z (pre-checkpoint — Tasks 1+2 only)
- Tasks: 2 of 3 (Task 3 is human-verify checkpoint)
- Files modified: 7
Accomplishments
tablos.templcreated with 5 components: TablosDashboard, TablosEmptyState, TabloCard, TabloCreateFormFragment, TabloCardWithOOBFormCleartablos_forms.gowith TabloCreateForm + TabloCreateErrors types (mirrors auth_forms.go)layout.templfooter updated from "Phase 2 · Authentication" to "Phase 3 · Tablos"handlers_tablos.gofilled from stub to full implementation (List/New/Create handlers)router.goprotected group updated: GET / → TablosListHandler, + GET /tablos/new, POST /tabloshandlers.goIndexHandler removed;index.templemptied;index_templ.godeleted- TestTabloList, TestTabloList_Empty, TestTabloCreate (HTMX + non-HTMX), TestTabloCreate_Validation all PASS
- Phase 1/2 tests (TestSignup/TestLogin/TestLogout/TestCSRF) still pass — no regression
Task Commits
- Task 1: tablos templates + layout footer -
43ddf25(feat) - Task 2: tablo handlers + router wiring -
5db9215(feat)
Tests: 4 of 10 Green, 6 Remain RED for Plan 03
| Test | Status |
|---|---|
| TestTabloList | GREEN |
| TestTabloList_Empty | GREEN |
| TestTabloCreate/HTMX_create | GREEN |
| TestTabloCreate/non-HTMX_create | GREEN |
| TestTabloCreate_Validation | GREEN |
| TestTabloDetail_Owner | RED (Plan 03) |
| TestTabloDetail_NonOwner | RED (Plan 03) |
| TestTabloDetail_InvalidID | RED (Plan 03) |
| TestTabloUpdate | RED (Plan 03) |
| TestTabloDeleteConfirm | RED (Plan 03) |
| TestTabloDelete/HTMX_delete | RED (Plan 03) |
| TestTabloDelete/non-HTMX_delete | RED (Plan 03) |
Handler Contracts Established
TablosDeps (unchanged from Plan 01):
type TablosDeps struct {
Queries *sqlc.Queries
}
Handler signatures:
TablosListHandler(deps TablosDeps) http.HandlerFunc— GET /TablosNewHandler(deps TablosDeps) http.HandlerFunc— GET /tablos/newTablosCreateHandler(deps TablosDeps) http.HandlerFunc— POST /tablos
NewRouter signature (unchanged from Plan 01):
func NewRouter(pinger Pinger, staticDir string, deps AuthDeps, tabloDeps TablosDeps, csrfKey []byte, env string, trustedOrigins ...string) http.Handler
Template Contracts for Plan 03
TabloCardwraps Delete button in<div class="tablo-delete-zone">— Plan 03 wires /delete-confirm to swap outerHTMLTabloCardrenders "View" link to/tablos/{id}— Plan 03 implements that route- All 5 template components in
tablos.templare callable by Plan 03
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Deleted stale index_templ.go after emptying index.templ
- Found during: Task 2 (after reducing index.templ to bare package declaration)
- Issue:
templ generateregenerated index_templ.go withimport "github.com/a-h/templ"even though the file has no templ components, causinggo buildto fail with "imported and not used". - Fix: Deleted
backend/templates/index_templ.gomanually afterjust generate; build passes. - Files modified: backend/templates/index_templ.go (deleted)
- Committed in:
5db9215(Task 2)
Known Stubs
TabloCardDelete button fireshx-get="/tablos/{id}/delete-confirm"— the/delete-confirmroute does not exist yet (Plan 03 implements it). The button is visible on the dashboard but clicking it returns a 404 until Plan 03.TabloCard"View" link points to/tablos/{id}— route not yet registered (Plan 03). Navigating returns chi's default 404 until Plan 03.
These stubs are intentional per plan design — Plan 02 establishes the zone and link shapes that Plan 03 will wire.
Checkpoint Status
Task 3 (human-verify) reached — execution paused awaiting manual browser verification of:
- Dashboard "Your Tablos" heading + tablo cards or empty state
- "New tablo" button HTMX fetch of inline form
- HTMX create: form clears, card prepends, no full reload
- Validation: empty title shows "Title is required." inline
- Non-JS POST → 303 redirect to /, tablo in list
- CSRF token present in form
_csrfhidden field
Next Phase Readiness
- Plan 03 can implement TabloDetail, TabloUpdate, TabloDeleteConfirm, TabloDelete, and TabloDeleteCancel handlers and routes.
- TablosDeps available, NewRouter signature stable.
.tablo-delete-zoneclass on TabloCard wired for Plan 03's delete-confirm OOB swap.
Phase: 03-tablos-crud Completed (partial — checkpoint): 2026-05-14