If Goldr saves you time, please consider starring ⭐ the repository - it helps more developers find it.
Goldr is a server-first, HTML-first, HTMX-native Go framework for web applications that stay easy to inspect and change as they grow.
The filesystem is the route map, .templ files own HTML, HTMX stays visible in
markup, and handlers remain ordinary Go. Goldr generates the repetitive route
dispatch and URL helpers around that source. Your application still owns its
net/http server, middleware, auth, sessions, validation, data access, static
handlers, asset tools, and deployment.
Goldr is v0. APIs and conventions may change before v1.
Go and HTMX make a small application easy to start. As the application grows, teams rebuild the same support layer: filesystem routes, nested layouts, route-safe URLs, generated-output checks, asset fingerprints, live reload, and inspection commands.
Goldr provides that layer without moving the application out of Go. A route directory owns the page, layout state, HTMX fragments, mutation actions, and templates for one local workflow. You can inspect the application surface from the directory tree instead of chasing runtime registration, copied path strings, or hidden client state.
From a Goldr checkout, run the full-feature example:
(cd examples/full_feature && go run .)Then inspect its route surface and generated assets:
(cd examples/full_feature && go tool goldr routes list)
(cd examples/full_feature && go tool goldr routes layouts)
(cd examples/full_feature && go tool goldr routes refs)
(cd examples/full_feature && go tool goldr assets list)
(cd examples/full_feature && go tool goldr check)The example includes pages, nested layouts, HTMX fragments, POST actions, forms, generated URL helpers, custom errors, middleware, request parsing, CSRF, route-rendered error pages, and fingerprinted static assets.
Use Go 1.26 or newer. Goldr applications use templ for HTML rendering and keep both CLI tools pinned in the application module.
Create a module and install Goldr, templ, and their app-local tools:
mkdir hello-goldr
cd hello-goldr
go mod init example.com/hello-goldr
GOLDR_VERSION=v0.1.3
TEMPL_VERSION=v0.3.1020
go get github.com/mobiletoly/goldr@${GOLDR_VERSION} github.com/a-h/templ@${TEMPL_VERSION}
go get -tool github.com/mobiletoly/goldr/cmd/goldr@${GOLDR_VERSION}
go get -tool github.com/a-h/templ/cmd/templ@${TEMPL_VERSION}
go tool -n goldr
go tool -n templUse the same Goldr version for the runtime library and the cmd/goldr tool.
Running tools through go tool keeps their versions with the application.
Create the starter route tree:
go tool goldr initThe command creates:
app/
routes/
route.go app-owned route declaration and page handler
page.templ app-owned page HTML
layout.go app-owned layout logic
layout.templ app-owned document HTML
goldr_gen.go generated route dispatch
urls/
goldr_gen.go generated URL helpers
internal/goldrinspect/
goldr_gen.go generated inspection support
Edit the four app-owned files. Regenerate the three Goldr-owned files instead of editing them.
The root route.go declares one page:
package routes
import (
"net/http"
"github.com/mobiletoly/goldr"
)
var Route = goldr.RouteDef{
Page: page,
}
func page(_ *http.Request) goldr.PageRouteResponse {
return goldr.NewPage(
PageView(),
goldr.PageMetadata{
Title: "Hello Goldr",
},
)
}Route is generation input. Goldr reads this package-level static declaration
without running the application. Because the declaration lives at the root of
app/routes, it owns /. Page: page selects the ordinary Go function that
handles GET and HEAD requests for that path.
The handler returns a page response containing a templ component and metadata.
page.templ owns the component's HTML:
package routes
templ PageView() {
<section>
<h1>Hello Goldr</h1>
<p>Edit app/routes/page.templ to start building.</p>
</section>
}The root layout wraps this page and every descendant page. ctx.Child is the
matched page or inner layout component, and ctx.Metadata comes from the
matched page response:
package routes
import (
"net/http"
"github.com/a-h/templ"
"github.com/mobiletoly/goldr"
)
const defaultTitle = "Hello Goldr"
func Layout(_ *http.Request, ctx goldr.LayoutContext) templ.Component {
return LayoutView(ctx.Metadata, ctx.Child)
}
func pageTitle(metadata goldr.PageMetadata) string {
if metadata.Title != "" {
return metadata.Title
}
return defaultTitle
}package routes
import "github.com/mobiletoly/goldr"
templ LayoutView(metadata goldr.PageMetadata, child templ.Component) {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>{ pageTitle(metadata) }</title>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-beta4" integrity="sha384-aWZK1NtOs/aWb/+YZdTM8q2JkWEshlMc9mgZ189numT9bwFhyAyYEoO4nO/2dTXt" crossorigin="anonymous" defer></script>
</head>
<body>
<main>
@child
</main>
</body>
</html>
}Add main.go. The application owns the server and mounts Goldr's generated
handler like any other http.Handler:
package main
import (
"log"
"net/http"
"example.com/hello-goldr/app/routes"
)
func main() {
mux := http.NewServeMux()
mux.Handle("/", routes.Handler())
log.Println("listening on http://127.0.0.1:8080")
log.Fatal(http.ListenAndServe("127.0.0.1:8080", mux))
}The request path is direct:
GET /
-> generated routes.Handler()
-> page()
-> goldr.NewPage(PageView(), metadata)
-> Layout(..., ctx.Child)
-> layout.templ renders @child
-> HTML response
Generate templ output and Goldr route wiring, tidy the module, inspect the route, validate generated files, and run the application:
go tool goldr generate
go mod tidy
go tool goldr routes list
go tool goldr check
go run .The route list connects the URL to its source and generated helper:
KIND METHOD PATH PARAMS SOURCE OWNER DECL NAME TITLE LABELS NAV TRAIL_KEYS HELPER
layout - / - layout.go - - - - - - - -
page GET,HEAD / - route.go - local - - - - - urls.Root.Path()
Open http://127.0.0.1:8080.
After route or template edits, run go tool goldr generate before
go tool goldr check. For live reload, use:
go tool goldr devRead Getting Started to build a two-page app by hand and inspect its dynamic route. Read Live Reload for asset and Tailwind workflows.
The filesystem is the route map:
app/routes/
layout.go -> layout logic for / and below
layout.templ -> layout HTML
route.go -> GET /
page.templ -> page HTML
users/
layout.go -> layout logic for /users and below
layout.templ -> users layout HTML
route.go -> GET /users, GET /users/table, POST /users/create
page.templ -> users page HTML
frag_table.templ -> fragment HTML
by_id/
route.go -> GET /users/{id}
page.templ -> user detail HTML
Each route directory declares its page, fragments, and actions in one static
Route value:
var Route = goldr.RouteDef{
Page: page,
Fragments: goldr.Fragments{
goldr.FragmentRoute("/table", table),
},
Actions: goldr.Actions{
goldr.Action(http.MethodPost, "/create", postCreate),
},
}The directory and declaration generate route-shaped URL helpers:
urls.Users.Path()
urls.Users.Table.Path()
urls.Users.Create.Path()
urls.Users.ByID.Bind(id).Path()HTMX remains visible at the call site. Templates use the generated fragment
path in ordinary hx-* attributes:
package users
import "example.com/hello-goldr/app/urls"
templ UsersView() {
<button
hx-get={ urls.Users.Table.Path() }
hx-target="#users-table"
hx-swap="innerHTML"
>
Refresh users
</button>
<div id="users-table"></div>
}Goldr uses Go-safe filesystem names. by_id/ maps to {id}, while a static
directory such as build_info/ maps to /build-info. Layouts wrap pages in
their directory and below. Fragments render standalone partials, and actions
return explicit route responses.
Goldr writes ordinary Go dispatch to app/routes/goldr_gen.go and URL helpers
to app/urls/goldr_gen.go; it does not assemble a route registry at runtime.
Read Routes for dynamic segments, route-local workflows,
mounted routes, and the complete route contract.
- A route tree you can read:
app/routesis the URL map, with Go-safe names and colocated source. - Route-local pages, fragments, and actions declared in
route.go. - Nested layouts that compose without a second routing or template tree.
- Generated paths for links, forms, redirects, HTMX attributes, and response headers.
- Visible browser behavior through normal
hx-*attributes.
goldr devruns templ generation, Goldr route generation, asset fingerprinting, app restart, and browser reload.goldr generaterefreshes route wiring, URL helpers, templ output, and fingerprinted assets.goldr checkverifies generated routes, templ output, and managed assets without writing files.
- Put final browser-ready files in
assets/build; Goldr writes fingerprinted files toassets/dist, generates paths such asassets.Path("app.css"), and exposes an embeddedassets.FS()for your static handler. - Use
goldr check,go tool goldr assets check, andgo tool goldr assets listto inspect packaged resource state. - Keep CSS compilation, JavaScript bundling, static serving, cache policy, and deployment in application-owned tools and code.
routes list,routes explain, androutes layoutsexpose route paths, handlers, and layout stacks.routes refsinventories direct HTMX references in.templfiles.- The visual inspector outlines the layouts, pages, fragments, and labeled components that produced each page region.
For a bounded rich-client escape hatch, see examples/react_island and
examples/svelte_island. Goldr owns pages and navigation while React or Svelte
owns one explicit editor subtree. Read
Client Islands for the lifecycle contract.
Run the Kit route example to see one shared implementation subtree mounted
under /admin/reports and /user/reports:
(cd examples/kit_routes && go run .)Run the chat example for app-owned realtime behavior with server-sent events:
(cd examples/chat && go run .)- User Documentation - the complete documentation index.
- Getting Started - build a two-page app by hand and inspect its dynamic route.
- Concepts - pages, layouts, fragments, actions, generated handlers, and URL helpers.
- CLI - app-local
go tool goldrcommands. - Routes - filesystem conventions and runtime behavior.
- Mounted Kit Route Subtrees - reusable non-live route surfaces mounted by filesystem-owned routes.
- Navigation Trails - contextual trails, breadcrumb-style rendering, and app-level Back links.
- Client Islands - bounded React or Svelte components inside Goldr pages.
- HTMX - visible
hx-*attributes and response headers. - Error Handling - route errors, custom hooks, full-page errors, and HTMX error fragments.
- Assets - fingerprinted files, cache headers, and app-owned asset tooling.
- SSE - app-owned streams, event IDs, and named SSE swaps.
- CSRF - signed-cookie tokens for unsafe requests.
- Composition - mux, middleware, static assets, and app-owned server behavior.
- Application Dependencies - app-owned typed dependencies for generated route packages.
- Live Reload -
goldr dev, browser reload, assets, and Tailwind workflows. - Template Inspection - render-unit comments and visible browser overlays.
- Coding Agents - guidance for agents working on Goldr applications.
Goldr is licensed under the Apache License 2.0.