neoma

module
v1.1.3 Latest Latest
Warning

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

Go to latest
Published: Mar 21, 2026 License: MPL-2.0

README

Neoma

A modern, fast, and flexible framework for building HTTP REST APIs in Go backed by OpenAPI 3.2 and JSON Schema.

Go Reference Go Version

What is Neoma?

Neoma provides a declarative, type-safe layer on top of your router of choice. Define your endpoints with annotated Go structs, and Neoma handles the rest: request parsing, validation, content negotiation, error formatting, OpenAPI generation, and interactive documentation. The goals of this project are to provide:

  • Incremental adoption for teams with existing services
    • Bring your own router (Chi, Echo, Gin, Fiber, or Go 1.22+ stdlib), middleware, and logging
    • Extensible OpenAPI and JSON Schema layer to document existing routes
  • A modern REST API backend framework for Go developers
  • Guard rails to prevent common mistakes
  • Documentation that cannot get out of date
  • High quality generated developer tooling

Features include:

  • Declarative interface on top of your router of choice:
    • Operation and model documentation
    • Request params (path, query, header, or cookie)
    • Request body
    • Responses (including errors)
    • Response headers
  • Pluggable error model: RFC 9457 Problem Details by default, or bring your own ErrorHandler
    • Auto-generated error documentation pages with RFC links, causes, and fixes
    • Per-endpoint error examples discovered at build time via go generate
    • Link header with rel="type" pointing to resolvable error documentation
  • Per-operation request size limits with sane defaults
  • Content negotiation between server and client
    • Support for JSON (RFC 8259) and optionally CBOR (RFC 7049) content types via the Accept header
  • Conditional requests support, e.g. If-Match or If-Unmodified-Since header utilities
  • Link header with rel="describedBy" and $schema field in response bodies (RFC 8288), pointing to resolvable JSON Schema
  • Patch toolkit for partial updates (RFC 5789):
    • RFC 7396 JSON Merge Patch
    • RFC 6902 JSON Patch
    • Apply directly to JSON bytes, Go structs, or parse into operations for custom storage
  • Annotated Go types for input and output models
    • Generates JSON Schema from Go types
    • Static typing for path, query, header params, bodies, response headers, etc.
    • Automatic input model validation with detailed error locations (e.g. body.items[3].tags)
  • Dual OpenAPI specs: public and internal
    • Mark fields, parameters, or entire operations as hidden:"true" to exclude from the public spec
    • Internal spec includes everything for your team, served at a separate endpoint with optional auth middleware
  • Pipeline architecture: request processing is split into named, replaceable stages
    • Insert, replace, or remove stages without modifying framework internals
    • Zero reflection at request time; all struct analysis happens once at registration
  • Interactive documentation generation using Scalar (default), Stoplight Elements, or Swagger UI
    • Docs endpoints support middleware for authentication
  • Optional CLI built-in, configured via arguments or environment variables
    • Set via e.g. -p 8000, --port=8000, or SERVICE_PORT=8000
    • Startup actions and graceful shutdown built-in
  • Generates OpenAPI for access to a rich ecosystem of tools
  • Generates JSON Schema for each resource, served at individual schema endpoints
  • Hexagonal architecture: clean separation between core interfaces, domain logic, and adapter implementations

Install

Install via go get. Note that Go 1.25 or newer is required.

# After: go mod init ...
go get -u github.com/MeGaNeKoS/neoma

Example

Here is a complete basic hello world example in Neoma, that shows how to initialize an app complete with CLI, declare a resource operation, and define its handler function.

package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/MeGaNeKoS/neoma/adapters/neomachi/v5"
	"github.com/MeGaNeKoS/neoma/formats/cbor"
	"github.com/MeGaNeKoS/neoma/neoma"
	"github.com/MeGaNeKoS/neoma/neomacli"
	"github.com/go-chi/chi/v5"
)

type Options struct {
	Port int `help:"Port to listen on" short:"p" default:"8888"`
}

type GreetingOutput struct {
	Body struct {
		Message string `json:"message" example:"Hello, world!" doc:"Greeting message"`
	}
}

