Type-safe HTTP framework for Go with automatic OpenAPI generation.
Define your request and response types, wire up handlers, and get a fully-documented API with validation baked in.
type CreateUserInput struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
type UserOutput struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
handler := rocco.NewHandler[CreateUserInput, UserOutput](
"create-user", "POST", "/users",
func(req *rocco.Request[CreateUserInput]) (UserOutput, error) {
return UserOutput{
ID: "usr_123",
Name: req.Body.Name,
Email: req.Body.Email,
}, nil
},
).WithErrors(rocco.ErrBadRequest, rocco.ErrConflict)Your types define the contract. Rocco handles validation, serialization, error responses, and OpenAPI schema generation — all derived from the same source of truth.
go get github.com/zoobzio/roccoRequires Go 1.24+.
package main
import (
"fmt"
"github.com/zoobzio/openapi"
"github.com/zoobzio/rocco"
)
type CreateUserInput struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
type UserOutput struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
engine := rocco.NewEngine()
// Configure OpenAPI metadata
engine.WithOpenAPIInfo(openapi.Info{
Title: "User API",
Version: "1.0.0",
})
handler := rocco.NewHandler[CreateUserInput, UserOutput](
"create-user", "POST", "/users",
func(req *rocco.Request[CreateUserInput]) (UserOutput, error) {
return UserOutput{
ID: "usr_123",
Name: req.Body.Name,
Email: req.Body.Email,
}, nil
},
).
WithSummary("Create a new user").
WithTags("users").
WithSuccessStatus(201).
WithErrors(rocco.ErrBadRequest, rocco.ErrUnprocessableEntity)
engine.WithHandlers(handler)
// OpenAPI spec at /openapi, interactive docs at /docs
fmt.Println("Server listening on :8080")
engine.Start(rocco.HostAll, 8080)
}| Feature | Description | Docs |
|---|---|---|
| Type-Safe Handlers | Generic handlers with compile-time type checking | Handlers |
| Server-Sent Events | Built-in SSE support for real-time streaming | Streaming |
| Automatic OpenAPI | Generate OpenAPI 3.1.0 specs from your types | OpenAPI |
| Request Validation | Struct tag validation with detailed error responses | Concepts |
| Sentinel Errors | Typed HTTP errors with OpenAPI schema generation | Errors |
| Lifecycle Events | Observable signals for logging, metrics, tracing | Events |
- Type-safe — Generic handlers catch errors at compile time, not runtime
- Self-documenting — OpenAPI specs generated from the same types that validate requests
- Explicit — No magic, no hidden behaviors, no struct tag DSLs for routing
- Chi-powered — Built on the battle-tested Chi router with full middleware compatibility
- Observable — Lifecycle events via capitan for metrics and tracing
- Streaming-native — First-class SSE support with typed event streams
Rocco enables a pattern: define types once, derive everything else.
Your request and response structs become the single source of truth. From them, rocco derives validation rules, OpenAPI schemas, error contracts, and documentation.
Define a type:
type CreateOrderInput struct {
CustomerID string `json:"customer_id" validate:"required,uuid4" description:"Customer UUID"`
Items []Item `json:"items" validate:"required,min=1" description:"Order line items"`
Total float64 `json:"total" validate:"required,gt=0" description:"Order total in USD"`
}Get an OpenAPI schema:
CreateOrderInput:
type: object
required: [customer_id, items, total]
properties:
customer_id:
type: string
format: uuid
description: Customer UUID
items:
type: array
minItems: 1
description: Order line items
items:
$ref: '#/components/schemas/Item'
total:
type: number
exclusiveMinimum: 0
description: Order total in USDGet consistent validation errors:
{
"code": "VALIDATION_FAILED",
"message": "validation failed",
"details": {
"fields": [
{"field": "customer_id", "message": "must be a valid UUID"},
{"field": "total", "message": "must be greater than 0"}
]
}
}No separate schema files. No manual sync between code and docs. The types ARE the contract.
- Overview — Design philosophy and architecture
- Quickstart — Get started in minutes
- Concepts — Handlers, requests, validation, errors
- Architecture — Internal design and components
- Handlers — Request/response handlers and streaming
- Errors — Sentinel errors and custom error types
- Authentication — Identity extraction and middleware
- OpenAPI — Schema generation and customization
- Best Practices — Patterns and recommendations
- Streaming — Server-Sent Events
- CRUD API — Complete REST API example
- Authentication — JWT and session patterns
- Observability — Logging, metrics, tracing
- Realtime — SSE patterns and use cases
- API — Complete function documentation
- Errors — All sentinel errors and detail types
- Events — Lifecycle signals and field keys
See CONTRIBUTING.md for guidelines.
MIT License — see LICENSE for details.