Building a Go Web App with HTMX and Bamboo CSS: A Step‑by‑Step Guide
Set up a Go web app skeleton with HTMX and Bamboo CSS, embed assets, and use an htmlRenderer for template rendering.
Create the project skeleton, download HTMX, Bamboo CSS, and gopher image, and implement the htmlRenderer as shown.
Summary
The tutorial begins by creating a Go project skeleton that organizes assets into separate directories for static files, templates, and Go code, ensuring a clean separation of concerns. HTMX is installed via wget and served as a static file, while Bamboo CSS and a gopher image are also downloaded into the static folder, providing styling and visual content without relying on a CDN. The template structure uses a base.tmpl that defines the common layout, pages for page‑specific content, and partials for reusable snippets, with explicit template names defined using {{define}} blocks for clarity. The HTML templates import Bamboo CSS and HTMX with a defer attribute, ensuring HTMX loads after the DOM is parsed. Asset embedding is achieved with Go 1.16’s //go:embed directive, creating separate HTMLFiles and StaticFiles file systems that avoid path prefixes when opening files. An htmlRenderer type is introduced to parse shared templates at startup, clone them for each request, and execute named templates, encapsulating rendering logic and custom functions like now(). The renderer’s render method writes the output to the response writer, handling errors gracefully. The guide concludes with a practical example of a button that triggers an HTMX GET request to /gopher, demonstrating partial page updates and dynamic content rendering.
Key changes
- Project skeleton separates assets, static files, templates, and Go code
- HTMX, Bamboo CSS, and gopher image are downloaded via wget and served statically
- Template structure uses base.tmpl, pages, and partials with explicit names
- HTMX is loaded with defer to avoid blocking DOM parsing
- Assets are embedded using //go:embed, creating HTMLFiles and StaticFiles FSs
- htmlRenderer parses shared templates, clones them per request, and executes named templates
- Custom template functions like now() are added to the renderer
- The renderer writes rendered output to the HTTP response