Framework Packages
Andurel v2 is a project generator plus independently versioned Go modules under pkg/*. The generated application is not a thin wrapper around a hidden runtime: it owns its composition root, environment names, domain code, routes, controllers, models, and views. Framework packages provide reusable infrastructure at those boundaries.
Package map
| Module | Responsibility | Deep dive |
|---|---|---|
pkg/storage |
PostgreSQL via pgx, narsilc-friendly Connection, transactions, migrations, test databases, and River clients |
Getting Started |
pkg/inertia |
Echo-native Inertia v3 protocol, Vite assets, props, redirects, flash, and SSR | Inertia |
pkg/hypermedia |
Templ rendering and Datastar/SSE response helpers | Templ & Datastar |
pkg/routing |
Typed URL construction shared by Go and generated TypeScript | Routing |
pkg/server |
Bounded HTTP server construction and graceful shutdown | HTTP Server |
pkg/email |
Transport-neutral email payloads, validation, retry classification, and Mailpit | |
pkg/validation |
Structured field errors and composable validation rules | Validation |
pkg/telemetry |
OpenTelemetry helpers for application processes | Telemetry |
pkg/kiks |
Cookie jars, bagged sessions, and flash middleware | Cookies & Sessions |
The packages expose ordinary Go constructors rather than an Andurel service locator. Fx belongs to the generated application and connects constructors and process lifecycles.
Composition and process boundaries
The web process normally follows this graph:
1config constructors
2 -> storage.Postgres + queue insertion
3 -> models and services
4 -> inertia.Renderer controllers or Templ/hypermedia controllers
5 -> Echo router
6 -> server.Server
Inertia projects also run a separate Node owner in cmd/ssr for production SSR. The queue process has its own graph: the same storage connection, a queue processor, registered River workers, telemetry, and email transports, but no HTTP server. Configuration types preserve that separation: insertion and worker settings are distinct even though both eventually contain storage.QueueConfig.
Configuration boundary
Package configuration types contain operational policy and validation. They do not choose environment-variable names. For example, storage.DefaultConfig() supplies pool defaults, while generated config.NewDatabase() maps DB_* values onto the type and validates the result.
This means packages work without Fx or environment variables, applications can adopt another configuration source without forking the framework, and a package update cannot silently introduce a new environment contract. See Configuration for the generated mappings.
Versioning and upgrades
Each package has its own module, semantic version, and changelog. Versions may differ from one another and from the CLI release. go.mod is the source of truth for code dependencies; andurel.toml / andurel.lock record scaffold choices and pinned tools used to maintain the project.
1andurel packages list
2andurel packages update
Updating the CLI does not rewrite existing imports. Update packages deliberately, read each changelog, compile generated code, and test the owning process. Storage changes require database, transaction, migration, queue-insertion, and worker coverage. Inertia changes require initial HTML, client visits, partial reloads, redirects, validation, Vite development, production assets, and the configured SSR client plus cmd/ssr.
Extending and replacing implementations
Depend on the smallest public interface available. Models normally accept storage.Connection, services accept email sender interfaces, and only Inertia controllers accept *inertia.Renderer. Application-specific adapters stay in the application.
Replace implementations at the composition root: tests can provide fake senders, a deployment can install a custom email transport, and a non-Fx program can construct storage directly. Importing implementation details throughout the application defeats these boundaries and makes independent upgrades harder.