Skip to main content
Version: 1.17.0

Application container

pkg/app is where a Nucleus application is assembled. One call wires every subsystem — configuration, logging, databases, sessions, mail, routing — and returns a validated application ready to run.

Read this page when you need programmatic control over startup: building an app inside a test, embedding one in a larger binary, or replacing the default subsystems with your own.

import "github.com/jcsvwinston/nucleus/pkg/app"

cfg, err := app.LoadConfig("nucleus.yml")
if err != nil {
return err
}

a, err := app.New(cfg)
if err != nil {
return err
}
defer a.Shutdown(ctx)

return a.Run(ctx)

What app.New wires​

Called with no options, app.New(cfg) initialises:

  • the canonical configuration view
  • the slog logger (pkg/observe)
  • the SQL database map by alias — database_default plus databases.<alias>
  • the mail sender (pkg/mail)
  • the session manager (pkg/auth), backed by the configured store (memory, sql or redis)
  • the HTTP router and middleware chain (pkg/router)
  • the request scope resolver, for multi-site and multi-tenant setups
  • the model registry (pkg/model)

This is the default, full-stack mode, and it matches what the mvc scaffold template produces. The admin panel (orbit) is a separate module you mount with .Mount(orbit.Module(...)); it is not part of the default wiring.

Core-only mode​

Pass app.WithoutDefaults() to opt out of the default subsystems and wire only what you need:

a, err := app.New(cfg, app.WithoutDefaults())

This is the path the api template uses. From here you attach the subsystems you actually want using extensions.

Extensions​

Extensions are first-class pluggable subsystems:

type Extension interface {
Name() string
Attach(a *App) error
Shutdown(ctx context.Context) error
}
a, err := app.New(cfg,
app.WithoutDefaults(),
app.WithExtensions(myExtension),
)

Attach runs at startup and can register routes, middleware, models, and shutdown hooks on the application. Shutdown runs during graceful shutdown, in reverse attach order.

What App exposes​

MemberPurpose
App.DBThe default database handle.
App.DBsAll opened databases keyed by alias.
App.Database(alias)Look up a specific database.
App.DatabaseForRequest(r)Resolve the database for the current request scope (multi-site / multi-tenant).
App.RouterThe mounted router.
App.ModelsThe model registry.
App.Run(ctx) / App.Shutdown(ctx)Lifecycle entry points.

Lifecycle​

App.Run blocks. It listens, serves traffic, and — when the context is cancelled — runs each registered shutdown hook in reverse attach order before returning. server.shutdown_timeout in nucleus.yml bounds the graceful timeout.

There are no hidden globals. App registers no singleton, so each app.New call produces an independent application. That is what makes end-to-end testing straightforward: run a real App on a random port and tear it down when the test finishes.