Skip to content

Server & Registry

Server

The Server is the main entry point for the framework. It holds the app registry and orchestrates the boot sequence.

Creating a Server

srv := burrow.NewServer(
    session.New(),
    auth.New(),
    healthcheck.New(),
    myApp,
)

Apps are automatically sorted by their HasDependencies declarations — you can list them in any order.

Methods

NewServer

func NewServer(apps ...App) *Server

Creates a server and registers all given apps in order.

SetLayout

func (s *Server) SetLayout(fn LayoutFunc)

Configures the app layout function. Call before Run().

Registry

func (s *Server) Registry() *Registry

Returns the server's app registry for direct access.

Flags

func (s *Server) Flags(configSource func(key string) cli.ValueSource) []cli.Flag

Returns all CLI flags: core framework flags merged with flags from all Configurable apps. Pass a config source function to enable TOML file sourcing, or nil for CLI+ENV only.

Run

func (s *Server) Run(ctx context.Context, cmd *cli.Command) error

Boots and starts the server. This is a cli.ActionFunc — pass it directly to cli.Command.Action.

Boot Sequence

When Run() is called, the following happens in order:

  1. Parse config — reads CLI flags, env vars, and TOML into a Config struct
  2. Open database — connects to SQLite with WAL mode, foreign keys, and connection pool
  3. Run migrations — calls RunAppMigrations for every Migratable app
  4. Register apps — calls Register() on each app with the shared AppConfig
  5. Seed database — calls Seed() on each Seedable app
  6. Configure apps — calls Configure() on each Configurable app
  7. Build templates — collects .html files from all HasTemplates apps and template functions from all HasFuncMap apps, parses them into a single global *template.Template
  8. Create router — sets up Chi with core middleware (request logger, request ID, gzip, body limit)
  9. Inject context — injects nav items (from HasNavItems), layout, and template executor into the request context via middleware
  10. Register middleware — applies middleware from all HasMiddleware apps (including request-scoped HasRequestFuncMap injection)
  11. Register routes — calls Routes() on all HasRoutes apps
  12. Start HTTP server — listens on the configured address with graceful shutdown and zero-downtime restart via SIGHUP (see Deployment Guide)

Logging

The framework uses slog.Default() for all logging. Configure your preferred logger (text, JSON, tint, etc.) by calling slog.SetDefault() before starting the server.

Registry

The Registry manages registered apps and provides access to their capabilities.

Methods

Add

func (r *Registry) Add(app App)

Registers an app. Panics on duplicate names or missing dependencies.

Get

func (r *Registry) Get(name string) (App, bool)

Returns the app with the given name, or false if not found. Use with type assertions to access app-specific methods.

Apps

func (r *Registry) Apps() []App

Returns all registered apps in registration order.

RunMigrations

func (r *Registry) RunMigrations(ctx context.Context, db *bun.DB) error

Runs migrations for all Migratable apps.

AllNavItems

func (r *Registry) AllNavItems() []NavItem

Collects and sorts nav items from all HasNavItems apps by position.

RegisterMiddleware

func (r *Registry) RegisterMiddleware(router chi.Router)

Applies middleware from all HasMiddleware apps to the router.

RegisterRoutes

func (r *Registry) RegisterRoutes(router chi.Router)

Calls Routes() on all HasRoutes apps.

AllFlags

func (r *Registry) AllFlags(configSource func(key string) cli.ValueSource) []cli.Flag

Collects CLI flags from all Configurable apps. Pass nil for CLI+ENV only.

Configure

func (r *Registry) Configure(cmd *cli.Command) error

Calls Configure() on each Configurable app.

AllCLICommands

func (r *Registry) AllCLICommands() []*cli.Command

Collects CLI subcommands from all HasCLICommands apps.

Seed

func (r *Registry) Seed(ctx context.Context) error

Calls Seed() on each Seedable app in order.

RenderTemplate

func RenderTemplate(w http.ResponseWriter, r *http.Request, statusCode int, name string, data map[string]any) error

Renders a named template into the HTTP response. If the request has an HX-Request header (htmx), the fragment is returned directly. Otherwise, it is wrapped in the layout function from context (if set).