Skip to content

Anvil v1

Anvil is a compile-time wiring engine for Go backends.

You write controllers, route tables, policies, request structs, services, and errors in ordinary Go. The Anvil compiler type-checks that source and writes the Go code that is repetitive to maintain by hand: dependency construction, route registration, request binding, validation calls, and middleware chains. The same compiler model also produces manifests, OpenAPI documents, and testbed input for tooling.

Anvil is not a web framework. It does not replace your domain model, storage layer, architecture style, logging package, HTTP driver, queue broker, or cloud SDK. It generates the wiring between those parts.

type Projects struct {
sdk.Controller `path:"/projects"`
Store project.Store `inject:""`
Routes struct {
Create sdk.POSTWith[WritePolicy] `path:"/"`
Get sdk.GET `path:"/:projectId"`
Live sdk.WS `path:"/:projectId/live"`
}
}
type GetProjectRequest struct {
ProjectID uuid.UUID `param:"projectId" validate:"required,uuid"`
}
func (p *Projects) Get(ctx sdk.Ctx, req GetProjectRequest) (ProjectDTO, error) {
found, err := p.Store.Find(ctx.Context(), req.ProjectID)
if project.IsNotFound(err) {
return ProjectDTO{}, ctx.Errors().NotFound("project")
}
if err != nil {
return ProjectDTO{}, ctx.Errors().Wrap(err, "querying project")
}
return projectDTO(found), nil
}

The compiler reads marker types and struct tags with Go type information. Route discovery happens at generation time, not while a request is being handled, and Anvil does not parse arbitrary comments to guess your API shape.

For each supported protocol, generated code contains the runtime glue for that protocol. For HTTP that includes:

  • Component/provider construction
  • Dependency graph resolution
  • Group and route registration
  • Path parameter, query, header, and body binding
  • Declarative validation checks
  • Request-level Validate(ctx sdk.Ctx) error calls
  • Middleware chain execution
  • WebSocket route registration when a route uses sdk.WS
  • Protocol metadata used by drivers at startup

Generated code is ordinary Go: deterministic, formatted, readable, and debuggable. If a route binding is wrong, the generated file is one of the first places to look.

At runtime, Anvil coordinates an application instance:

  • Drivers implement protocol adapters such as HTTP, gRPC, GraphQL, and queues
  • The core runtime coordinates lifecycle hooks, events, the error pipeline, and DI
  • Plugins register providers, lifecycle hooks, error observers, and event subscribers
  • Generated code registers routes and jobs against the selected drivers

Handlers receive sdk.Ctx, which exposes cancellation, request data, response metadata, locals, errors, and Native() for explicit driver access.

The same compiler pass can produce several artifacts:

  • Generated Go wiring
  • anvil.manifest.v1 JSON
  • OpenAPI JSON
  • Testbed JSON
  • Built-in analyzer diagnostics
  • Starlark rule diagnostics

The manifest is the shared contract for docs, lint rules, custom Starlark checks, and generated test scenarios.

Public Anvil v1 is split by responsibility:

github.com/TDB-Group/anvil sdk, compiler, core runtime
github.com/TDB-Group/anvil-http std, fiber, gin drivers
github.com/TDB-Group/anvil-grpc gRPC drivers
github.com/TDB-Group/anvil-graphql GraphQL drivers
github.com/TDB-Group/anvil-queue memory, redis, nats, sqs drivers
github.com/TDB-Group/anvil-plugins telemetry, s3, first-party plugins

Third-party framework dependencies live in driver or plugin repositories, not in the core SDK package.

  1. Getting Started
  2. Responsibilities
  3. SDK Contract
  4. Callbacks and Middleware
  5. Generate
  6. Errors
  7. Golden Sample Backend