You build a full-stack app with Go and HTMX by using Go as a robust backend that renders HTML templates and serves JSON or HTML fragments, while HTMX on the frontend handles AJAX, CSS transitions, and DOM updates without writing custom JavaScript. This approach keeps your application logic in Go, maintains a single codebase for rendering, and leverages HTMX's attributes to trigger server requests and update the DOM dynamically.
Start by setting up a Go server that serves static assets and renders templates. In your HTML, use HTMX attributes like hx-post or hx-get on buttons or forms to trigger requests. When the server receives a request, it can return a full HTML page for navigation or a partial HTML snippet (a fragment) to update a specific section of the page.
Here is a minimal example of a Go handler that returns a partial HTML fragment for an HTMX request:
package main
import (
"html/template"
"net/http"
"time"
)
var tmpl = template.Must(template.ParseFiles("templates/partials.html"))
func handler(w http.ResponseWriter, r *http.Request) {
// Check if this is an HTMX request (optional but good for debugging)
if r.Header.Get("HX-Request") == "true" {
w.Header().Set("Content-Type", "text/html")
}
data := map[string]interface{}{
"timestamp": time.Now().Format(time.RFC1123),
"message": "Content updated via HTMX!",
}
// Render only the partial template, not the full page
tmpl.ExecuteTemplate(w, "partial", data)
}
func main() {
http.HandleFunc("/update", handler)
http.ListenAndServe(":8080", nil)
}
The corresponding templates/partials.html would contain the fragment to be injected:
{{define "partial"}}
<div class="card">
<h3>{{.message}}</h3>
<p>Updated at: {{.timestamp}}</p>
</div>
{{end}}
On the frontend, your HTML button triggers the update:
<!DOCTYPE html>
<html>
<head>
<title>Go + HTMX</title>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
</head>
<body>
<div id="content-area">
<p>Click the button to update this section.</p>
</div>
<!-- hx-post sends a POST request to /update -->
<!-- hx-target specifies where to put the response -->
<!-- hx-swap replaces the inner HTML of the target -->
<button hx-post="/update"
hx-target="#content-area"
hx-swap="innerHTML">
Update Content
</button>
</body>
</html>
For a complete application, structure your Go code to handle routing, database interactions, and template rendering similarly to a standard MVC pattern. Use html/template for server-side rendering of initial pages and partials. HTMX handles the interactivity, so you avoid writing fetch or XMLHttpRequest code. You can also use hx-trigger for events like load, click, or change, and hx-vals to pass form data or query parameters directly from the HTML attributes. This stack allows you to build dynamic, responsive applications with the simplicity of traditional server-side rendering and the interactivity of modern SPAs.