HAMR
v0.9.1 preview - useful now, still getting sanded down

A practical Go stack
for server-rendered apps.

HAMR bundles the pieces most Go web apps end up wiring together anyway: Templ, HTMX, session auth, CSRF, migrations, a dev server, and a project shape that stays readable once the app grows.

It is opinionated on purpose: one codebase, one binary, HTML first, JSON where it helps. If that is how you already like to build, HAMR saves you a lot of setup work.

terminal
# Install the CLI
$ go install github.com/FyrmForge/hamr/cmd/hamr@latest

# Scaffold a new project
$ hamr new myapp
$ cd myapp

# Start the dev server (file watching, hot reload, builds)
$ hamr dev

What HAMR actually covers.

Not a giant abstraction layer. Just the parts teams keep rebuilding from scratch.

One handler, two clients

Return HTML to the browser and JSON to an API client from the same handler. HTMX stays simple instead of spawning a second controller layer.

Templates that compile

Templ turns views into Go code. You find broken markup at build time instead of after deploying a typo in a string template.

HTML-first interactivity

HTMX and Alpine are there for the places where a little client-side state helps. The default path is still HTML over HTTP.

Sessions, auth, and CSRF

Cookie sessions, Argon2id hashing, CSRF, and a subject loader that works with your own user model.

Short dev loop

hamr dev handles templ generation, rebuilds, reloads, and Docker services so you can stay in one terminal instead of five.

Database work included

Postgres setup, migrations, retries, and a repo layer are already wired so your first real feature can talk to data.

SAME HANDLER. DIFFERENT RESPONSE.

Return HTML to browsers
and JSON to clients.

You should not have to choose between a "web handler" and an "API handler" for the same piece of application logic. HAMR keeps that branch close to the response instead of splitting your app in two.

See the response helpers
internal/web/handler/books/handler.go
func (h *handler) List(c echo.Context) error {
    books, err := h.repo.All(c.Request().Context())
    if err != nil {
        return respond.Error(c, err)
    }

    // HTMX or browser → renders the Templ component
    // API client      → returns JSON
    return respond.HTML(c, http.StatusOK,
        templates.BookList(books))
}

The tradeoffs are explicit.

01

Start with one codebase

Most apps do not need microservices on day one. HAMR is built for the part where you are trying to ship something useful.

02

HTML is the default transport

The browser gets HTML first. JSON is there when another client actually needs it. The same handler can do both.

03

Your data model stays yours

HAMR works with your IDs and your user model. It does not try to own the center of your app.

04

Generated code should stay readable

Scaffolding is fine. Hidden runtime magic is not. You should be able to open generated code and understand it.

05

Defaults should survive production

Cookies, CSRF, password hashing, CSP, structured logs, and migrations should not be an afterthought you bolt on later.

06

Narrow on purpose

If you want a SPA starter kit or a giant extension marketplace, HAMR will probably feel restrictive. That is part of the design.

If this matches how you like to build

Start with the docs, then build the bookmark app. You will know pretty quickly whether the constraints feel helpful.