xtablo-source/.planning/PROJECT.md
2026-05-14 20:12:25 +02:00

5.8 KiB

Xtablo — Go + HTMX Rewrite

What This Is

A full rewrite of the Xtablo product from a JS/Turbo monorepo (apps/main, apps/external, apps/api, …) into a single Go server with HTMX-driven UI. v1 focuses on the authenticated Tablos workflow only; other surfaces (booking, client portal, admin, chat, billing) come in later milestones. Built for a developer who wants a simpler, more durable stack and is using this rewrite as a deliberate pivot.

Core Value

A user can sign in and run the Tablos workflow — create tablos, manage their tasks (kanban), and attach files — without a JS framework.

If everything else fails, this must work end-to-end on a single Go binary backed by Postgres and an S3-compatible bucket.

Requirements

Validated

(None yet — ship to validate)

Active

  • Built-in email/password auth with server-managed sessions (no third-party auth)
  • Tablo CRUD (list, create, view, edit, delete) scoped to the owning user
  • Kanban tasks attached to a tablo (columns, ordering, CRUD)
  • File attachments on a tablo via S3-compatible storage (R2)
  • Background worker for async jobs (e.g. signed URL refresh, future emails)
  • Deployable as a single container to a single VPS/Cloud Run-style host

Out of Scope

  • Chat / messaging — Stream Chat + Durable Object worker dropped; not load-bearing for v1
  • Stripe / billing — defer monetization until product loop is validated
  • Public booking widgetapps/external rewrite not in v1 (may return in a later milestone)
  • Client portalapps/clients magic-link experience deferred
  • Admin appapps/admin internal tooling deferred
  • Notes / Etapes / Events sub-features inside a Tablo — only Tasks + Files in v1
  • Third-party auth providers — explicitly built-in only; no Clerk/Auth0/Lucia
  • Mobile / Expo app — out of scope for this rewrite
  • Supabase as a runtime dependency — Postgres only; Supabase Auth / RLS replaced by Go-side authz
  • The existing go-backend/ directory — treated as scratch; new code lives in a fresh backend/ Go package

Context

  • The JS monorepo (this repository) is the source of truth for product behavior and is fully mapped in .planning/codebase/ (ARCHITECTURE, STACK, STRUCTURE, INTEGRATIONS, CONVENTIONS, CONCERNS, TESTING). Use these to derive expected behavior — but the rewrite is free to simplify both schema and visuals.
  • The DB schema will change during the rewrite — the JS version's Supabase schema is a reference, not a constraint. The user wants to be in the loop on schema decisions for each domain (users/sessions, tablos, tasks, files).
  • Visuals will also change — no requirement to mirror the existing UI; Tailwind + HTMX patterns drive the new look.
  • go-backend/ already contains real scaffolding (router, sqlc, air, tailwind input). It is not the foundation — a fresh backend/ package will be created.
  • Developer is comfortable in Go and wants a low-dependency, server-rendered stack going forward.

Constraints

  • Tech stack: Go (server + templates) + HTMX + Tailwind + Postgres + sqlc — no third-party auth, no JS framework, no managed BaaS
  • Auth: Server-managed sessions only (signed/HTTP-only cookies), no JWTs from external providers
  • Storage: Files in S3-compatible object storage (Cloudflare R2 to start)
  • Architecture: One web server binary + one background worker (same repo, possibly same binary with subcommand)
  • Deploy target: Single VPS / container — no Kubernetes
  • Scope discipline: v1 ships the Tablo workflow only; resist scope creep from JS feature inventory

Key Decisions

Decision Rationale Outcome
Rewrite in Go + HTMX (no SPA) Simpler stack, developer preference, product pivot — Pending
Built-in sessions, no 3rd-party auth Avoid vendor coupling; sessions are well-trodden ground — Pending
Drop Supabase (keep Postgres) Owning the auth + RLS story in Go is simpler than maintaining the boundary — Pending
Fresh backend/ Go package, set go-backend/ aside Existing scaffold has decisions to revisit; cleaner to start over — Pending
v1 = Tablos workflow only (Tasks + Files), defer chat/billing/booking/portal/admin Focus the rewrite around the load-bearing user loop first — Pending
Single binary + background worker, single VPS deploy Matches the "simpler stack" thesis; avoid orchestration cost early — Pending
User-in-the-loop on Postgres schema for each domain Schema is changing from JS version; explicit review before sqlc generation — Pending

Evolution

This document evolves at phase transitions and milestone boundaries.

After each phase transition (via /gsd-transition):

  1. Requirements invalidated? → Move to Out of Scope with reason
  2. Requirements validated? → Move to Validated with phase reference
  3. New requirements emerged? → Add to Active
  4. Decisions to log? → Add to Key Decisions
  5. "What This Is" still accurate? → Update if drifted

After each milestone (via /gsd-complete-milestone):

  1. Full review of all sections
  2. Core Value check — still the right priority?
  3. Audit Out of Scope — reasons still valid?
  4. Update Context with current state

Phase History

  • Phase 1: Foundation — Completed 2026-05-14. Fresh backend/ Go package boots a web server, renders an HTMX-driven base layout, connects to local Postgres with goose migrations. FOUND-01..FOUND-05 satisfied; user-approved manual walkthrough. Two inline justfile/tailwind fixes during UAT (commit fix(01): guard sqlc on empty queries and correct tailwind paths).

Last updated: 2026-05-14 after Phase 1 completion