# Go Backend Design System Implementation Plan

> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Build a repo-owned `templ` design system for `go-backend`, generate a static catalog outside the app, and migrate `/tablos` to the new shared primitives.

**Architecture:** Keep Tailwind as the styling/token foundation, but move reusable UI into `go-backend/internal/web/ui/` as `templ` primitives plus small Go helpers. Add a Go-driven static catalog generator that renders documentation and previews from the same component implementations, then migrate `/tablos` to consume those primitives instead of ad hoc view markup.

**Tech Stack:** Go, templ, HTMX, Tailwind CSS v4, Go `net/http` tests, standard library filesystem APIs

---

## File Structure

**Existing files to modify**

- `go-backend/tailwind.input.css`
  - Add design token definitions and any shared theme aliases needed by the primitives.
- `go-backend/static/styles.css`
  - Keep only app-shell styles, semantic shared component classes, and any small non-Tailwind glue that the primitives require.
- `go-backend/internal/web/views/tablos.templ`
  - Replace ad hoc button/badge/modal/table markup with `ui` primitives.
- `go-backend/internal/web/views/tablos_view.go`
  - Adapt the tablos view models to feed the new shared component APIs.
- `go-backend/internal/web/views/dashboard_components.templ`
  - Replace any reused button or badge markup that should be shared in the first migration pass.
- `go-backend/internal/web/views/home.go`
  - Adjust any overview helper data needed to feed shared UI primitives.
- `go-backend/internal/web/handlers/tablos_test.go`
  - Update assertions to check shared component contracts.
- `go-backend/router_test.go`
  - Add or update full-page assertions proving shared primitives appear in rendered pages.
- `go-backend/justfile`
  - Add a command for generating the design-system catalog.

**New files to create**

- `go-backend/internal/web/ui/variants.go`
  - Shared enums/constants/helpers for variants and sizes.
- `go-backend/internal/web/ui/tokens.go`
  - Token names, semantic aliases, and any helper mappings needed by components.
- `go-backend/internal/web/ui/button.templ`
  - Shared button primitive.
- `go-backend/internal/web/ui/icon_button.templ`
  - Shared icon-only button primitive, including destructive/borderless cases.
- `go-backend/internal/web/ui/badge.templ`
  - Shared badge primitive for statuses.
- `go-backend/internal/web/ui/input.templ`
  - Shared text input primitive.
- `go-backend/internal/web/ui/textarea.templ`
  - Shared textarea primitive.
- `go-backend/internal/web/ui/form_field.templ`
  - Shared labeled field wrapper with error state.
- `go-backend/internal/web/ui/card.templ`
  - Shared card shell and subregions where justified.
- `go-backend/internal/web/ui/modal.templ`
  - Shared modal shell and actions.
- `go-backend/internal/web/ui/table.templ`
  - Shared table wrappers/helpers for headers and row actions.
- `go-backend/internal/web/ui/empty_state.templ`
  - Shared empty-state primitive.
- `go-backend/internal/web/ui/ui_test.go`
  - Rendering tests for core primitive contracts.
- `go-backend/internal/web/ui/catalog/pages.go`
  - Catalog page registry and page metadata.
- `go-backend/internal/web/ui/catalog/examples.go`
  - Rendered example fixtures used by the catalog.
- `go-backend/internal/web/ui/catalog/catalog.templ`
  - Shared catalog page templates.
- `go-backend/internal/web/ui/catalog/catalog_test.go`
  - Catalog rendering and registration tests.
- `go-backend/cmd/designsystem/main.go`
  - Static catalog generator entrypoint.
- `go-backend/cmd/designsystem/main_test.go`
  - Generator output tests.

**Generated files expected to change**

- `go-backend/internal/web/ui/*_templ.go`
  - Generated from the new `templ` primitives.
- `go-backend/internal/web/ui/catalog/*_templ.go`
  - Generated from catalog templates.
- `go-backend/internal/web/views/*_templ.go`
  - Regenerated after migrating views to shared primitives.
- `docs/design-system/*.html`
  - Generated static catalog output.
- `go-backend/static/tailwind.css`
  - Regenerated compiled Tailwind output.

**Verification commands**

- `cd go-backend && go test ./internal/web/ui -v`
- `cd go-backend && go test ./cmd/designsystem -v`
- `cd go-backend && go test ./internal/web/handlers -run 'Tablos|HomePage'`
- `cd go-backend && just generate`
- `cd go-backend && go test ./...`
- `cd go-backend && just build`

## Chunk 1: UI Foundation

### Task 1: Introduce failing tests for shared variant and primitive contracts

**Files:**
- Create: `go-backend/internal/web/ui/ui_test.go`

- [ ] **Step 1: Write failing rendering tests for the first primitive contracts**

Add focused tests for:

- button variants and sizes
- icon button destructive variant
- badge variant rendering
- modal shell structure

Example starter shape:

