avero

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: MIT Imports: 24 Imported by: 0

README

Avero

Avero is an application host for Go services. It owns the composition root, the lifecycle, the configuration, the telemetry and the routing. It does not own the semantics of your application.

Avero is not a web framework. It writes plain Go that you can read, change and delete.

Start

go install github.com/alternayte/avero/cmd/avero@latest

avero new blog
cd blog
cp .env.example .env
avero migrate up
avero dev

The application answers on http://localhost:8080. A change to a .css file reaches the browser in about 40 milliseconds. A change to a .go file reaches it in under two seconds.

You need Go, and a database when you leave SQLite. You need no Node.js.

What you get

  • One command writes an application that builds, runs and passes its tests.
  • Typed handlers with generated binding and validation. No reflection runs on a request path.
  • A module contract, so one directory holds one feature.
  • Server rendered pages with templ, and forms with CSRF, flash messages and validation.
  • An asset pipeline with esbuild and the Tailwind standalone binary, and no Node.js for the ssr shape.
  • A TypeScript front end for the spa shape, built by Vite and carried by the binary, with the migrations beside it.
  • Datastar and htmx, as optional imports.
  • An HTTP client generator with timeouts, retries, a circuit breaker and OTel spans.
  • A development loop that swaps a stylesheet with no reload and morphs the page after a rebuild.
  • An MCP server, so an agent reads the routes, the modules and the models, and writes a new slice.
  • An OpenAPI 3.1 description that avero routes --openapi reads from the code, and a typed front end client that the spa shape generates from it.
  • AGENTS.md and four skills in the Agent Skills format, which a coding agent reads with no setting.

The commands

avero new <name>      write a new application
avero slice <name>    write a new feature slice
avero dev             run the application and rebuild it on each change
avero generate        write the generated files
avero build           generate, build the assets and compile the binary
avero migrate         write and apply the migrations
avero routes          print the routes, or the OpenAPI description
avero modules         print the contribution of each module
avero schema          print the models
avero doctor          prove the configuration and the database
avero verify          run the gate
avero mcp             serve the agent surface over stdio
avero js pin <pkg>    fetch a bundled module into the vendor directory
avero assets init     write the package.json of tier 1

The shapes

Shape Application Exercises
ssr a blog with posts the router, the views, the forms and the assets
spa a task board in TypeScript with React, TanStack Query and Vite the JSON routes and the embedded front end
api an order service the JSON service and the generated client

examples/ holds one application of each shape. The gate writes them again and compares them, so they never drift from avero new.

An example ignores its output directory, as every application does, so a clone holds no built asset. Write the starter assets one time:

go run ./internal/cmd/averoexamples -assets
cd examples/blog && go run .

The state of the subsystems

ID Subsystem State
S1 Configuration ready
S2 Host and lifecycle ready
S3 Telemetry ready
S4 Router and request context ready
S5 Handler codegen ready
S6 Module system ready
S7 Outbox relay planned
S8 Inbox consumer planned
S9 Event sourcing planned
S10 View layer ready
S11 Asset pipeline ready
S12 Hypermedia adapters ready
S13 Client codegen ready
S14 CLI and scaffolder ready
S15 Dev loop ready
S16 Agent surface ready

An application that publishes a message with an exactly-once effect waits for S7, S8 and S9. Every other shape works today.

The documents

The gate

just verify

The gate runs gofmt, go vet, golangci-lint, the tests with the race detector, the integration tests, the regeneration check, the three reference applications, and the development experience budgets.

Licence

MIT. See LICENSE.

Documentation

Overview

Package avero is the name that an application writes.

It holds aliases and thin wrappers for the subsystem packages. It holds no logic and no state, so it is not a facade: it hides nothing and it adds no behaviour. Read the subsystem package for the contract of a name.

config   the configuration loader and the report, S1
host     the lifecycle, the readiness gate and the boot checks, S2
router   the routes, the request context and the middleware, S4
module   the module contract and the module inspection, S6
view     the helpers of a server rendered page, S10
assets   the asset pipeline and the manifest, S11

The hypermedia adapters, ds and htmx, are optional imports. This package holds no alias for them, so an application that needs neither carries neither. See the SDD, S12.

telemetry the traces, the metrics and the logger, S3

An application can import a subsystem directly. The two forms are the same types.

Index

Constants

View Source
const (
	SourceEnv     = config.SourceEnv
	SourceDefault = config.SourceDefault
	SourceAbsent  = config.SourceAbsent
)

The sources that a report names.