func main() {
	cli := neomacli.New(func(hooks neomacli.Hooks, options *Options) {
		router := chi.NewMux()
		adapter := neomachi.NewAdapter(router)
		config := neoma.DefaultConfig("My API", "1.0.0")
		config.Formats["application/cbor"] = cbor.DefaultCBORFormat
		config.Formats["cbor"] = cbor.DefaultCBORFormat
		api := neoma.NewAPI(config, adapter)

		neoma.Get(api, "/greeting/{name}", func(ctx context.Context, input *struct {
			Name string `path:"name" maxLength:"30" example:"world" doc:"Name to greet"`
		}) (*GreetingOutput, error) {
			resp := &GreetingOutput{}
			resp.Body.Message = fmt.Sprintf("Hello, %s!", input.Name)
			return resp, nil
		})

		hooks.OnStart(func() {
			http.ListenAndServe(fmt.Sprintf(":%d", options.Port), router)
		})
	})

	cli.Run()
}

[!TIP] Replace chi.NewMux() with http.NewServeMux() and neomachi with neomastdlib to use the standard library router from Go 1.22+. Everything else stays the same.

You can test it with go run greet.go (optionally pass --port to change the default) and make a sample request using Restish (or curl):

$ curl localhost:8888/greeting/world
{"message":"Hello, world!"}

Even though the example is tiny you can also see some generated documentation at http://localhost:8888/public/docs. The generated OpenAPI spec is available at http://localhost:8888/openapi.json.

Adapters

Neoma supports multiple routers through adapter packages. Bring your own router, middleware, and logging.

Adapter Import Router Install
neomachi adapters/neomachi/v5 chi/v5 go get github.com/go-chi/chi/v5
neomaecho adapters/neomaecho/v4 echo/v4 go get github.com/labstack/echo/v4
neomaecho adapters/neomaecho/v5 echo/v5 go get github.com/labstack/echo/v5
neomagin adapters/neomagin/v1 gin go get github.com/gin-gonic/gin
neomafiber adapters/neomafiber/v2 fiber/v2 go get github.com/gofiber/fiber/v2
neomafiber adapters/neomafiber/v3 fiber/v3 go get github.com/gofiber/fiber/v3
neomastdlib adapters/neomastdlib net/http ServeMux (Go 1.22+) (included in Go standard library)

Each adapter follows the same pattern:

import "github.com/MeGaNeKoS/neoma/adapters/neomachi/v5"

adapter := neomachi.NewAdapter(router)
api := neoma.NewAPI(config, adapter)

Error Handling

Neoma's error model is fully pluggable through the ErrorHandler interface. Two built-in handlers are provided.

RFC 9457 Problem Details (default):

config.ErrorHandler = errors.NewRFC9457Handler()

// With custom type URIs and instance tracking:
config.ErrorHandler = errors.NewRFC9457HandlerWithConfig(
    "/errors",
    func(ctx core.Context) string { return ctx.URL().Path },
)
{
    "type": "/errors/422",
    "title": "Unprocessable Entity",
    "status": 422,
    "detail": "Validation failed",
    "instance": "/items",
    "errors": [{"message": "expected string length <= 10", "location": "body.name", "value": "too-long"}]
}

When using type URIs, Neoma auto-serves error documentation pages with causes, fixes, endpoint listings, and RFC references at each URI (e.g. /errors/422).

No-Op (full custom control):

config.ErrorHandler = errors.NewNoopHandler()

Suppresses all error schemas from the OpenAPI spec. You handle error serialization yourself.

Convenience functions:

errors.Error400BadRequest("invalid input")
errors.Error404NotFound("item not found")
errors.Error422UnprocessableEntity("validation failed")
errors.Error500InternalServerError("unexpected error")

OpenAPI

Neoma generates OpenAPI 3.2 specs natively from your Go types. Set config.OpenAPIVersion to use 3.1 or 3.0 instead.

Endpoint Content
/openapi.json OpenAPI spec (JSON)
/openapi.yaml OpenAPI spec (YAML)
/public/docs Interactive docs UI (Scalar by default)
/schemas/{name} Individual JSON Schema
Public vs. Internal Spec

