Wire it up + serve assets — static, handlers, router, main
Four files as tabs, in dependency order: static/embed.go → handlers.go → router.go → main.go — embed the assets, render the template, serve /static, wire it in main. The last three are modifications of your lesson-1 files: the diff shows only the changed lines, everything else is carried forward.
1. static/embed.go (new) — makes the assets part of the binary:
//go:embed assets
var FS embed.FS
The CSS and vendored htmx live under static/assets/css/style.css and static/assets/js/htmx.min.js. Those two are provided assets — this course teaches Go and HTML, so the stylesheet ships with the starter (like a design system you'd be handed at work); you're welcome to edit it. //go:embed bakes them into the compiled binary, so there's no separate asset folder to deploy.
2. internal/handlers/handlers.go (modify) — Home now renders the template. The one changed function:
func (h *Handlers) Home(w http.ResponseWriter, r *http.Request) {
render(w, r, http.StatusOK, web.Home())
}
The raw-string fmt.Fprint is gone; the fmt import with it, and web is imported instead. Health and the struct are unchanged.
3. internal/handlers/router.go (modify) — one new route and one new parameter:
func (h *Handlers) Router(staticFS fs.FS) http.Handler { // ← now takes the asset FS
// ... the same middleware ...
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.FS(staticFS))))
// ... / and /healthz unchanged ...
}
4. cmd/signflow/main.go (modify) — derive the sub-FS and hand it to the router:
staticFS, err := fs.Sub(static.FS, "assets") // expose static/assets at /static
if err != nil {
return err
}
// ...
Handler: h.Router(staticFS),
Verify. Regenerate the templates, then run:
templ generate
go run ./cmd/signflow
Open http://localhost:8080. Same content as lesson 1 — but now it's a real, styled page: the SignFlow header, the hero, the "Skeleton status" card, all wearing the stylesheet. View source and you'll see the full HTML the layout produced. And:
$ curl -s -o /dev/null -w "%{http_code}\n" localhost:8080/static/css/style.css
200
The CSS is served from inside the binary.
Gotcha (recap — the stale template). Change
home.templ, reload, see no change? You skippedtempl generate. The binary renders the committed_templ.go, not your edited.templ. Generate, rebuild, reload.