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, migrations, and middleware, and an embedded SQLite database. The result is an application you can deploy as a single file — ./myapp and you're done.
Built on Chi, Bun/SQLite, 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
- Pure Go SQLite — no CGO required (
CGO_ENABLED=0), cross-compiles anywhere - Per-app migrations — each app manages its own SQL migrations
- Standard templates — Go's
html/templatewith a global template set, per-app FuncMaps, and automatic layout wrapping - CSS-agnostic — bring your own CSS framework (Bootstrap, Tailwind, etc.)
- 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
- Bootstrap integration — Bootstrap 5 CSS/JS, inline SVG icons, htmx, and dark mode theme switcher
- Contrib apps — auth (WebAuthn/passkeys), sessions, i18n, admin, CSRF, flash messages, jobs, uploads, rate limiting, healthcheck, static files
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) Register(_ *burrow.AppConfig) error { return nil }
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 + ModelAdmin
auth/ WebAuthn passkeys, recovery codes, email verification
authmail/ Pluggable email renderer + SMTP implementation
bootstrap/ Bootstrap 5 CSS/JS/htmx assets, theme switcher, layout
bsicons/ Bootstrap Icons as inline SVG template functions
csrf/ CSRF protection
healthcheck/ Liveness and readiness probes
htmx/ htmx static asset + request/response helpers
i18n/ Locale detection and translations
jobs/ SQLite-backed background job queue
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
Register(cfg *AppConfig) error
}Apps can optionally implement additional interfaces:
| Interface | Purpose |
|---|---|
Migratable |
Provide embedded SQL migrations |
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 embed their SQL migrations and implement Migratable:
//go:embed migrations
var migrationFS embed.FS
func (a *App) MigrationFS() fs.FS {
sub, _ := fs.Sub(migrationFS, "migrations")
return sub
}Migrations are tracked per-app in the _migrations table and run automatically on startup.
just setup # Check that all required dev tools are installed
just test # Run all tests
just lint # Run golangci-lint
just fmt # Format code
just coverage # Generate coverage report
just tidy # Tidy module dependencies
just example-hello # Run the hello world example
just example-notes # Run the notes example applicationRequires Go 1.25+. Run just setup to verify your dev environment.
Full documentation is available in the docs/ directory.
Burrow is licensed under the European Union Public Licence v1.2 (EUPL-1.2). You can build any kind of software on top of Burrow — commercial, proprietary, or open source — without having to open-source your application code. See the licensing guide for details on what the EUPL means for you.
Third-party licenses are listed in THIRD_PARTY_LICENSES.md.
