maniflex
Annotated Go structs in. A full REST API out.
maniflex is a Go framework that turns a plain struct into a production REST API —
filtering, pagination, relations, soft-delete, file uploads, and an OpenAPI 3.1
spec — with no generated code and no per-endpoint boilerplate. Behaviour is
declared with mfx: struct tags and customised through a composable
six-step middleware pipeline.
type Post struct {
maniflex.BaseModel
maniflex.WithDeletedAt
Title string `json:"title" mfx:"required,filterable,sortable"`
Body string `json:"body" mfx:"required"`
Status string `json:"status" mfx:"required,filterable,enum:draft|published|archived"`
UserID string `json:"user_id" mfx:"required,filterable"`
}
Register that struct and you get GET/POST /posts, GET/PATCH/DELETE /posts/{id},
?filter=status:eq:published, ?sort=created_at:desc, ?page=2&limit=20,
?include=user, soft-delete semantics, and an entry in /openapi.json.
Why maniflex
- Reflection, not codegen. Register a struct at startup; routes, schema, and validation are derived from it at runtime. Nothing to regenerate when a field changes.
- One module, two dependencies. The core
maniflexmodule depends only on chi and uuid. Postgres, Redis, Kafka, NATS, bcrypt and friends live in satellite modules you pull in only if you import them. - A pipeline you can reach into. Every request flows through six ordered
steps — Auth → Deserialize → Validate → Service → DB → Response. Hook
middleware
Before,After, orReplaceat any step, scoped by model or operation. - Batteries included, swappable. Ready-made middleware for JWT auth, unique validation, password hashing, multi-tenancy, audit logging, CORS, and more — each one just a function you can replace.
- SQLite or Postgres. Both backends share one SQL adapter. Develop against pure-Go SQLite (no CGo, no external service), deploy on Postgres.
Core concepts
Five ideas carry the whole framework. Understand these and the rest of the docs slot into place.
Model
A Go struct that embeds maniflex.BaseModel and declares its fields with mfx:
struct tags. The struct is the single source of truth: it defines the database
table, the JSON request and response shapes, the validation rules, and which
fields are filterable or sortable. Optional embeds add behaviour — maniflex.WithDeletedAt
turns on soft-delete — and naming conventions like a UserID field declare
relations.
→ Models & BaseModel, Field Tags Reference,
Relations
Registry
The collection of every registered model, built by MustRegister at startup.
It is consumed in two places: the HTTP router reads it to mount routes, and the
DB adapter reads it to run migrations and resolve relations. This is why
MustRegister must run before sqlite.Open / postgres.Open — the adapter
is handed the populated registry.
→ Getting Started
Pipeline
Six ordered steps every request flows through: Auth → Deserialize → Validate → Service → DB → Response. The pipeline is the unit of customisation — instead of writing handlers, you attach middleware to the step where your logic belongs. → Pipeline Overview, ServerContext
Middleware
A func(ctx *maniflex.ServerContext, next func() error) error registered on a pipeline
step. Registration is scoped with maniflex.ForModel(...) and maniflex.ForOperation(...),
and positioned with maniflex.Before (default), maniflex.After, or maniflex.Replace. Set
ctx.Response and return without calling next() to short-circuit the request.
→ Writing Middleware, Middleware Catalogue
Adapter
The database backend implementing the storage interface. Two ship in-tree —
db/sqlite (pure-Go, no CGo) and db/postgres — and both share one SQL core.
Inject one with server.SetDB(db), which patches the pipeline’s DB step in
place.
→ Database Backends, Transactions
Where to go next
- Getting Started — install, define your first model, run the server.
- Models & Tags — the full
mfx:tag reference and relation conventions. - The Pipeline — how requests flow and where to hook in.
- Middleware Catalogue — ready-made middleware for every step.
- Querying the API — filtering, sorting, pagination, includes.
maniflex requires Go 1.25 or newer.