View Source
const (
	ToastInfo    = router.ToastInfo
	ToastSuccess = router.ToastSuccess
	ToastWarning = router.ToastWarning
	ToastError   = router.ToastError
	// StatusCSRF is the status of a CSRF fault.
	StatusCSRF = router.StatusCSRF
)

The toast levels and the CSRF status.

View Source
const InspectPrefix = "avero:"

InspectPrefix marks a command that the avero binary sends to the application. The CLI runs `go run . avero:routes`, because the routes and the modules of an application live in its own code. See the SDD, S14.

View Source
const Redacted = config.Redacted

Redacted replaces the value of a secret field wherever Avero prints it.

Variables

This section is empty.

Functions

func AssetHandler

func AssetHandler(fsys fs.FS, m *Manifest) http.Handler

AssetHandler serves the built assets of a manifest. See assets.Handler.

r.Mount("/assets/", avero.AssetHandler(dist, m))

func Attr

func Attr(key string, value any) attribute.KeyValue

Attr builds a span attribute. A Secret reads as ******** and never reaches an exporter. See telemetry.Attr.

func Exit

func Exit(w io.Writer, err error) int

Exit writes err to w and returns the process exit code. It returns 0 for a nil error and 1 for any fault. It prints a configuration fault with the config format and every other fault with the host format. The caller owns the call to os.Exit.

func FieldError

func FieldError(ctx context.Context, field string) string

FieldError returns the validation message of this field.

The SDD names this helper Error. The root package already holds the Error name in the toast API of Ctx, and a package level Error reads as a fault type in Go. The view package holds the name that the SDD states, and a component calls view.Error.

func HasError

func HasError(ctx context.Context, field string) bool

HasError reports whether this field failed validation. See view.HasError.

func Inspect

func Inspect[T any](args []string, out, errOut io.Writer, r *Router, set *ModuleSet, checks ...Check) int

Inspect answers one inspection command and returns the exit code.

The type parameter is the configuration of the application, so avero:doctor reports every variable that the application reads. The checks are the boot checks, so the doctor answers the question that DX-8 asks before the process starts.

func Inspecting

func Inspecting(args []string) bool

Inspecting reports an inspection command. The application calls it before it loads the configuration and before it opens the database, so an inspection needs neither.

func main() {
    r, modules := wire(nil)
    if avero.Inspecting(os.Args[1:]) {
        os.Exit(avero.Inspect[Config](os.Args[1:], os.Stdout, os.Stderr, r, modules))
    }
    os.Exit(run())
}

func Load

func Load[T any](ctx context.Context) (*T, error)

Load reads the process environment into a new T. See config.Load.

func Old

func Old(ctx context.Context, field string) string

Old returns the value that the person submitted for this field. See view.Old.

func OldFrom

func OldFrom(ctx context.Context) any

OldFrom returns the input that failed validation.

func UnpackMigrations added in v0.2.0

func UnpackMigrations(fsys fs.FS, root string) (string, func(), error)

UnpackMigrations writes the migrations of an embedded file system into a temporary directory and returns it with the function that removes it.

An application that embeds its migrations therefore applies them from its own binary, and one artifact holds the server, the front end and the schema.

//go:embed all:migrations
var migrations embed.FS

dir, clean, err := avero.UnpackMigrations(migrations, "migrations")
defer clean()

func WithForm

func WithForm(page func(c *Ctx, f *Fields) ViewComponent) router.Option

WithForm renders the form again with 422 when validation fails. Pass it to NewRouter. See view.WithForm.

Types

type App

type App = host.App

App is one Avero application.

func New

func New(cfg BaseConfig, opts ...Option) *App

New builds an application. See host.New.

type AssetEntry

type AssetEntry = assets.Entry

AssetEntry is one built asset.

type BaseConfig

type BaseConfig = config.BaseConfig

BaseConfig holds the variables that every Avero application reads.

type Binder

type Binder = router.Binder

Binder fills itself from a request. `avero generate` writes it.

type Check

type Check = host.Check

Check is one boot check.

func BrokerCheck

func BrokerCheck(address string) Check

BrokerCheck proves that the broker accepts a connection. It opens a TCP connection to the host of the address, because the broker library belongs to the application.

func DatabaseCheck

func DatabaseCheck(dsn string) Check

DatabaseCheck proves that the database answers. It opens its own connection, so `avero doctor` runs it with no application. An application that already holds an engine passes it to DatabaseCheckOn.

func DatabaseCheckOn

func DatabaseCheckOn(e *drel.Engine) Check

DatabaseCheckOn proves the database with an engine that the application already opened.

func MigrationCheck

