HTMX and Golang
In the world of web development, simplicity and efficiency are key. This is where the combination of HTMX and Go comes into play. HTMX allows you to access AJAX, CSS Transitions, WebSockets, and more, directly in HTML, making your front-end development simpler. Golang, on the other hand, is renowned for its efficiency and simplicity in backend development. In this blog post, we will create a basic Todo application using HTMX on the frontend and Go as the backend server.
Setting Up the Go Environment
First, ensure you have Go installed on your system. You can download it from the official Go website.
Once installed, create a new directory for our project and initialize a new Go module:
mkdir todo-app
cd todo-app
go mod init todo-app
Creating the Go Server
Our Golang server will handle HTTP requests. Let's start by creating a file named main.go
:
package main
import (
"html/template"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("index.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl.Execute(w, nil)
})
log.Println("Starting server on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
This code snippet creates a basic web server that listens on port 8080 and serves an index.html
file.
Integrating HTMX
HTMX is a powerful tool that allows you to access modern browser features directly from HTML. To use HTMX, you need to include it in your HTML file. Create a file named index.html
in the same directory:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo App</title>
<script src="https://unpkg.com/htmx.org"></script>
</head>
<body>
<h1>Todo App</h1>
<!-- Todo List will be loaded here -->
<div id="todo-list" hx-get="/todos" hx-trigger="load">
Loading todos...
</div>
</body>
</html>
This HTML file includes HTMX and sets up a div that will be populated with our Todo list.
Building the Todo List
Let's add the ability to list, add, and delete todos. We will start by defining a Todo struct in our Golang code:
type Todo struct {
ID int
Title string
Done bool
}
For simplicity, we will store our todos in memory:
var todos = []Todo{
{1, "Learn Go", false},
{2, "Build a Todo App", false},
}
Now, let's create handlers for listing, adding, and deleting todos in main.go
:
List Todos
http.HandleFunc("/todos", func(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.ParseFiles("todos.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl.Execute(w, todos)
})
Add Todo
http.HandleFunc("/add-todo", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
title := r.FormValue("title")
todos = append(todos, Todo{len(todos) + 1, title, false})
http.Redirect(w, r, "/", http.StatusFound)
}
})
Delete Todo
http.HandleFunc("/delete-todo", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
id, err := strconv.Atoi(r.FormValue("id"))
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Delete todo from todos slice
// ...
http.Redirect(w, r, "/", http.StatusFound)
}
})
The Frontend with HTMX
In index.html
, use HTMX to handle adding and deleting todos:
<body>
<!-- ... -->
<form hx-post="/add-todo" hx-target="#todo-list">
<input type="text" name="title" required>
<button type="submit">Add Todo</button>
</form>
<div id="todo-list" hx-get="/todos" hx-trigger="load">
<!-- Todos will be loaded here -->
</div>
</body>
Each todo item can have a delete button:
<!-- In todos.html -->
{{range .}}
<div>
<span>{{.Title}}</span>
<form hx-post="/delete-todo" hx-target="#todo-list">
<input type="hidden" name="id" value="{{.ID}}">
<button type="submit">Delete</button>
</form>
</div>
{{end}}
Conclusion
We've created a basic Todo application using HTMX and Go. This setup demonstrates how you can build dynamic and efficient web applications with minimal JavaScript, leveraging the power of HTMX on the frontend and the simplicity and performance of Go on the backend.
Remember, this is just a basic example. For a production application, you would need to consider aspects like persistent storage, input validation, and error handling in more depth. However, this example serves as a great starting point for building simple, dynamic web applications with these powerful technologies.