Files
deploy-felhom-compose/TASK.md
T
2026-02-15 10:23:02 +01:00

257 lines
8.9 KiB
Markdown

# TASK.md — Controller Refactoring: Template Split, Server Decomposition, Domain Rename
> **Goal:** Improve code organization for maintainability and Claude Code efficiency.
> No new features — purely structural refactoring + one config rename.
>
> **Version bump:** v0.3.0 (structural refactor milestone)
---
## Task 1: Split templates.go → go:embed (HIGH PRIORITY)
The `templates.go` file contains ALL HTML templates and CSS as Go string constants.
The file itself says: *"As the UI grows, switch to go:embed for easier editing."*
With 7 templates + full CSS, it's time.
### 1.1 — Create template files directory
Create `controller/internal/web/templates/` with individual files:
```
internal/web/templates/
├── layout.html ← from layoutTmpl const
├── dashboard.html ← from dashboardTmpl const
├── stacks.html ← from stacksTmpl const (the stacks list page, NOT the old dashboard list)
├── login.html ← from loginTmpl const
├── logs.html ← from logsTmpl const
├── deploy.html ← from deployTmpl const
├── app_info.html ← from appInfoTmpl const
└── style.css ← from cssTemplate const
```
Each `.html` file should contain ONLY the template content (the `{{define "name"}}...{{end}}` block).
Keep the existing template names (`layout_start`, `layout_end`, `dashboard`, `stacks`, `login`, etc.).
### 1.2 — Create embed.go
Create `controller/internal/web/embed.go`:
```go
package web
import "embed"
//go:embed templates/*.html templates/*.css
var templateFS embed.FS
```
### 1.3 — Update template loading in server.go (or the new funcmap.go, see Task 2)
Replace the current `loadTemplates()` method that parses the `allTemplates` const:
```go
func (s *Server) loadTemplates() {
funcMap := template.FuncMap{ /* ... existing funcs ... */ }
s.tmpl = template.Must(
template.New("").Funcs(funcMap).ParseFS(templateFS, "templates/*.html"),
)
}
```
CSS serving: Instead of the `cssTemplate` const, read from `templateFS`:
```go
func (s *Server) serveCSSHandler(w http.ResponseWriter, r *http.Request) {
data, err := templateFS.ReadFile("templates/style.css")
if err != nil {
http.Error(w, "CSS not found", 500)
return
}
w.Header().Set("Content-Type", "text/css; charset=utf-8")
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write(data)
}
```
Register this handler for `/static/style.css` in `ServeHTTP` (replace the current inline CSS serving).
### 1.4 — Delete old string constants
Remove from `templates.go`:
- `const allTemplates = ...`
- `const layoutTmpl = ...`
- `const dashboardTmpl = ...`
- `const stacksTmpl = ...`
- `const loginTmpl = ...`
- `const logsTmpl = ...`
- `const deployTmpl = ...`
- `const appInfoTmpl = ...`
- `const cssTemplate = ...`
After this, `templates.go` should either be empty (delete it) or contain only the
felhom logo SVG constant if that's still embedded as a string (keep that one — it's small).
### 1.5 — Verify the build
- `go build ./cmd/controller/` must succeed
- `go:embed` requires Go 1.16+ (we're on 1.22, fine)
- Templates are still compiled into the binary — zero runtime file dependencies (same as before)
- Verify that the HTML files actually include the `{{define "name"}}...{{end}}` wrappers
(ParseFS needs them to register template names)
### Important notes
- The `<link rel="stylesheet" href="/static/style.css">` in layout.html already exists,
so CSS loading via the `/static/style.css` route should already work — just make sure
the handler reads from embed.FS instead of serving the const.
- The felhom logo SVG can stay as a Go const (it's small) or move to `templates/felhom-logo.svg`
and be served from embed.FS too. Either approach is fine.
---
## Task 2: Split server.go into focused files (MEDIUM PRIORITY)
Currently `server.go` handles: Server struct, auth/sessions, page handlers, template FuncMap,
asset serving, and HTTP routing. Split into:
### 2.1 — Create `auth.go`
Move from `server.go` to `internal/web/auth.go`:
- `type session struct`
- `const sessionCookieName`, `const sessionMaxAge`
- `RequireAuth()` middleware method
- `loginHandler()`, `loginPostHandler()`, `logoutHandler()`
- `createSession()`, `isValidSession()`, `cleanupSessions()`
- `renderLogin()` helper
### 2.2 — Create `handlers.go`
Move from `server.go` to `internal/web/handlers.go`:
- `baseData()` helper
- `dashboardHandler()`
- `stacksHandler()`
- `deployPageHandler()`
- `deployPagePostHandler()` (if it exists as separate handler)
- `appDetailHandler()`
- `logsPageHandler()`
### 2.3 — Create `funcmap.go`
Move from `server.go` to `internal/web/funcmap.go`:
- The entire `template.FuncMap` definition from `loadTemplates()`
- Extract it as a standalone function: `func (s *Server) templateFuncMap() template.FuncMap`
- Then `loadTemplates()` becomes a clean 3-liner calling `templateFuncMap()` + `ParseFS`
### 2.4 — Keep in server.go
After the split, `server.go` should contain only:
- `type Server struct`
- `func NewServer()`
- `func (s *Server) loadTemplates()` (now a 3-liner)
- `func (s *Server) ServeHTTP()` (HTTP routing dispatch)
- `func (s *Server) render()` helper
- Static file/asset serving handlers (`serveStaticFile`, `serveCSSHandler`, `serveLogoHandler`)
### 2.5 — Verify the split
All files are in `package web` — no import changes needed within the package.
The `Server` struct and all its methods are accessible across files in the same package.
Run `go build ./cmd/controller/` to verify everything compiles.
---
## Task 3: Rename controller domain from `dashboard.*` to `felhom.*` (LOW PRIORITY)
### 3.1 — Update controller's docker-compose.yml
In `controller/docker-compose.yml`, change the Traefik label:
```yaml
# OLD:
- "traefik.http.routers.controller.rule=Host(`dashboard.${DOMAIN}`)"
# NEW:
- "traefik.http.routers.controller.rule=Host(`felhom.${DOMAIN}`)"
```
### 3.2 — Update docker-setup.sh
In `controller/scripts/docker-setup.sh`, update `print_summary()` output:
- Any reference to `dashboard.${BASE_DOMAIN}``felhom.${BASE_DOMAIN}`
Also check install_controller() if it generates compose files or prints URLs.
### 3.3 — Update controller.yaml.example
If there's any reference to `dashboard.*` in the example config or comments, update to `felhom.*`.
### 3.4 — Update documentation
In CLAUDE.md build/deploy workflow sections, update any `dashboard.` references to `felhom.`.
### 3.5 — Cloudflare Tunnel public hostname (MANUAL — not code)
**Reminder for Viktor:** After deploying, manually update the Cloudflare Tunnel
public hostname in the Zero Trust dashboard:
- Old: `dashboard.demo-felhom.eu` → Traefik
- New: `felhom.demo-felhom.eu` → Traefik
### 3.6 — Pi-hole DNS (MANUAL — not code)
**Reminder for Viktor:** If there's a pi-hole local DNS record for `dashboard.demo-felhom.eu`,
update it to `felhom.demo-felhom.eu` (or rely on the wildcard `*.demo-felhom.eu` record).
---
## Task 4: Update documentation
### 4.1 — README.md
- Update directory structure to show `internal/web/templates/` directory
- Update "Tech stack" section: "Templates: go:embed HTML files" instead of "Go string constants"
- Mention the `felhom.*` subdomain for the controller
- Update file tree showing the new files (embed.go, auth.go, handlers.go, funcmap.go)
### 4.2 — CLAUDE.md
- Update workspace layout to reflect the new `internal/web/` file structure
- Update "Tech stack" section
- Update any `dashboard.*` references to `felhom.*`
- Note the go:embed pattern for future template additions
### 4.3 — CONTEXT.md
- Add session entry documenting the refactoring
- Note: templates moved from Go string constants to go:embed HTML files
- Note: server.go split into auth.go, handlers.go, funcmap.go
- Note: controller domain changed from dashboard.* to felhom.*
- Update version to v0.3.0
### 4.4 — BUILDING.md
- Update the structure check in build.sh verification section if needed
(the `internal/web/templates/` directory should exist now)
---
## Implementation order
1. **Task 1** (templates.go → go:embed) — do this first, biggest impact
2. **Task 2** (server.go split) — do this second, leverages the cleaner templates
3. **Task 3** (domain rename) — small, do last
4. **Task 4** (docs) — update after all code changes
## Verification checklist
- [ ] `go build ./cmd/controller/` compiles successfully
- [ ] All 7 HTML templates render correctly (login, dashboard, stacks, deploy, app_info, logs, layout)
- [ ] CSS loads at `/static/style.css`
- [ ] Felhom logo SVG loads at `/static/felhom-logo.svg`
- [ ] App logos/screenshots still serve from `/assets/`
- [ ] Auth (login/logout/session) works unchanged
- [ ] Stack operations (start/stop/deploy) work unchanged
- [ ] Controller accessible at `felhom.demo-felhom.eu` (after CF tunnel update)
- [ ] No broken links or template errors in browser console
- [ ] Build + push via build.sh works
- [ ] Deploy on demo-felhom works