```go
func TestIconButtonRendersBorderlessDestructiveMarkup(t *testing.T) {
	component := IconButton(IconButtonProps{
		Label:   "Supprimer le projet",
		Icon:    "trash",
		Variant: IconButtonVariantDangerGhost,
	})

	html := renderToString(t, component)

	for _, want := range []string{
		`class="borderless-icon-button"`,
		`aria-label="Supprimer le projet"`,
	} {
		if !strings.Contains(html, want) {
			t.Fatalf("expected %q in %q", want, html)
		}
	}
}
```

- [ ] **Step 2: Run the focused UI tests to verify they fail**

Run: `cd go-backend && go test ./internal/web/ui -v`

Expected: FAIL because the `ui` package or primitives do not exist yet.

- [ ] **Step 3: Add the minimal `ui` package structure**

Create:

- `variants.go`
- `tokens.go`
- empty `templ` primitive files for the first component set

Keep the first implementation minimal: just enough types and entrypoints to satisfy the tests.

- [ ] **Step 4: Re-run the focused UI tests to verify the first primitives compile and pass**

Run: `cd go-backend && just generate && go test ./internal/web/ui -v`

Expected: PASS for the initial primitive contract tests.

- [ ] **Step 5: Commit**

```bash
git add go-backend/internal/web/ui go-backend/tailwind.input.css go-backend/static/styles.css
git commit -m "feat: add design system ui foundation"
```

### Task 2: Add design tokens and shared semantic class rules

**Files:**
- Modify: `go-backend/tailwind.input.css`
- Modify: `go-backend/static/styles.css`
- Test: `go-backend/internal/web/ui/ui_test.go`

- [ ] **Step 1: Write a failing token-level test**

Add a test that renders a primitive and proves semantic classes/tokens are in use rather than page-local class strings.

- [ ] **Step 2: Run the focused test to verify it fails**

Run: `cd go-backend && go test ./internal/web/ui -run 'Token|Button|Badge' -v`

Expected: FAIL due to missing token-backed class behavior.

- [ ] **Step 3: Define shared tokens and semantic CSS**

Add:

- semantic token aliases in `tailwind.input.css`
- shared borderless/destructive button styles
- any tiny semantic CSS hooks the primitives need

Do not add page-specific classes here.

- [ ] **Step 4: Re-run the focused UI tests**

Run: `cd go-backend && just generate && go test ./internal/web/ui -run 'Token|Button|Badge' -v`

Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add go-backend/tailwind.input.css go-backend/static/styles.css go-backend/internal/web/ui
git commit -m "feat: add design system tokens"
```

## Chunk 2: Primitive Components

### Task 3: Build the first reusable primitives

**Files:**
- Create/Modify: `go-backend/internal/web/ui/button.templ`
- Create/Modify: `go-backend/internal/web/ui/icon_button.templ`
- Create/Modify: `go-backend/internal/web/ui/badge.templ`
- Create/Modify: `go-backend/internal/web/ui/input.templ`
- Create/Modify: `go-backend/internal/web/ui/textarea.templ`
- Create/Modify: `go-backend/internal/web/ui/form_field.templ`
- Create/Modify: `go-backend/internal/web/ui/card.templ`
- Create/Modify: `go-backend/internal/web/ui/modal.templ`
- Create/Modify: `go-backend/internal/web/ui/table.templ`
- Create/Modify: `go-backend/internal/web/ui/empty_state.templ`
- Modify: `go-backend/internal/web/ui/ui_test.go`

- [ ] **Step 1: Expand the test suite with one failing test per primitive**

Add one focused contract test per primitive. Examples:

- `Button` renders `primary`, `ghost`, and `danger`
- `IconButton` renders icon-only action buttons
- `Badge` renders status-like visual variants
- `FormField` renders label + error text
- `Modal` renders shell/body/actions
- `Table` renders shared header/body wrappers

- [ ] **Step 2: Run the primitive tests to verify they fail**

Run: `cd go-backend && go test ./internal/web/ui -run 'Button|IconButton|Badge|Modal|Table|FormField' -v`

Expected: FAIL due to missing or incomplete primitive implementations.

- [ ] **Step 3: Implement the minimal primitives to satisfy the tests**

Keep APIs tight:

- semantic variants
- `sm`, `md`, `lg` sizes
- pass-through HTMX attrs only where needed
- no arbitrary class-first API

- [ ] **Step 4: Re-run the primitive tests**

Run: `cd go-backend && just generate && go test ./internal/web/ui -run 'Button|IconButton|Badge|Modal|Table|FormField' -v`

Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add go-backend/internal/web/ui
git commit -m "feat: add initial design system primitives"
```

## Chunk 3: Static Catalog Generator

### Task 4: Build the catalog registry and page templates

**Files:**
- Create: `go-backend/internal/web/ui/catalog/pages.go`
- Create: `go-backend/internal/web/ui/catalog/examples.go`
- Create: `go-backend/internal/web/ui/catalog/catalog.templ`
- Create: `go-backend/internal/web/ui/catalog/catalog_test.go`

