Skip to content

Getting Started with HTMX and Go


Using HTMX and Go to build web applications involves creating a backend using Go (commonly known as Golang) and integrating HTMX on the frontend for dynamic and interactive functionalities.

What is HTMX?

HTMX is a JavaScript library that enables dynamic behavior by leveraging HTML attributes, allowing you to create web applications with minimal JavaScript code.

HTMX is designed with a REST backend in mind, providing a lightweight SPA-like feel by replacing and rendering individual components in server responses instead of the entire page.

Below is a step-by-step guide on building a simple web application using HTMX and Go:

Example 1

1. Set up your development environment

Make sure you have Go installed on your computer. You can download it from the official website:

2. Create a Go project

Create a new directory for your project and initialize it as a Go module:

mkdir your_project_name
cd your_project_name
go mod init

3. Create a simple Go server

Create a file named main.go in the project directory:

// main.go
package main

import (

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, HTMX!")

    http.ListenAndServe(":8080", nil)

4. Integrating HTMX into your HTML

Create an HTML file in your project directory, for example, index.html:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTMX Go App</title>
    <script src=""></script>

<h1 id="greeting" hx-get="/api/greeting">Loading...</h1>


5. Creating API endpoints in Go

Modify your main.go file to include API endpoints:

// main.go
package main

import (

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        http.ServeFile(w, r, "index.html")

    http.HandleFunc("/api/greeting", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, HTMX from Go!")

    http.ListenAndServe(":8080", nil)

6. Run your Go application

Use the following command to run your Go application:

go run main.go

Visit http://localhost:8080 in a web browser, and you should see your web application running with HTMX support.

Example 2

This UI and backend are implemented with just 150 lines of code (including HTML)!

  1. Start by creating a simple TODO resource.
package main

import ""

type TODO struct {

    Title       string
    Description string
    Completed   bool

func main() {
    api := babyapi.NewAPI[*TODO](
        "TODOs", "/todos",
        func() *TODO {return &TODO{} },

  1. Adding HtmlX

In order to add HTMX UI on top of this, here’s what we need to do:

(1) Implement the babyapi.HTMLer interface for the TODO resource.

(2) Use the new babyapi.HTMLer type with api.SetGetAllResponseWrapper to render the response for /todosHTML.

(3) Write a template for the HTMX frontend with the following features:

  • List all TODOs in a table.
  • Buttons for marking items as completed and deleting them.
  • Automatically append new TODOs with events sent from the server.
  • Form for creating new TODOs.

(4) Use HTML instead of JSON for the response:

type HTMLerinterface {
    HTML(*http.Request) string

HTML(*http.Request) method can be implemented as follows:

const todoRowTemplate = `...`

func (t *TODO) HTML(*http.Request) string {
    tmpl := template.Must(
return babyapi.MustRenderHTML(tmpl, t)

This method simply renders a template from a string and executes it with babyapi.MustRenderHTML along with the TODO data.

(5) HTML template:

<tr hx-target="this" hx-swap="outerHTML">
    <td>{{ .Title }}</td>
    <td>{{ .Description }}</td>
        {{- $disabled := "" }}
        {{-if .Completed }}
            {{- $disabled = "disabled" }}
        {{- end -}}

            hx-put="/todos/{{ .ID }}"
            hx-headers='{"Accept": "text/html"}'
            {{ $disabled }}>

            <!-- Include entire TODO itemfor idempotent PUT -->
            <input type="hidden" name="Completed" value="true">
            <input type="hidden" name="Title" value="{{ .Title }}">
            <input type="hidden" name="Description" value="{{ .Description }}">
            <input type="hidden" name="ID" value="{{ .ID }}">

        <button hx-delete="/todos/{{ .ID }}" hx-swap="swap:1s">

This template will create an HTML table row (<tr>) to display the title and description of a TODO. The row also includes buttons to mark the item as complete or delete it.

In addition to regular HTML, we can use HTMX attributes to control the interaction with the backend.


Leave a message

  • Welcome to visit the knowledge base of SRE and DevOps!
  • License under CC BY-NC 4.0
  • Made with Material for MkDocs and improve writing by generative AI tools
  • Copyright issue feedback, replace # with @