Working With Templates
DeploySolo uses Go’s html/template package with a small set of conventions that make templates predictable, reusable, and htmx-friendly. Templates are loaded once at startup and shared across all routes.
Template loading and layout
Templates live under web/templates and are loaded in main.go via:
render.LoadTemplates(pb, "web/templates")
This directory is expected to contain:
- Pages: full HTML documents (
templates/pages/*.html) - Partials: shared fragments (
templates/partials/*.tmpl) - Inline blocks: reusable named templates defined inside page files (e.g.
{{ define "task" }})
A page template should include:
- A full HTML document (
<!DOCTYPE html>) - Shared partials like
headandnavbar - One or more named blocks for htmx partial rendering
Example (simplified):
todo.htmldefines:"task"– view state"updatetask"– edit state- The full page layout
This keeps all UI states for a page in one file.
Rendering full pages
Use render.Render("page.html", data) when returning a complete page. The data you pass becomes .Data in the template.
From the Todo example:
- The authenticated user’s tasks JSON field is unmarshaled into []Task
- That slice is passed directly to the template
- The page iterates over .Data to render the initial list
This pattern works well for dashboards, settings pages, and any route that should load normally or via hx-boost.
Rendering partials for htmx
For htmx endpoints, return only the HTML fragment needed for the swap:
- Use
render.RenderRaw("templateName", data) - The named template must render a single root element
- The root element’s
idshould match thehx-target
Example:
- Target:
#task-<id> - Returned HTML: a
<div id="task-<id>">...</div>or<form id="task-<id>">...</form>
This is critical for clean outerHTML swaps and avoids layout drift.
Template design rules
Follow these rules consistently:
- One page = one
.htmlfile - Keep htmx states as named templates in the same file
- Do not return full documents from htmx routes
- Keep CSS classes identical between view/edit states unless a visual change is intentional
WebAwesome components are safe to use inside templates and work seamlessly with htmx swaps.
For how templates connect to routes and handlers, see Creating Pages and htmx Routes.