- [ ] **Step 1: Write failing catalog tests**

Add tests for:

- component pages are registered
- a tokens page exists
- component examples render through the real primitives

- [ ] **Step 2: Run the focused catalog tests to verify they fail**

Run: `cd go-backend && go test ./internal/web/ui/catalog -v`

Expected: FAIL because catalog registry/templates do not exist yet.

- [ ] **Step 3: Implement the catalog registry and page templates**

Add:

- page metadata
- component examples
- shared catalog layout
- snippet sections

Use the real primitives from `internal/web/ui/`.

- [ ] **Step 4: Re-run the focused catalog tests**

Run: `cd go-backend && just generate && go test ./internal/web/ui/catalog -v`

Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add go-backend/internal/web/ui/catalog
git commit -m "feat: add design system catalog pages"
```

### Task 5: Add the static generator command and generated output

**Files:**
- Create: `go-backend/cmd/designsystem/main.go`
- Create: `go-backend/cmd/designsystem/main_test.go`
- Modify: `go-backend/justfile`
- Generated: `docs/design-system/*.html`

- [ ] **Step 1: Write failing generator tests**

Add tests that:

- create a temp output dir
- run the generator
- assert `index.html`, `tokens.html`, and at least one component page exist

- [ ] **Step 2: Run the generator tests to verify they fail**

Run: `cd go-backend && go test ./cmd/designsystem -v`

Expected: FAIL because the generator command does not exist yet.

- [ ] **Step 3: Implement the generator and `just` entrypoint**

Add:

- generator command
- output directory creation
- page rendering loop
- `just design-system` recipe

- [ ] **Step 4: Generate the static catalog and verify tests pass**

Run:

- `cd go-backend && go test ./cmd/designsystem -v`
- `cd go-backend && just design-system`

Expected:

- tests PASS
- `docs/design-system/` contains generated HTML pages

- [ ] **Step 5: Commit**

```bash
git add go-backend/cmd/designsystem go-backend/justfile docs/design-system
git commit -m "feat: add static design system generator"
```

## Chunk 4: Migrate `/tablos`

### Task 6: Replace ad hoc `/tablos` UI markup with shared primitives

**Files:**
- Modify: `go-backend/internal/web/views/tablos.templ`
- Modify: `go-backend/internal/web/views/tablos_view.go`
- Modify: `go-backend/internal/web/views/dashboard_components.templ`
- Modify: `go-backend/internal/web/views/home.go`
- Modify: `go-backend/internal/web/handlers/tablos_test.go`
- Modify: `go-backend/router_test.go`

- [ ] **Step 1: Add failing migration tests**

Add or update tests so they explicitly expect shared component contracts in `/tablos`, for example:

- shared `Button` class contract in toolbar or modal
- shared `IconButton` contract for delete actions
- shared `Badge` contract for statuses
- shared `Modal` shell contract
- shared `Table` wrapper contract

- [ ] **Step 2: Run the focused `/tablos` tests to verify they fail**

Run: `cd go-backend && go test ./internal/web/handlers -run 'Tablos|HomePage' -v`

Expected: FAIL because views still render ad hoc markup.

- [ ] **Step 3: Migrate `/tablos` to `ui` primitives**

Replace local markup with shared components:

- primary actions -> `Button`
- delete actions -> `IconButton`
- statuses -> `Badge`
- create form shell -> `Modal` + `FormField` + `Input`
- list view shell -> `Table`
- empty state -> `EmptyState`

Keep the page-specific layout, filters, and HTMX flows intact.

- [ ] **Step 4: Re-run focused `/tablos` tests**

Run: `cd go-backend && just generate && go test ./internal/web/handlers -run 'Tablos|HomePage' -v`

Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add go-backend/internal/web/views go-backend/internal/web/handlers/tablos_test.go go-backend/router_test.go
git commit -m "refactor: migrate tablos to design system primitives"
```

## Chunk 5: Final Verification And Docs Output

### Task 7: Regenerate docs, verify the full app, and lock in usage rules

**Files:**
- Modify if needed: `docs/design-system/*.html`
- Modify if needed: `go-backend/internal/web/ui/catalog/*`
- Modify if needed: `go-backend/internal/web/ui/ui_test.go`

- [ ] **Step 1: Generate the final catalog output**

Run: `cd go-backend && just design-system`

Expected: refreshed static catalog pages under `docs/design-system/`.

- [ ] **Step 2: Run the full verification suite**

Run:

- `cd go-backend && just generate`
- `cd go-backend && go test ./...`
- `cd go-backend && just build`

Expected:

- all tests PASS
- app builds cleanly

- [ ] **Step 3: Do a final plan-vs-spec review pass**

Check:

- primitives exist
- catalog exists and is generated outside the app
- `/tablos` uses shared primitives
- no duplicate delete button implementation remains

- [ ] **Step 4: Commit**

```bash
git add go-backend docs/design-system
git commit -m "feat: add go-backend design system"
```
