Search documentation

Find a page in the Andurel docs.

Framework Packages

Andurel v2 is a project generator plus seven independently versioned Go modules. 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, Bun/sqlc interop, transactions, migrations, test databases, and River clients Storage
pkg/inertia Echo-native Inertia v3 protocol, Vite assets, props, redirects, flash, and SSR Inertia
pkg/hypermedia Templ rendering and Datastar/SSE response helpers Hypermedia
pkg/routing Typed URL construction shared by Go and generated TypeScript Routing Package
pkg/server Bounded HTTP server construction and graceful shutdown Server
pkg/email Transport-neutral email payloads, validation, retry classification, and Mailpit Email Package
pkg/validation Structured field errors and composable validation rules Validation

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    -> Templ controllers or inertia.Renderer controllers
5    -> Echo router
6    -> server.Server

The queue process has a separate graph. It constructs 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.lock records the framework version, scaffold choices, extensions, and tools used to maintain the project.

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.