A web framework for Go developers who want something like Django, Rails, or Flask — but with the deployment simplicity of a single static binary.
Most Go web development follows the "API backend + SPA frontend" pattern. Burrow takes a different approach: server-rendered HTML with templates, modular apps with their own routes and middleware, and a document database that just works. Deploy with embedded SQLite as a single binary, or connect to PostgreSQL for scale — same code, same API.
Built on Chi, Den (ODM with SQLite and PostgreSQL backends), and Go's standard html/template. Ideal for self-hosted applications, internal tools, or any project where "download, start, use" is the goal.
Tip
Why Burrow? A burrow is a network of interconnected chambers — each with its own purpose, yet part of a larger whole. That's exactly how the framework works: pluggable apps are the rooms, and your gophers live in them.
Note
Burrow is designed for server-rendered web applications, not API-only services. If you're building a JSON API with a separate frontend, a lighter router like Chi on its own is probably a better fit.
- App-based architecture — build your application from composable, self-contained apps
- SQLite or PostgreSQL — embedded SQLite (pure Go, no CGO) for single-binary deploys, or PostgreSQL for scale — switch with one flag
- Automatic schema — document types declared in code, tables and indexes created on startup
- Standard templates — Go's
html/templatewith a global template set, per-app FuncMaps, and automatic layout wrapping - Tailwind v4 by default —
contrib/admin,contrib/auth, andcontrib/jobsship Tailwind v4 templates out of the box, and the bundledburrow tailwindsub-command auto-discovers every contrib's template directory so utility scanning Just Works. Prefer a different stack? Bring your own CSS and override the contrib templates viahtml/template's last-define-wins — Burrow's core itself ships no CSS. - Layout system — app layout via server, admin layout via admin package
- CLI configuration — flags, environment variables, and TOML config via urfave/cli
- CSRF protection — automatic token generation and validation
- Flash messages — session-based flash message system
- htmx-first interactivity —
contrib/htmxships the vendored JS plus response helpers (OpenDialog,SmartRedirect, etc.) so SSR pages get partial swaps and modals without a JS framework. Dark mode followsprefers-color-scheme. - Contrib apps — auth (WebAuthn/passkeys), sessions, i18n, admin, CSRF, flash messages, jobs, uploads, rate limiting, healthcheck, static files, API docs (Scalar)
The fastest path is the bundled burrow CLI, which scaffolds a project with the contrib stack, Tailwind v4, live reload, CI, and goreleaser config already wired:
go install github.com/oliverandrich/burrow/cmd/burrow@latest
burrow new myapp --module github.com/you/myapp
cd myapp && mise run setup && mise run devWithout mise, the scaffold prints a go mod tidy && go run ./cmd/myapp fallback.
Or build from scratch:
mkdir myapp && cd myapp
go mod init myapp
go get github.com/oliverandrich/burrow@latestpackage main
import (
"context"
"log"
"net/http"
"os"
"github.com/oliverandrich/burrow"
"github.com/go-chi/chi/v5"
"github.com/urfave/cli/v3"
)
// homeApp is a minimal app with a single route.
type homeApp struct{}
func (a *homeApp) Name() string { return "home" }
func (a *homeApp) Routes(r chi.Router) {
r.Method("GET", "/", burrow.Handle(func(w http.ResponseWriter, r *http.Request) error {
return burrow.Text(w, http.StatusOK, "Hello from Burrow!")
}))
}
func main() {
srv := burrow.NewServer(
&homeApp{},
)
cmd := &cli.Command{
Name: "myapp",
Flags: srv.Flags(nil),
Action: srv.Run,
}
if err := cmd.Run(context.Background(), os.Args); err != nil {
log.Fatal(err)
}
}go mod tidy
go run .See example/hello/ for a minimal hello world app, or example/notes/ for a complete example with auth, admin, i18n, and more.
contrib/ Reusable apps
admin/ Admin panel coordinator (top-nav layout, dashboard cards, route mounting)
apidocs/ Vendored Scalar OpenAPI documentation UI
auth/ WebAuthn passkeys, recovery codes, email verification
authmail/ Pluggable email renderer + SMTP implementation
csrf/ CSRF protection
healthcheck/ Liveness and readiness probes
htmx/ htmx static asset + request/response helpers
i18n/ Locale detection and translations
jobs/ Den-backed background job queue (SQLite + Postgres)
messages/ Flash messages
ratelimit/ Per-client rate limiting
session/ Cookie-based sessions
staticfiles/ Static file serving with content-hashed URLs
uploads/ File upload storage and serving
example/ Example applications (hello world, notes app)
Every app implements burrow.App:
type App interface {
Name() string
}Apps can optionally implement additional interfaces:
| Interface | Purpose |
|---|---|
HasDocuments |
Register Den document types |
HasRoutes |
Register HTTP routes |
HasMiddleware |
Contribute middleware |
HasNavItems |
Contribute navigation items |
HasTemplates |
Contribute .html template files |
HasFuncMap |
Contribute static template functions |
HasRequestFuncMap |
Contribute request-scoped template functions |
Configurable |
Define CLI flags and read configuration |
HasCLICommands |
Contribute CLI subcommands |
Seedable |
Seed the database with initial data |
HasAdmin |
Contribute admin panel routes and nav items |
HasStaticFiles |
Contribute embedded static file assets |
HasTranslations |
Contribute translation files |
HasDependencies |
Declare required apps |
HasJobs |
Register background job handlers |
PostConfigurable |
Second-pass configuration after all apps are configured |
HasShutdown |
Clean up on graceful shutdown |
Layouts are template name strings. The app layout wraps user-facing pages:
srv.SetLayout("myapp/layout")The admin layout is owned by the admin package:
admin.New(admin.WithLayout("custom/admin-layout"))RenderTemplate renders page content, then wraps it in the layout template with .Content set to the rendered fragment. Layout templates access dynamic data via template functions:
{{ range navLinks }}...{{ end }} {{/* filtered nav with active state */}}
{{ if currentUser }}...{{ end }} {{/* authenticated user */}}
{{ csrfToken }} {{/* CSRF token for forms */}}Configuration is resolved in order: CLI flags > environment variables > TOML file.
Core flags include --host, --port, --database-dsn, --log-level, --log-format, --tls-mode, and more. Apps can contribute their own flags via the Configurable interface.
Apps declare their document types by implementing HasDocuments:
func (a *App) Documents() []document.Document {
return []document.Document{&Poll{}, &Choice{}}
}Tables and indexes are created automatically on startup via Den's Register(). No SQL migration files needed.
Burrow uses mise for tool-version pinning and task running. After cloning:
mise install # Install pinned Go + dev tools
mise run setup # Verify the environment + install pre-commit git hooksCommon tasks:
mise run test # Run all tests
mise run lint # Run golangci-lint
mise run fmt # Format code
mise run coverage # Generate coverage report
mise run tidy # Tidy module dependencies
mise run example-hello # Run the hello world example
mise run example-notes # Run the notes example application
mise tasks # List every available taskFull documentation is available in the docs/ directory.
Burrow is licensed under the MIT License.
The Go Gopher was originally designed by Renee French and is licensed under CC BY 4.0.
Third-party licenses are listed in THIRD_PARTY_LICENSES.md.
