Why Templ — type safety and generation
Lesson 1 ended with Home writing HTML as a raw Go string. That works for one line and falls apart for a real page: no type-checking, a missing </div> compiles fine and breaks at runtime, and there's no way to share a header across pages. We need real templates — and we want them type-safe.
Templ compiles HTML templates into Go functions. You write .templ files; a generator turns each into a _templ.go file of plain Go. The payoff: a template is type-checked like any other Go code. Pass an int where the template expects a string and it won't compile — the error is at build time, at the exact line, not a blank space on a live page.
The generation step. After you write or edit a .templ file, you run:
templ generate
That regenerates the _templ.go files. We commit the generated .go alongside the .templ — so the app builds and deploys with only the Go toolchain; templ is needed only when you change a template. (This mirrors how a real project keeps generated code in the repo so CI doesn't need every code-gen tool installed.)
Gotcha — the stale-template trap. Edit a
.templ, forget to runtempl generate, reload the page, and you see the old output — because the running binary uses the committed_templ.go, not your edited.templ. It looks like your change did nothing. It's not broken; it's un-generated. The habit that saves you: edit.templ→templ generate→ rebuild. (Many editors run it on save.)
HTMX, vendored — no build step. SignFlow uses HTMX for interactivity later (a form that posts without a full page reload). HTMX is a single JavaScript file; we vendor it under static/js/htmx.min.js and link it from the layout. No npm, no bundler, no CDN dependency at runtime — the file ships inside the binary. The whole front end is: server-rendered HTML + one vendored script.
This lesson. You'll build a shared Layout, a Home page that slots into it, a tiny render helper, and wire Home to render the template instead of a string. Same page as lesson 1 — but now the compiler checks it, and it finally has some CSS.