# Go Backend Login 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:** Replace the current Vite-oriented `go_backend` app with a standalone Go web app that serves a templ-rendered XTablo login page and uses HTMX for inline login feedback on `http://localhost:3000`.

**Architecture:** The server remains a small `chi` application. `GET /` renders a full page from `templ`, `POST /login` returns a small server-rendered fragment for HTMX swaps, and `GET /static/*` serves local CSS. The page includes the HTMX runtime from the specified CDN URL and no custom app JavaScript.

**Tech Stack:** Go, chi, templ, net/http, HTMX CDN, server-served CSS

---

## Chunk 1: Test Scaffold And Module Setup

### Task 1: Add dependencies and basic file layout

**Files:**
- Modify: `go_backend/go.mod`
- Modify: `go_backend/go.sum`
- Create: `go_backend/internal/web/handlers/login.go`
- Create: `go_backend/internal/web/views/layout.templ`
- Create: `go_backend/internal/web/views/login.templ`
- Create: `go_backend/static/styles.css`

- [ ] **Step 1: Add the failing tests first before any production behavior changes**
- [ ] **Step 2: Add `templ` module dependency after the tests are in place**
- [ ] **Step 3: Create focused directories for handlers, views, and static assets**
- [ ] **Step 4: Keep Vite-only files untouched until replacement code is ready**

## Chunk 2: HTTP-Level TDD

### Task 2: Cover the root page

**Files:**
- Create: `go_backend/router_test.go`
- Test: `go_backend/router_test.go`

- [ ] **Step 1: Write a failing test for `GET /`**

```go
func TestRootRendersLoginPage(t *testing.T) {
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()

	router := newRouter()
	router.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", rec.Code)
	}

	body := rec.Body.String()
	for _, want := range []string{
		"Se connecter a Xtablo",
		`hx-post="/login"`,
		"https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-beta2/dist/htmx.min.js",
	} {
		if !strings.Contains(body, want) {
			t.Fatalf("expected body to contain %q", want)
		}
	}
}
```

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

Run: `go test ./...`
Expected: the new root-page assertions fail against the current Vite/Spa output.

- [ ] **Step 3: Implement the minimum root-page rendering path**
- [ ] **Step 4: Run test to verify it passes**

Run: `go test ./...`
Expected: `TestRootRendersLoginPage` passes.

### Task 3: Cover HTMX login fragment behavior

**Files:**
- Modify: `go_backend/router_test.go`
- Test: `go_backend/router_test.go`

- [ ] **Step 1: Write a failing test for missing login fields**

```go
func TestLoginReturnsValidationError(t *testing.T) {
	form := url.Values{}
	form.Set("email", "")
	form.Set("password", "")

	req := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()

	router := newRouter()
	router.ServeHTTP(rec, req)

	if rec.Code != http.StatusUnprocessableEntity {
		t.Fatalf("expected status 422, got %d", rec.Code)
	}
	if !strings.Contains(rec.Body.String(), "Veuillez renseigner votre email et votre mot de passe") {
		t.Fatalf("expected validation error fragment, got %q", rec.Body.String())
	}
}
```

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

Run: `go test ./...`
Expected: missing route or wrong response.

- [ ] **Step 3: Write a failing test for demo credential success**

```go
func TestLoginReturnsSuccessMessage(t *testing.T) {
	form := url.Values{}
	form.Set("email", "demo@xtablo.com")
	form.Set("password", "xtablo-demo")

	req := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	rec := httptest.NewRecorder()

	router := newRouter()
	router.ServeHTTP(rec, req)

	if rec.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", rec.Code)
	}
	if !strings.Contains(rec.Body.String(), "Connexion reussie") {
		t.Fatalf("expected success fragment, got %q", rec.Body.String())
	}
}
```

- [ ] **Step 4: Run test to verify it fails**

Run: `go test ./...`
Expected: no success behavior exists yet.

- [ ] **Step 5: Implement the minimal `POST /login` validation and fragment rendering**
- [ ] **Step 6: Run test to verify both login fragment tests pass**

Run: `go test ./...`
Expected: both login tests pass.

## Chunk 3: Replace Vite-Oriented Production Code

### Task 4: Simplify routing and startup

**Files:**
- Modify: `go_backend/main.go`
- Modify: `go_backend/router.go`
- Possibly remove references from: `go_backend/internal/spahandler/handler.go`
- Possibly remove references from: `go_backend/internal/frontend/file.go`

- [ ] **Step 1: Introduce a `newRouter()` function shared by tests and main**
- [ ] **Step 2: Bind the server to `localhost:3000`**
- [ ] **Step 3: Replace dev/prod SPA branching with direct routes for `/`, `/login`, and `/static/*`**
- [ ] **Step 4: Remove unused Vite-specific wiring once tests stay green**

### Task 5: Render the login page with templ

**Files:**
- Modify: `go_backend/internal/web/views/layout.templ`
- Modify: `go_backend/internal/web/views/login.templ`
- Modify: `go_backend/internal/web/handlers/login.go`
- Modify: `go_backend/static/styles.css`

- [ ] **Step 1: Create a base page layout with head metadata, CSS link, and HTMX CDN script**
- [ ] **Step 2: Create the login page component**
- [ ] **Step 3: Create a reusable status fragment component for success and error states**
- [ ] **Step 4: Match the requested visual structure with local CSS, not utility classes**
- [ ] **Step 5: Keep copy in French and links as placeholders where needed**

## Chunk 4: Verification

### Task 6: Generate code, format, test, and build

**Files:**
- Generated: `go_backend/internal/web/views/*_templ.go`

- [ ] **Step 1: Generate templ output**

Run: `templ generate`
Expected: updated generated Go files for the templ views.

- [ ] **Step 2: Format the Go code**

Run: `gofmt -w main.go router.go internal/web/handlers/login.go internal/web/views/*_templ.go router_test.go`
Expected: no output, files rewritten in place.

- [ ] **Step 3: Run the full Go test suite**

Run: `go test ./...`
Expected: all tests pass.

- [ ] **Step 4: Run a build verification**

Run: `go build ./...`
Expected: build succeeds with exit code 0.

- [ ] **Step 5: Manual smoke check**

Run: `go run .`
Expected: server listens on `http://localhost:3000`.

---

Plan complete and saved to `docs/superpowers/plans/2026-05-07-go-backend-login.md`. Ready to execute.