func MigrationCheck(dsn, dir string) Check

MigrationCheck proves that the database holds every migration of the directory. It opens its own connection, so `avero doctor` runs it with no application. An application that already holds an engine passes it to MigrationCheckOn, which opens nothing.

Register it with WithChecks, so a pending migration stops the process before it serves. See DX-8.

func MigrationCheckFS added in v0.2.0

func MigrationCheckFS(dsn string, sets ...fs.FS) Check

MigrationCheckFS proves the embedded migration sets against a database that the check opens itself. `avero doctor` holds no engine, so it uses this one.

func MigrationCheckOn

func MigrationCheckOn(e *drel.Engine, dir string) Check

MigrationCheckOn proves the migrations with an engine that the application already opened.

func MigrationCheckOnFS added in v0.2.0

func MigrationCheckOnFS(e *drel.Engine, sets ...fs.FS) Check

MigrationCheckOnFS proves the migrations of the embedded sets of the feature slices. Each slice embeds its own, and drel merges them in version order.

func SecretCheck

func SecretCheck(secret Secret) Check

SecretCheck returns a boot check that proves AVERO_SECRET is long enough to sign a cookie. Register it with WithChecks, so that a weak secret stops the process with a repair sentence instead of a panic inside the router wiring. See DX-8.

app := avero.New(cfg.BaseConfig,
    avero.WithChecks(avero.SecretCheck(cfg.Secret)),
    avero.WithHandler(handler))

type Component

type Component = host.Component

Component is a part of the application that has a lifecycle.

type Contribution

type Contribution = module.Contribution

Contribution is one row of the contribution table.

type Ctx

type Ctx = router.Ctx

Ctx carries one request.

func NewCtx

func NewCtx(w http.ResponseWriter, r *http.Request) *Ctx

NewCtx builds a Ctx for one request. A test calls a handler with it and needs no router. See router.NewCtx.

type DescribeModule

type DescribeModule = module.DescribeModule

DescribeModule states the description that an agent reads.

type Description

type Description = module.Description

Description states what one module contributes. See AN-3.

type EventDesc

type EventDesc = module.EventDesc

EventDesc is one event of a module.

type Field

type Field = config.Field

Field is one row of a report.

type FieldDesc

type FieldDesc = module.FieldDesc

FieldDesc is one field of a model or of an event.

type Fields

type Fields = router.Fields

Fields holds one message for each field that failed validation.

func FieldsFrom

func FieldsFrom(ctx context.Context) *Fields

FieldsFrom returns the validation result of a failed request. S10 renders the form again from it.

type HTTPModule

type HTTPModule = module.HTTPModule

HTTPModule contributes routes.

type Handler

type Handler = router.Handler

Handler is one typed handler.

func In

func In[T any, P interface {
	*T
	Binder
	Validator
}](fn func(c *Ctx, in T) (Response, error),
) Handler

In adapts a typed handler to the router. The constraint requires the Bind and Validate methods that `avero generate` writes, so a missing or stale generated file is a compile fault at the route. See router.In.

r.Post("/things", avero.In(m.Create))

type InboxHandler

type InboxHandler = module.InboxHandler

InboxHandler is one message handler.

type InboxModule

type InboxModule = module.InboxModule

InboxModule contributes message handlers.

type Job

type Job = module.Job

Job is one scheduled unit of work.

type Loader

type Loader = config.Loader

Loader reads the configuration values.

type Manifest

type Manifest = assets.Manifest

Manifest maps the name of an asset to the built file.

func LoadManifest

func LoadManifest(fsys fs.FS, name string) (*Manifest, error)

LoadManifest reads the asset manifest from an embedded file system. See assets.LoadManifest.

//go:embed all:assets/dist
var dist embed.FS
m, err := avero.LoadManifest(dist, "assets/dist/manifest.json")

type Middleware

type Middleware = router.Middleware

Middleware wraps a handler and carries a name.

func AccessLog

func AccessLog(l *slog.Logger) Middleware

AccessLog writes one line for each request.

func Adapt

func Adapt(name string, mw func(http.Handler) http.Handler) Middleware

Adapt turns a net/http middleware into an Avero middleware.

func CSRF

func CSRF(secret Secret, opts ...router.CookieOption) Middleware

CSRF protects an unsafe method with a signed double-submit token. Pass cfg.Secret, which BaseConfig reads from AVERO_SECRET.

func Flash

func Flash(secret Secret, opts ...router.CookieOption) Middleware

Flash carries a Toast from one request to the next. Pass cfg.Secret, which BaseConfig reads from AVERO_SECRET.

