14 KiB
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
uiprimitives.
- Replace ad hoc button/badge/modal/table markup with
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
templprimitives.
- Generated from the new
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 -vcd go-backend && go test ./cmd/designsystem -vcd go-backend && go test ./internal/web/handlers -run 'Tablos|HomePage'cd go-backend && just generatecd 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:
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
uipackage structure
Create:
variants.gotokens.go- empty
templprimitive 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
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
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:
-
Buttonrendersprimary,ghost, anddanger -
IconButtonrenders icon-only action buttons -
Badgerenders status-like visual variants -
FormFieldrenders label + error text -
Modalrenders shell/body/actions -
Tablerenders 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,lgsizes -
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
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
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
justentrypoint
Add:
-
generator command
-
output directory creation
-
page rendering loop
-
just design-systemrecipe -
Step 4: Generate the static catalog and verify tests pass
Run:
cd go-backend && go test ./cmd/designsystem -vcd go-backend && just design-system
Expected:
-
tests PASS
-
docs/design-system/contains generated HTML pages -
Step 5: Commit
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
Buttonclass contract in toolbar or modal -
shared
IconButtoncontract for delete actions -
shared
Badgecontract for statuses -
shared
Modalshell contract -
shared
Tablewrapper contract -
Step 2: Run the focused
/tablostests 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
/tablostouiprimitives
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
/tablostests
Run: cd go-backend && just generate && go test ./internal/web/handlers -run 'Tablos|HomePage' -v
Expected: PASS.
- Step 5: Commit
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 generatecd 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
-
/tablosuses shared primitives -
no duplicate delete button implementation remains
-
Step 4: Commit
git add go-backend docs/design-system
git commit -m "feat: add go-backend design system"