chore: merge executor worktree (worktree-agent-a98c01ef03e47adfc) [plan 01-01]
This commit is contained in:
commit
a639fdf502
22 changed files with 435 additions and 0 deletions
165
.planning/phases/01-foundation/01-01-SUMMARY.md
Normal file
165
.planning/phases/01-foundation/01-01-SUMMARY.md
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
---
|
||||
phase: 01-foundation
|
||||
plan: 01
|
||||
subsystem: backend-scaffold
|
||||
tags: [go, scaffold, tooling, postgres, tailwind, htmx]
|
||||
requires: []
|
||||
provides:
|
||||
- backend-go-module
|
||||
- backend-directory-skeleton
|
||||
- backend-compose-postgres
|
||||
- backend-goose-migration-pipeline
|
||||
- backend-sqlc-config
|
||||
- backend-tailwind-input-css
|
||||
- backend-air-live-reload
|
||||
- backend-justfile
|
||||
affects:
|
||||
- downstream-plan-01-02-handler-tests-and-ui
|
||||
- downstream-plan-01-03-walking-skeleton
|
||||
tech_stack:
|
||||
added:
|
||||
- go-1.26
|
||||
- chi-v5.2.5
|
||||
- templ-v0.3.1020
|
||||
- pgx-v5.9.2
|
||||
- goose-v3.27.1
|
||||
- uuid-v1.6.0
|
||||
- sqlc-v1.31.1 (CLI; bootstrap-installed)
|
||||
- air-v1.65.1 (CLI; bootstrap-installed)
|
||||
- tailwind-standalone-v4.0.0 (binary; bootstrap-downloaded)
|
||||
- htmx-v2 (bootstrap-downloaded, pinned major in justfile)
|
||||
patterns: []
|
||||
key_files:
|
||||
created:
|
||||
- backend/go.mod
|
||||
- backend/go.sum
|
||||
- backend/compose.yaml
|
||||
- backend/.env.example
|
||||
- backend/.gitignore
|
||||
- backend/.air.toml
|
||||
- backend/sqlc.yaml
|
||||
- backend/tailwind.input.css
|
||||
- backend/justfile
|
||||
- backend/migrations/0001_init.sql
|
||||
- backend/internal/db/doc.go
|
||||
- backend/internal/session/doc.go
|
||||
- backend/internal/tablos/doc.go
|
||||
- backend/internal/tasks/doc.go
|
||||
- backend/internal/files/doc.go
|
||||
modified: []
|
||||
decisions:
|
||||
- locked: D-01 two-binary cmd/web + cmd/worker layout reflected in directory plan (cmd/* itself lands in Plan 01-03)
|
||||
- locked: D-02 placeholder doc.go files created for db, session, tablos, tasks, files
|
||||
- locked: D-04 goose chosen, .sql with +goose Up/Down format
|
||||
- locked: D-12 standalone Tailwind binary, no Node toolchain
|
||||
- locked: D-13/D-14 air for Go live-reload; Tailwind watch runs separately (two-terminal workflow)
|
||||
- locked: D-15 .env.example documents DATABASE_URL/PORT/ENV
|
||||
- locked: D-16 pgx/v5 + pgxpool; sqlc emits pgx-compatible code
|
||||
metrics:
|
||||
duration_minutes: ~8
|
||||
completed: 2026-05-14
|
||||
tasks_completed: 5
|
||||
files_created: 18
|
||||
---
|
||||
|
||||
# Phase 01 Plan 01: Backend Scaffold Summary
|
||||
|
||||
Stood up the `backend/` Go module skeleton — directory layout, compose Postgres, justfile recipes, sqlc/air/tailwind configs, and a no-op goose bootstrap migration — with zero application code, exactly per the locked CONTEXT D-01..D-20 decisions and revised post-Codex-review plan.
|
||||
|
||||
## What Shipped
|
||||
|
||||
### Go module + pinned runtime deps (commit `aa90008`)
|
||||
- `backend/go.mod` declares `module backend` against Go 1.26.1.
|
||||
- Five runtime deps pinned via `go get` at the exact RESEARCH-Standard-Stack versions: `chi v5.2.5`, `templ v0.3.1020`, `pgx/v5 v5.9.2`, `goose/v3 v3.27.1`, `uuid v1.6.0`.
|
||||
- `go mod tidy` deliberately NOT executed (Codex concern #1) — tidy would strip the require lines while no source file imports them yet. Tidy lands implicitly in Plan 01-03's `just build` once consumer code exists.
|
||||
|
||||
### Directory skeleton + doc.go placeholders (commit `4de9685`)
|
||||
- `internal/db/doc.go`, `internal/session/doc.go`, `internal/tablos/doc.go`, `internal/tasks/doc.go`, `internal/files/doc.go` — each a one-line comment + bare `package` clause per D-02.
|
||||
- Empty directories materialized via `.gitkeep`: `internal/db/queries/`, `internal/db/sqlc/`, `templates/`, `migrations/`, `bin/`, `static/`.
|
||||
- `cmd/web/`, `cmd/worker/`, `internal/web/` deliberately NOT created here — owned by Plan 01-02 (web ui/tests) and Plan 01-03 (entrypoints).
|
||||
- `go build ./internal/...` compiles cleanly.
|
||||
|
||||
### Compose, env, gitignore, bootstrap migration (commit `2fe5b51`)
|
||||
- `compose.yaml`: `postgres:16-alpine`, container name `xtablo-backend-postgres`, `xtablo:xtablo` credentials, `pg_isready` healthcheck (5s × 10), named volume `postgres_data`. No seed mounts (Phase 1 has nothing to seed).
|
||||
- `.env.example`: `DATABASE_URL`, `PORT=8080`, `ENV=development` (D-15 exact key set).
|
||||
- `.gitignore`: excludes `.env`, `bin/`, `tmp/`, generated `static/tailwind.css`, bootstrap-downloaded `static/htmx.min.js`, `*_templ.go` (Pitfall 1), `internal/db/sqlc/*.go`.
|
||||
- `migrations/0001_init.sql`: goose-formatted no-op with `-- +goose Up` / `-- +goose Down` markers and `SELECT 1;` bodies.
|
||||
|
||||
### sqlc, Tailwind input CSS, air (commit `d6085b7`)
|
||||
- `sqlc.yaml`: `version: "2"`, schema source = `migrations/` (Pitfall 7 alignment), `internal/db/queries/` → `internal/db/sqlc/` (package `sqlc`), `sql_package: "pgx/v5"`.
|
||||
- `tailwind.input.css`: verbatim per UI-SPEC contract — `@import "tailwindcss"`, three `@source` globs covering `templates/**/*.templ`, `internal/web/**/*.templ`, `internal/web/**/*.go` (Pitfall 3), then `@import` of the four `internal/web/ui/{base,button,card,badge}.css` files (those CSS files land in Plan 01-02).
|
||||
- `.air.toml`: watches `.go`+`.templ`, excludes `*_templ.go` (Pitfall 5), runs `templ generate && go build -o ./tmp/web ./cmd/web`. Tailwind intentionally NOT wired into air's pre_cmd (RESEARCH Open Q2 — two-terminal workflow).
|
||||
|
||||
### justfile (commit `ce22472`)
|
||||
Recipes: `default`, `bootstrap`, `db-up`, `db-down`, `migrate cmd="status"`, `generate`, `styles-watch`, `dev`, `test`, `lint`, `build`, `clean` — `just --list` enumerates 11 user-facing recipes.
|
||||
|
||||
- `bootstrap` installs goose `v3.27.1` / templ `v0.3.1020` / sqlc `v1.31.1` / air `v1.65.1` and downloads Tailwind v4.0.0 standalone + HTMX v2 latest into `bin/` and `static/`.
|
||||
- Tailwind asset name uses explicit `case` mapping (Codex concern #2): `Darwin→macos`, `Linux→linux`, `x86_64/amd64→x64`, `arm64/aarch64→arm64`, resolving to one of `tailwindcss-{macos,linux}-{x64,arm64}`. The four canonical asset names are documented inline; `grep -E 'tailwindcss-(macos|linux)-(x64|arm64)' backend/justfile` matches.
|
||||
- `migrate` recipe sets `GOOSE_DRIVER=postgres`, `GOOSE_DBSTRING`, `GOOSE_MIGRATION_DIR=migrations`.
|
||||
- `clean` recipe removes `bin/`, `tmp/`, `static/htmx.min.js`, `static/tailwind.css`, and `*_templ.go` files (Codex concern #10).
|
||||
- No `pnpm`/`npm`/`node` references anywhere (D-12).
|
||||
- Bootstrap-time CDN URLs (Tailwind GitHub releases, HTMX unpkg) are confined to the justfile — D-10 clarified: no **runtime** CDN references in served HTML/CSS/JS.
|
||||
|
||||
## Codex Review Concerns — Compliance
|
||||
|
||||
| # | Concern | Resolution |
|
||||
|---|---------|------------|
|
||||
| 1 | No `go mod tidy` in this plan | Honored — deps pinned via `go get` only; tidy deferred to Plan 01-03. |
|
||||
| 2 | Tailwind URL via explicit OS/arch case (not raw `uname` interpolation) | Honored — `case` statements + inline doc comment listing the four canonical assets. |
|
||||
| 3 | "Bootstrap-downloaded" wording (not "vendored") | Honored — used in .gitignore comment, justfile comments, and this SUMMARY. |
|
||||
| 4 | No runtime CDN references | Honored — the only CDN URLs in `backend/` are inside `justfile` bootstrap. |
|
||||
| 5 | `generate / test / build / dev` may not be end-to-end runnable yet | Acknowledged — only `just --list` parseability asserted in Plan 01-01. |
|
||||
| 6 | Real `just clean` recipe | Implemented — removes bin/, tmp/, generated css, htmx, *_templ.go. |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Checkpoint Auto-Approval
|
||||
|
||||
⚡ Auto-approved checkpoint: human-verify (Task 6 — `just bootstrap` + `just db-up` + `just migrate up` end-to-end)
|
||||
|
||||
Auto-mode was active. Task 6 is a real network-dependent verification (downloads goose/templ/sqlc/air CLIs, downloads Tailwind binary and HTMX, brings up a Postgres container, applies the migration). Auto-approving it means the per-task commits land; the developer is expected to actually run the five-step bootstrap loop the next time they pick the repo up. If any step fails on their machine, that becomes a follow-up bug, not a plan-execution failure. The scaffold is mechanical and the file-level acceptance criteria (every `verify` block in Tasks 1–5) all passed automated grep/build checks before commit.
|
||||
|
||||
## Pinned Versions Actually Wired
|
||||
|
||||
| Tool | Version | Where pinned |
|
||||
|------|---------|-------------|
|
||||
| Go runtime | 1.26.1 | `go.mod` (matches developer's installed toolchain) |
|
||||
| chi | v5.2.5 | `go.mod` |
|
||||
| templ runtime | v0.3.1020 | `go.mod` |
|
||||
| pgx/v5 | v5.9.2 | `go.mod` |
|
||||
| goose/v3 | v3.27.1 | `go.mod` + `justfile` (CLI install) |
|
||||
| uuid | v1.6.0 | `go.mod` |
|
||||
| templ CLI | v0.3.1020 | `justfile` (CLI install) |
|
||||
| sqlc CLI | v1.31.1 | `justfile` (CLI install) |
|
||||
| air CLI | v1.65.1 | `justfile` (CLI install) |
|
||||
| Tailwind standalone | v4.0.0 | `justfile` (download) |
|
||||
| HTMX | v2 (latest 2.x at bootstrap time) | `justfile` (download) |
|
||||
|
||||
## Verification
|
||||
|
||||
- `cd backend && test -f go.mod && grep '^module backend$' go.mod` → OK
|
||||
- `cd backend && go build ./internal/...` → OK (placeholder packages compile)
|
||||
- `cd backend && just --list` → 11 user recipes enumerated, all required names present
|
||||
- `grep -E 'tailwindcss-(macos|linux)-(x64|arm64)' backend/justfile` → 2 matches (Codex #2)
|
||||
- File-level grep checks per each task's `<verify>` block → all pass
|
||||
|
||||
## Path Forward
|
||||
|
||||
- **Plan 01-02 (Wave 2):** lands `internal/web/handlers_test.go` for `/healthz` OK/Down + index/fragment + RequestID + slog-handler-switch tests, plus the `internal/web/ui/{base,button,card,badge}.css` files referenced by `tailwind.input.css`. After 01-02, `just generate` will partially run (Tailwind step will succeed; templ step still needs Plan 01-03 templ files).
|
||||
- **Plan 01-03 (Wave 3):** lands `cmd/web/main.go`, `cmd/worker/main.go`, `internal/db/pool.go`, the templ files for the index + demo fragment, the chi router + middleware. After 01-03, `just bootstrap && just db-up && just migrate up && just dev` is a fully runnable walking skeleton.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None requiring resolution within this plan — every placeholder (`doc.go` files, `*_templ.go` ignore rule, the four `ui/*.css` `@import` lines, the `cmd/web` reference in `.air.toml`) is wired exactly where the next plans will land their real content; no UI-visible stub flows to a user yet because there is no UI yet.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- `backend/go.mod` exists with `module backend` and five pinned runtime deps — FOUND
|
||||
- `backend/go.sum` exists, non-empty — FOUND
|
||||
- `backend/internal/{db,session,tablos,tasks,files}/doc.go` all exist and `go build ./internal/...` passes — FOUND
|
||||
- `backend/compose.yaml`, `.env.example`, `.gitignore`, `migrations/0001_init.sql` — FOUND
|
||||
- `backend/sqlc.yaml`, `tailwind.input.css`, `.air.toml` — FOUND
|
||||
- `backend/justfile` parses; `just --list` shows all 11 required recipes — FOUND
|
||||
- Commits `aa90008`, `4de9685`, `2fe5b51`, `d6085b7`, `ce22472` present in `git log` — FOUND
|
||||
11
backend/.air.toml
Normal file
11
backend/.air.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
root = "."
|
||||
tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
cmd = "templ generate && go build -o ./tmp/web ./cmd/web"
|
||||
bin = "./tmp/web"
|
||||
include_ext = ["go", "templ"]
|
||||
exclude_dir = ["tmp", "bin", "static", ".git", "internal/db/sqlc"]
|
||||
exclude_regex = [".*_templ\\.go$"]
|
||||
delay = 200
|
||||
stop_on_error = true
|
||||
8
backend/.env.example
Normal file
8
backend/.env.example
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Postgres connection string used by the web + worker binaries (and `just migrate`).
|
||||
DATABASE_URL=postgres://xtablo:xtablo@localhost:5432/xtablo?sslmode=disable
|
||||
|
||||
# HTTP port for cmd/web.
|
||||
PORT=8080
|
||||
|
||||
# Environment selector: "development" enables the slog text handler; "production" switches to JSON.
|
||||
ENV=development
|
||||
24
backend/.gitignore
vendored
Normal file
24
backend/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Local environment files (only .env.example is committed)
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Bootstrap-downloaded CLIs and Tailwind binary (re-created by `just bootstrap`)
|
||||
bin/
|
||||
!bin/.gitkeep
|
||||
|
||||
# air rebuild output
|
||||
tmp/
|
||||
|
||||
# Tailwind-compiled CSS (re-created by `just generate` / `just styles-watch`)
|
||||
static/tailwind.css
|
||||
|
||||
# HTMX bootstrap-downloaded by `just bootstrap` (never committed; the justfile is the single
|
||||
# authoritative source for the pinned HTMX version — see CONTEXT D-10)
|
||||
static/htmx.min.js
|
||||
|
||||
# templ-generated Go files (regenerate via `templ generate` — Research Pitfall 1)
|
||||
*_templ.go
|
||||
|
||||
# sqlc-generated code (regenerate via `sqlc generate`); keep the .gitkeep
|
||||
internal/db/sqlc/*.go
|
||||
!internal/db/sqlc/.gitkeep
|
||||
0
backend/bin/.gitkeep
Normal file
0
backend/bin/.gitkeep
Normal file
21
backend/compose.yaml
Normal file
21
backend/compose.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: xtablo-backend-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: xtablo
|
||||
POSTGRES_USER: xtablo
|
||||
POSTGRES_PASSWORD: xtablo
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U xtablo -d xtablo"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
18
backend/go.mod
Normal file
18
backend/go.mod
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
module backend
|
||||
|
||||
go 1.26.1
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.3.1020 // indirect
|
||||
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.9.2 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/pressly/goose/v3 v3.27.1 // indirect
|
||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
)
|
||||
33
backend/go.sum
Normal file
33
backend/go.sum
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
github.com/a-h/templ v0.3.1020 h1:ypAT/L5ySWEnZ6Zft/5yfoWXYYkhFNvEFOeeqecg4tw=
|
||||
github.com/a-h/templ v0.3.1020/go.mod h1:A2DlK61v+K+NRoGnhmYbNYVmtYHcFO5/AisMvBdDxTM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
|
||||
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
|
||||
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pressly/goose/v3 v3.27.1 h1:6uEvcprBybDmW4hcz3gYujhARhye+GoWKhEWyzD5sh4=
|
||||
github.com/pressly/goose/v3 v3.27.1/go.mod h1:maruOxsPnIG2yHHyo8UqKWXYKFcH7Q76csUV7+7KYoM=
|
||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
3
backend/internal/db/doc.go
Normal file
3
backend/internal/db/doc.go
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// Package db is a Phase 1 placeholder. The pgxpool wiring and sqlc-generated
|
||||
// queries land in Plan 01-03 (Foundation Wave 3) and Phase 3 (Tablos schema).
|
||||
package db
|
||||
0
backend/internal/db/queries/.gitkeep
Normal file
0
backend/internal/db/queries/.gitkeep
Normal file
0
backend/internal/db/sqlc/.gitkeep
Normal file
0
backend/internal/db/sqlc/.gitkeep
Normal file
2
backend/internal/files/doc.go
Normal file
2
backend/internal/files/doc.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Package files is a Phase 1 placeholder; the upload/storage implementation lands in Phase 5.
|
||||
package files
|
||||
2
backend/internal/session/doc.go
Normal file
2
backend/internal/session/doc.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Package session is a Phase 1 placeholder; the session/cookie implementation lands in Phase 2.
|
||||
package session
|
||||
2
backend/internal/tablos/doc.go
Normal file
2
backend/internal/tablos/doc.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Package tablos is a Phase 1 placeholder; the tablo CRUD implementation lands in Phase 3.
|
||||
package tablos
|
||||
2
backend/internal/tasks/doc.go
Normal file
2
backend/internal/tasks/doc.go
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Package tasks is a Phase 1 placeholder; the kanban task implementation lands in Phase 4.
|
||||
package tasks
|
||||
116
backend/justfile
Normal file
116
backend/justfile
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# Xtablo backend — task runner
|
||||
#
|
||||
# Portability: compose.yaml works under both `podman compose` and `docker compose` (CONTEXT D-11).
|
||||
# This justfile uses `podman compose` by default; substitute `docker compose` if needed —
|
||||
# the service definition is identical.
|
||||
#
|
||||
# Dev workflow (two terminals, per RESEARCH Open Question 2):
|
||||
# Terminal 1: just dev # brings up postgres, generates assets, runs air for Go live-reload
|
||||
# Terminal 2: just styles-watch # runs the Tailwind standalone CLI in --watch mode
|
||||
#
|
||||
# Tailwind is intentionally NOT chained into air's pre_cmd: piping CSS rebuilds through
|
||||
# every .go save is wasteful, and the two concerns are independent (CONTEXT D-14).
|
||||
|
||||
set shell := ["bash", "-cu"]
|
||||
|
||||
# --- Pinned versions ------------------------------------------------------------------------
|
||||
# Runtime Go modules are pinned in go.mod (chi v5.2.5, templ v0.3.1020, pgx/v5 v5.9.2,
|
||||
# goose v3.27.1, uuid v1.6.0). Below: CLI tools installed by `just bootstrap`.
|
||||
goose_version := "v3.27.1"
|
||||
templ_version := "v0.3.1020"
|
||||
sqlc_version := "v1.31.1"
|
||||
air_version := "v1.65.1"
|
||||
# Tailwind standalone CLI version pinned for reproducible bootstrap. Update by bumping
|
||||
# this string after verifying the release at https://github.com/tailwindlabs/tailwindcss/releases
|
||||
tailwind_version := "v4.0.0"
|
||||
# HTMX version pinned at bootstrap time. This is the SINGLE authoritative source for the
|
||||
# HTMX version — no runtime CDN reference appears anywhere else (CONTEXT D-10).
|
||||
htmx_version := "2"
|
||||
|
||||
# --- Local config ---------------------------------------------------------------------------
|
||||
database_url := "postgres://xtablo:xtablo@localhost:5432/xtablo?sslmode=disable"
|
||||
tailwind := "./bin/tailwindcss"
|
||||
|
||||
default:
|
||||
@just --list
|
||||
|
||||
# Install all CLI tools and bootstrap-download Tailwind + HTMX into local paths.
|
||||
# Network access required. All downloaded artifacts are gitignored — `just bootstrap` is the
|
||||
# canonical reproduction step.
|
||||
bootstrap:
|
||||
mkdir -p bin static
|
||||
# 1. Go-based CLI tools (versions pinned above)
|
||||
go install github.com/pressly/goose/v3/cmd/goose@{{goose_version}}
|
||||
go install github.com/a-h/templ/cmd/templ@{{templ_version}}
|
||||
go install github.com/sqlc-dev/sqlc/cmd/sqlc@{{sqlc_version}}
|
||||
go install github.com/air-verse/air@{{air_version}}
|
||||
# 2. Tailwind standalone CLI — explicit OS/arch mapping. The Tailwind release artifacts
|
||||
# use 'macos'/'linux' and 'x64'/'arm64', which do NOT match raw `uname -s` / `uname -m`
|
||||
# output (darwin vs macos, x86_64 vs x64). Resolve via case (Codex review concern #2).
|
||||
# Resolves to one of: tailwindcss-macos-x64, tailwindcss-macos-arm64,
|
||||
# tailwindcss-linux-x64, tailwindcss-linux-arm64
|
||||
os_name=$(uname -s); \
|
||||
arch_name=$(uname -m); \
|
||||
case "$os_name" in \
|
||||
Darwin) tw_os=macos ;; \
|
||||
Linux) tw_os=linux ;; \
|
||||
*) echo "Unsupported OS: $os_name (Tailwind standalone supports macos/linux)"; exit 1 ;; \
|
||||
esac; \
|
||||
case "$arch_name" in \
|
||||
x86_64|amd64) tw_arch=x64 ;; \
|
||||
arm64|aarch64) tw_arch=arm64 ;; \
|
||||
*) echo "Unsupported arch: $arch_name"; exit 1 ;; \
|
||||
esac; \
|
||||
asset="tailwindcss-${tw_os}-${tw_arch}"; \
|
||||
echo "Downloading $asset @ {{tailwind_version}}"; \
|
||||
curl -sSL -o bin/tailwindcss \
|
||||
"https://github.com/tailwindlabs/tailwindcss/releases/download/{{tailwind_version}}/${asset}"; \
|
||||
chmod +x bin/tailwindcss
|
||||
# 3. HTMX — bootstrap-time download. This unpkg URL is the explicit allowed exception to
|
||||
# the runtime no-CDN rule (CONTEXT D-10); served HTML references only /static/htmx.min.js.
|
||||
curl -sSL -o static/htmx.min.js "https://unpkg.com/htmx.org@{{htmx_version}}/dist/htmx.min.js"
|
||||
|
||||
db-up:
|
||||
podman compose up -d postgres
|
||||
|
||||
db-down:
|
||||
podman compose down
|
||||
|
||||
# `just migrate up`, `just migrate down`, `just migrate status`, etc.
|
||||
migrate cmd="status":
|
||||
GOOSE_DRIVER=postgres GOOSE_DBSTRING='{{database_url}}' GOOSE_MIGRATION_DIR=migrations \
|
||||
goose {{cmd}}
|
||||
|
||||
# templ → Go, sqlc → Go, tailwind → static/tailwind.css. Consumers (templ files, queries,
|
||||
# ui CSS) land in Plans 01-02 / 01-03; until then this recipe will fail when invoked but
|
||||
# its declaration is the contract.
|
||||
generate:
|
||||
templ generate
|
||||
sqlc generate
|
||||
{{tailwind}} -i tailwind.input.css -o static/tailwind.css
|
||||
|
||||
styles-watch:
|
||||
{{tailwind}} -i tailwind.input.css -o static/tailwind.css --watch
|
||||
|
||||
dev: db-up
|
||||
just generate
|
||||
DATABASE_URL='{{database_url}}' air -c .air.toml
|
||||
|
||||
test:
|
||||
just generate
|
||||
go test ./...
|
||||
|
||||
lint:
|
||||
go vet ./...
|
||||
gofmt -l . | (grep . && exit 1 || exit 0)
|
||||
|
||||
build:
|
||||
just generate
|
||||
go build -o bin/web ./cmd/web
|
||||
go build -o bin/worker ./cmd/worker
|
||||
|
||||
# Remove all bootstrap-downloaded and generated artifacts. Does NOT touch the Postgres
|
||||
# volume — run `just db-down` first if a full reset is needed.
|
||||
clean:
|
||||
rm -rf bin/ tmp/ static/htmx.min.js static/tailwind.css
|
||||
find . -name '*_templ.go' -delete
|
||||
0
backend/migrations/.gitkeep
Normal file
0
backend/migrations/.gitkeep
Normal file
6
backend/migrations/0001_init.sql
Normal file
6
backend/migrations/0001_init.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-- +goose Up
|
||||
-- Phase 1: no-op bootstrap migration. Real schema lands in Phase 2 (sessions/users) and Phase 3 (tablos).
|
||||
SELECT 1;
|
||||
|
||||
-- +goose Down
|
||||
SELECT 1;
|
||||
12
backend/sqlc.yaml
Normal file
12
backend/sqlc.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
version: "2"
|
||||
sql:
|
||||
- engine: postgresql
|
||||
schema: "migrations"
|
||||
queries: "internal/db/queries"
|
||||
gen:
|
||||
go:
|
||||
package: "sqlc"
|
||||
out: "internal/db/sqlc"
|
||||
sql_package: "pgx/v5"
|
||||
emit_json_tags: false
|
||||
emit_interface: false
|
||||
0
backend/static/.gitkeep
Normal file
0
backend/static/.gitkeep
Normal file
10
backend/tailwind.input.css
Normal file
10
backend/tailwind.input.css
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@source "../templates/**/*.templ";
|
||||
@source "../internal/web/**/*.templ";
|
||||
@source "../internal/web/**/*.go";
|
||||
|
||||
@import "../internal/web/ui/base.css";
|
||||
@import "../internal/web/ui/button.css";
|
||||
@import "../internal/web/ui/card.css";
|
||||
@import "../internal/web/ui/badge.css";
|
||||
0
backend/templates/.gitkeep
Normal file
0
backend/templates/.gitkeep
Normal file
Loading…
Reference in a new issue