func Recover

func Recover(l *slog.Logger) Middleware

Recover turns a panic into 500.

func RequestID

func RequestID() Middleware

RequestID gives each request an identifier.

func Transaction

func Transaction(e *drel.Engine) Middleware

Transaction opens a drel transaction and decides the commit from the response.

type MigrationModule

type MigrationModule = module.MigrationModule

MigrationModule contributes migration files.

type Migrator

type Migrator = host.Migrator

Migrator applies the pending migrations at boot.

type ModelDesc

type ModelDesc = module.ModelDesc

ModelDesc is one persistent model of a module.

type Module

type Module = module.Module

Module is one feature of an application.

type ModuleReport

type ModuleReport = module.Report

ModuleReport lists the contribution of every module.

type ModuleSet

type ModuleSet = module.Set

ModuleSet holds the modules and the result of the inspection.

func Modules

func Modules(ms ...Module) *ModuleSet

Modules inspects each module one time and returns the set. Attach adds the routes to a router. See module.Modules.

set := avero.Modules(billing.New(db), catalog.New(db))
if err := set.Attach(r); err != nil {
    os.Exit(avero.Exit(os.Stderr, err))
}

type OTelConfig

type OTelConfig = config.OTelConfig

OTelConfig holds the standard OTEL_* variables.

type Option

type Option = host.Option

Option configures an application.

func WithChecks

func WithChecks(cs ...Check) Option

WithChecks registers boot checks. See host.WithChecks.

func WithComponents

func WithComponents(cs ...Component) Option

WithComponents registers components. See host.WithComponents.

func WithHandler

func WithHandler(h http.Handler) Option

WithHandler mounts the application handler. See host.WithHandler.

func WithListener

func WithListener(l net.Listener) Option

WithListener supplies the listener. See host.WithListener.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger supplies the logger. See host.WithLogger.

func WithMigrator

func WithMigrator(m Migrator) Option

WithMigrator supplies the migrator. See host.WithMigrator.

func WithSignals

func WithSignals(sig ...os.Signal) Option

WithSignals sets the signals that close the application. See host.WithSignals.

func WithoutSignals

func WithoutSignals() Option

WithoutSignals installs no signal handler. See host.WithoutSignals.

type Projection

type Projection = module.Projection

Projection is one read model projection.

type ProjectorModule

type ProjectorModule = module.ProjectorModule

ProjectorModule contributes projections.

type Ready

type Ready = host.Ready

Ready is the optional readiness contract.

type Report

type Report = config.Report

Report lists every configuration field with its value and its source.

func LoadFrom

func LoadFrom[T any](ctx context.Context, l Loader) (*T, *Report, error)

LoadFrom reads l into a new T and returns a report. See config.LoadFrom.

type Response

type Response = router.Response

Response is the result of a handler.

func Empty

func Empty(code int) Response

Empty returns a status with no body.

func HTML

func HTML(code int, body string) Response

HTML returns an HTML response.

func JSON

func JSON(code int, body any) Response

JSON returns a response that encodes body as JSON.

func NoContent

func NoContent() Response

NoContent returns 204 with no body.

func Redirect

func Redirect(code int, to string) Response

Redirect returns a redirect.

func Status

func Status(code int) Response

Status returns a response that carries the standard text of the code.

func Text

func Text(code int, body string) Response

Text returns a plain text response.

func View

func View(c ViewComponent) Response

View renders a component with 200 and the HTML content type.

return avero.View(pages.Index(posts)), nil

func ViewStatus

func ViewStatus(code int, c ViewComponent) Response

ViewStatus renders a component with this status. See view.ViewStatus.

type Route

type Route = router.Route

Route is one registered route.

type RouteDesc

type RouteDesc = module.RouteDesc

RouteDesc is one route of a module.

type RouteReport

type RouteReport = router.Report

RouteReport lists every route of a router.

type Router

type Router = router.Router

Router registers routes and builds the http.Handler.

func NewRouter

func NewRouter(opts ...router.Option) *Router

NewRouter builds a router. See router.New.

type ScheduleModule

type ScheduleModule = module.ScheduleModule

ScheduleModule contributes scheduled jobs.

type Scheduler

type Scheduler = module.Scheduler

Scheduler collects the jobs of the modules.

type SchemaReport

type SchemaReport = module.SchemaReport

SchemaReport lists the models of every module. `avero schema` prints it.

func Schema

func Schema(set *ModuleSet) *SchemaReport

Schema returns the models that the modules describe.

type Secret

type Secret = config.Secret

Secret holds a value that no log line and no error message prints.

