skip to the main content
2025-08-14

Making webapps using Golang Tailwind Templ Htmx Sqlc

Code here: https://github.com/domi-ninja/gotths-example

GoTTHS - Golang Tailwind Templ Htmx Sqlc

The whole fun of doing full-stack go is cooking your own stack. There are some like it, but this one is mine.

Inspired by

Reasoning for technolgies used

  • Tailwind: I am fine with using plain CSS with variables, but prefer tailwind. As a bonus, this allows me to use things like https://daisyui.com/htmx-component-library/. It also makes it so that ai-generated styles are less likely to break existing styles in other places (not local to the component).
  • Templ: Inspired by pocketbase, I have tried using a thin wrapper around html/template for server side rendering. It worked fine, but similar to tailwind, I have concluded that it is worth using. In this case, the slight annoyances are worth it to recieve some compile-time type safety for the templates, and for being able to use the database models generated by sqlc directly in my templates
  • HTMX is one of the many fun ways to make the server side rendered pages come to life. I am very familiar with it, but there is many other mini-frameworks that would do the same jobs just as well
  • SQLC: SQLC is used for generating models and functions for interacting with a relational DB. It occupies a sweet spot between an ORM and having to write your own DB interfaces with a bunch of copy-pasting, and I feel very good about using this.

Files

$ tree -L 2
.
├── app.go                      entry point and routing
├── app.toml                    config file for our app
├── cmd
│   └── server                  
├── data.db                     sqlite3 db file for development
├── frontend
│   ├── assets                  frontend blobs
│   ├── components              templ reused page components 
│   ├── layouts                 templ layout components 
│   ├── tailwind.config-v3.js   configure tailwind here
│   ├── tailwind-input-v3.css   change styles here
│   └── views                   templ actual views / partial views
├── go.mod
├── goose.sh                    bash wrapper for goose command
├── go.sum
├── handle_index.go               handler for /
├── handle_post_postid_DELETE.go  handler for delete existing post: DELETE to /post/{postId}
├── handle_posts_POST.go          handler for creating new post:    POST to /posts
├── handle_posts_postid_GET.go    handler for rendering post:       GET to /post/{postId}
├── handle_reload_WS.go           websocket demo and `/reload` dev utility
├── handler_utils.go              http handler utils for less code
├── internal
│   └── db_generated            db binding code generated by sqlc
├── Makefile                    interact with this project using make
├── README.md
├── sql
│   ├── migrations              numbered goose migrations
│   └── query                   named sqlc queries
├── sqlc.yaml                   
└── webhelp                     some minimal framework stuff that might be reused
    ├── config.go                   config parser
    ├── env_dev.go                  prod vs dev compile time differences example
    ├── env_prod.go                 ^
    ├── logger.go                   logger middleware that helps find where in the code things happen
    ├── render.go                   wrapping templ rendering in case we need that 
    ├── utils.go
    └── webhelp.go

Dev features

  • All changes result in a recompile via air, which then triggers an homemade websocket-based page refresher in the browser (reload.js)
  • Makefile

PRs welcome

This is a very small example, not a fully featured template. I have not researched if a good one exists.
This may never change since golang is very well suited to handknitted software like this. Still, one never knows

Missing features that would be cool to have

  • [ ] Auth via a provider
  • [ ] Auth, handrolled, but convering all the weird edge cases
  • [ ] File upload using a configured S3 service
  • [ ] A nice way to do form validation
  • [ ] Common frontend components, e.g. Date and Calendar, using something like daisyui perhaps?
  • [ ] Some sort of deployment story in addition to “golang can compile everything into a blob, figure it out yourself”