Mark operations, fields, or parameters as hidden to exclude them from the public spec while keeping a complete internal spec for your team:

config.InternalSpec = core.InternalSpecConfig{
    Enabled:  true,
    Path:     "/internal/openapi",
    DocsPath: "/internal/docs",
}
type Input struct {
    Name  string `query:"name"`
    Debug bool   `query:"debug" hidden:"true"`
}

The Debug parameter appears only in the internal spec. The public spec shows Name only.

Docs UI Providers
config.Docs.Provider = openapi.ScalarProvider{}      // default
config.Docs.Provider = openapi.StoplightProvider{}    // Stoplight Elements
config.Docs.Provider = openapi.SwaggerUIProvider{}    // Swagger UI

Docs endpoints support middleware for authentication:

config.Docs.Middlewares = core.Middlewares{authMiddleware}

Auto Discovery

The neoma-discover tool scans your handlers for error constructors at build time and generates per-endpoint error examples in the OpenAPI spec. No manual error listing required.

//go:generate go run github.com/MeGaNeKoS/neoma/cmd/neoma-discover -output neoma_errors_gen.go ./...
go generate ./...

The generated file auto-registers via init() when the handlers package is imported. No manual wiring needed. Each operation's error responses will include concrete, endpoint-specific examples.

Configuration

Key configuration options (all set on the Config struct returned by neoma.DefaultConfig):

Field Default Description
OpenAPIVersion "3.2.0" OpenAPI spec version ("3.2.0", "3.1.0", or "3.0.3")
OpenAPIPath "/openapi" URL prefix for spec endpoints
Docs.Path "/public/docs" URL path for the docs UI
Docs.Provider ScalarProvider{} Docs renderer (Scalar, Stoplight, Swagger UI)
SchemasPath "/schemas" URL path for individual JSON Schema endpoints
DefaultFormat "application/json" Fallback content type
ErrorHandler RFC 9457 Error response handler
AllowAdditionalPropertiesByDefault true Allow extra JSON fields by default
FieldsOptionalByDefault true Struct fields are optional unless tagged required:"true"
RejectUnknownQueryParameters false Return 422 on unknown query parameters
InternalSpec.Enabled false Enable the internal OpenAPI spec

Documentation

Full documentation is available in the wiki:

Go package documentation: pkg.go.dev/github.com/MeGaNeKoS/neoma

Credits

Neoma draws inspiration from Huma by Daniel Taylor.

License

MPL-2.0

Directories