type Source

type Source = config.Source

Source states where a value came from.

type Telemetry

type Telemetry = telemetry.Provider

Telemetry holds the tracer, the meter and the logger of one application. It is a component, so Stop flushes the exporters.

func NewTelemetry

func NewTelemetry(cfg BaseConfig, opts ...TelemetryOption) (*Telemetry, error)

NewTelemetry builds the telemetry provider from the OTEL_* variables. See telemetry.New.

type TelemetryOption

type TelemetryOption = telemetry.Option

TelemetryOption configures the telemetry provider.

type Toast

type Toast = router.Toast

Toast is one message that the next rendered page shows.

func Toasts

func Toasts(ctx context.Context) []Toast

Toasts returns the messages of this response. See view.Toasts.

type Validator

type Validator = router.Validator

Validator checks itself. `avero generate` writes it.

type ViewComponent

type ViewComponent = view.Component

ViewComponent renders itself. A templ component satisfies it. The root package already holds Component for the lifecycle contract of the host, so the view name carries the View prefix here.

func CSRFField

func CSRFField() ViewComponent

CSRFField returns the hidden field that an unsafe form must carry.

The SDD names it CSRF. The root package already holds CSRF for the middleware, so the field carries the longer name here. A component calls view.CSRF.

type ViewFunc

type ViewFunc = view.Func

ViewFunc adapts a function to the Component interface.

Directories

Path Synopsis
Package assets holds the asset pipeline, S11.
Package assets holds the asset pipeline, S11.
cli module
cmd
avero command
Command avero writes an application, generates its code, proves its configuration and builds it.
Command avero writes an application, generates its code, proves its configuration and builds it.
avero/dev
Package dev holds the development loop, S15.
Package dev holds the development loop, S15.
Package codegen writes the binding and the validation of each handler input as plain Go.
Package codegen writes the binding and the validation of each handler input as plain Go.
client
Package client holds the HTTP client generator and the runtime that its output calls, S13.
Package client holds the HTTP client generator and the runtime that its output calls, S13.
client/internal/example
Package example holds the client that the tests of the generator drive.
Package example holds the client that the tests of the generator drive.
internal/example
Package example is the fixture of the generator.
Package example is the fixture of the generator.
Package config loads a configuration struct from environment variables.
Package config loads a configuration struct from environment variables.
Package ds holds the Datastar adapter, S12.
Package ds holds the Datastar adapter, S12.
Package host owns the lifecycle of an Avero application.
Package host owns the lifecycle of an Avero application.
Package htmx holds the htmx adapter, S12.
Package htmx holds the htmx adapter, S12.
internal
budget
Package budget records a development experience measurement in the artifacts of the repository.
Package budget records a development experience measurement in the artifacts of the repository.
cli
Package cli holds the commands of the avero binary, S14.
Package cli holds the commands of the avero binary, S14.
cmd/averoexamples command
Command averoexamples writes the three reference applications into examples/, and proves that they match the templates of the scaffolder.
Command averoexamples writes the three reference applications into examples/, and proves that they match the templates of the scaffolder.
cmd/averogen command
Command averogen writes the binding and the validation of each handler input, and the implementation of each client interface.
Command averogen writes the binding and the validation of each handler input, and the implementation of each client interface.
inspect
Package inspect runs an inspection command of an application and returns the JSON document that it printed.
Package inspect runs an inspection command of an application and returns the JSON document that it printed.
migrations
Package migrations reads the migration files of an application and the rows that drel already applied.
Package migrations reads the migration files of an application and the rows that drel already applied.
sse
Package sse writes a server sent event stream.
Package sse writes a server sent event stream.
Package mcp serves the agent surface of an application over stdio, S16.
Package mcp serves the agent surface of an application over stdio, S16.
Package module holds the module contract and the module inspection, S6.
Package module holds the module contract and the module inspection, S6.
Package openapi writes the OpenAPI description of an application, S14.
Package openapi writes the OpenAPI description of an application, S14.
Package router builds an http.Handler from typed handlers.
Package router builds an http.Handler from typed handlers.
Package scaffold writes a new Avero application, S14.
Package scaffold writes a new Avero application, S14.
Package telemetry wires OpenTelemetry traces and metrics, and log/slog.
Package telemetry wires OpenTelemetry traces and metrics, and log/slog.
Package verify runs the gate of an application and reports one record for each step, S16.
Package verify runs the gate of an application and reports one record for each step, S16.
Package view holds the helpers that a server rendered page needs, S10.
Package view holds the helpers that a server rendered page needs, S10.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL