-- Leo's gemini proxy

-- Connecting to capsule.adrianhesketh.com:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; charset=utf-8

capsule.adrianhesketh.com


home


Templ - hot reload with Air


My colleague Joe [0] introduced me to air [1] this week. He'd been using it while building a web app with the templ [2] templating language to rebuild templates, and restart his Go web server.


[0]

[1]

[2]


I'd never seen it before, but it was just what I was looking for.


Once you've installed it, you can run `air init` in your project's root directory to create a `.air.toml` file containing configuration.


If you have your `main` package and function in the root of your project, it will build and run your project straight away, but the default configuration isn't configured to watch for changes to `*.templ` files or run `templ generate`. It's also important to ignore `.*_templ.go` files or it will end up in an infinite loop of changes.


To make these changes, change the `cmd` field to add the `templ generate` command.


cmd = "templ generate && go build -o ./tmp/main ."

Then, update the `exclude_regex` field to ignore `.*_templ.go` files:


exclude_regex = [".*_templ.go"]

Finally, update the `include_ext` field to include the `templ` extension:


include_ext = ["go", "tpl", "tmpl", "templ", "html"]

Now you're free to run `air` at the command line. When you make changes the build will be executed and your web server can start up again.


Asciinema demo


Putting it together


In total, the configuration is as below:


root = "."
tmp_dir = "tmp"

[build]
  bin = "./tmp/main"
  cmd = "templ generate && go build -o ./tmp/main ."
  delay = 1000
  exclude_dir = ["assets", "tmp", "vendor"]
  exclude_file = []
  exclude_regex = [".*_templ.go"]
  exclude_unchanged = false
  follow_symlink = false
  full_bin = ""
  include_dir = []
  include_ext = ["go", "tpl", "tmpl", "templ", "html"]
  kill_delay = "0s"
  log = "build-errors.log"
  send_interrupt = false
  stop_on_error = true

[color]
  app = ""
  build = "yellow"
  main = "magenta"
  runner = "green"
  watcher = "cyan"

[log]
  time = false

[misc]
  clean_on_exit = false

MacOS tip


If you're on a Mac, when you run a Go web server, it might pop up a warning:


> Do you want the application "main" to accept incoming network connections?


That makes hot reload impossibly annoying, but it can be worked around.


If you've got `http.ListenAndServe(":8000")`, update it to `http.ListenAndServe("localhost:8000")` when you're running it on your local machine and MacOS won't put up the warning.


Just be aware that you'll need to set it back if you want the server to accept incoming requests from outside your local computer.


Nix users


There's no package for `air` at the moment in the Nix packages repo, but it's relatively easy to add Go packages. Add this to `air.nix` and you can import it from your home manager or nix-darwin setup with `air = pkgs.callPackage ./air.nix {};`


{ lib, buildGoModule, fetchFromGitHub }:

buildGoModule rec {
  pname = "air";
  version = "1.27.3";

  src = fetchFromGitHub {
    owner = "cosmtrek";
    repo = "air";
    rev = "v${version}";
    # Calculated by downloading the code and running nix-hash --type sha256 .
    sha256 = "04xdgimbkg7kkngpfkxm7v0i3fbv3xfzvc96lafs05pn58zxrva0";
  };

  vendorSha256 = "1gnlx9rzp6vzjl7vivianhkr1c615iwvng2gfpsp6nz2b1821c07";

  meta = with lib; {
    description = "Yet another live-reloading command line utility for Go applications in development";
    homepage = https://github.com/cosmtrek/air;
    license = licenses.mit;
    maintainers = with maintainers; [ cosmtrek ];
    platforms = platforms.linux ++ platforms.darwin;
  };

More


Next


Building a Hotwired web app with Go and Templ


Previous


Thoughts on team metrics


Home


home

-- Response ended

-- Page fetched on Sat Apr 27 23:54:42 2024