Path Synopsis
adapters
neomachi/v5
Package neomachi provides a neoma adapter for the chi v5 HTTP router.
Package neomachi provides a neoma adapter for the chi v5 HTTP router.
neomaecho/v4
Package neomaecho provides a neoma adapter for the Echo v4 web framework.
Package neomaecho provides a neoma adapter for the Echo v4 web framework.
neomaecho/v5
Package neomaecho provides a neoma adapter for the Echo v5 web framework.
Package neomaecho provides a neoma adapter for the Echo v5 web framework.
neomafiber/v2
Package neomafiber provides a neoma adapter for the Fiber v2 web framework.
Package neomafiber provides a neoma adapter for the Fiber v2 web framework.
neomafiber/v3
Package neomafiber provides a neoma adapter for the Fiber v3 web framework.
Package neomafiber provides a neoma adapter for the Fiber v3 web framework.
neomagin/v1
Package neomagin provides a neoma adapter for the Gin web framework.
Package neomagin provides a neoma adapter for the Gin web framework.
neomastdlib
Package neomastdlib provides a neoma adapter for Go's standard library net/http router.
Package neomastdlib provides a neoma adapter for Go's standard library net/http router.
Package binding handles the extraction and conversion of HTTP request data into Go types, including path/query/header parameter binding, request body deserialization, multipart form processing, and response output writing.
Package binding handles the extraction and conversion of HTTP request data into Go types, including path/query/header parameter binding, request body deserialization, multipart form processing, and response output writing.
Package casing provides string case conversion utilities for transforming between camelCase, snake_case, kebab-case, and other naming conventions.
Package casing provides string case conversion utilities for transforming between camelCase, snake_case, kebab-case, and other naming conventions.
cmd
neoma-discover command
Command neoma-discover scans Go packages for error usage and generates a Go source file that registers discovered errors for OpenAPI documentation.
Command neoma-discover scans Go packages for error usage and generates a Go source file that registers discovered errors for OpenAPI documentation.
Package conditional implements HTTP conditional request handling using If-Match, If-None-Match, If-Modified-Since, and If-Unmodified-Since headers.
Package conditional implements HTTP conditional request handling using If-Match, If-None-Match, If-Modified-Since, and If-Unmodified-Since headers.
Package core defines the foundational types and interfaces for the neoma REST API framework, including the API configuration, HTTP context, JSON Schema, OpenAPI specification, operation registration, content negotiation, error handling, and middleware.
Package core defines the foundational types and interfaces for the neoma REST API framework, including the API configuration, HTTP context, JSON Schema, OpenAPI specification, operation registration, content negotiation, error handling, and middleware.
Package errors provides error handling implementations for the neoma framework, including RFC 9457 Problem Details support for standardized HTTP API error responses.
Package errors provides error handling implementations for the neoma framework, including RFC 9457 Problem Details support for standardized HTTP API error responses.
formats
cbor
Package cbor provides CBOR (Concise Binary Object Representation) format support for neoma content negotiation.
Package cbor provides CBOR (Concise Binary Object Representation) format support for neoma content negotiation.
Package middleware provides route grouping and middleware management for the neoma framework, allowing shared path prefixes, middleware chains, and operation modifiers to be applied to groups of routes.
Package middleware provides route grouping and middleware management for the neoma framework, allowing shared path prefixes, middleware chains, and operation modifiers to be applied to groups of routes.
Package negotiate implements HTTP content negotiation for selecting request and response formats based on Accept and Content-Type headers.
Package negotiate implements HTTP content negotiation for selecting request and response formats based on Accept and Content-Type headers.
Package neoma provides a high-level API for building RESTful services with automatic OpenAPI specification generation, input validation, and content negotiation.
Package neoma provides a high-level API for building RESTful services with automatic OpenAPI specification generation, input validation, and content negotiation.
Package neomacli provides a CLI harness for running neoma-based API servers with graceful shutdown, signal handling, and customizable options.
Package neomacli provides a CLI harness for running neoma-based API servers with graceful shutdown, signal handling, and customizable options.
Package neomatest provides testing utilities for neoma APIs, including an in-memory adapter for sending requests and inspecting responses without starting a real HTTP server.
Package neomatest provides testing utilities for neoma APIs, including an in-memory adapter for sending requests and inspecting responses without starting a real HTTP server.
Package openapi provides utilities for generating, serving, and filtering OpenAPI specifications, as well as rendering interactive API documentation using providers such as Scalar, Stoplight Elements, and Swagger UI.
Package openapi provides utilities for generating, serving, and filtering OpenAPI specifications, as well as rendering interactive API documentation using providers such as Scalar, Stoplight Elements, and Swagger UI.
Package patch implements RFC 6902 (JSON Patch) and RFC 7396 (JSON Merge Patch) for use in HTTP PATCH handlers per RFC 5789.
Package patch implements RFC 6902 (JSON Patch) and RFC 7396 (JSON Merge Patch) for use in HTTP PATCH handlers per RFC 5789.
Package schema provides JSON Schema generation from Go types, schema registration and lookup, validation against schemas, and default value application.
Package schema provides JSON Schema generation from Go types, schema registration and lookup, validation against schemas, and default value application.
Package sse provides Server-Sent Events (SSE) support for streaming responses from neoma API handlers.
Package sse provides Server-Sent Events (SSE) support for streaming responses from neoma API handlers.
Package validation provides format validation functions used by the neoma schema validation engine.
Package validation provides format validation functions used by the neoma schema validation engine.
Package yaml converts JSON to YAML.
Package yaml converts JSON to YAML.

Jump to

Keyboard shortcuts

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