Recipe - OpenAPI Documentation with Swagger UI
Document your Kern API routes with OpenAPI 3.0.3 using the extensions/xopenapi package, served as JSON and Swagger UI.
OpenAPI Documentation with Swagger UI
Use extensions/xopenapi to document routes explicitly and serve both a JSON schema and a Swagger UI page.
Setup
import (
"github.com/mobentum/kern"
"github.com/mobentum/kern/extensions/xopenapi"
)
type CreateUserRequest struct {
Name string `json:"name"`
Email string `json:"email"`
}
type UserResponse struct {
ID int `json:"id"`
Name string `json:"name"`
}Route handler
func createUser(c *kern.Context) {
var req CreateUserRequest
if err := c.DecodeJSON(&req); err != nil {
c.Error(400, "invalid request")
return
}
user := UserResponse{ID: 1, Name: req.Name, Email: req.Email}
c.Created(user)
}OpenAPI route metadata
func main() {
app := kern.New(kern.WithRecovery())
app.POST("/api/users", createUser)Register OpenAPI documentation
if err := xopenapi.Register(app, xopenapi.Config{
JSONPath: "/openapi.json",
DocsPath: "/docs",
DocsTitle: "My API Docs",
Info: xopenapi.Info{
Title: "User API",
Version: "1.0.0",
Description: "A simple user management API",
},
Servers: []xopenapi.Server{
{URL: "http://localhost:8080", Description: "Local"},
},
Routes: []xopenapi.Route{
{
Method: "POST",
Path: "/api/users",
Summary: "Create a user",
Description: "Creates a new user and returns the created resource.",
OperationID: "createUser",
Tags: []string{"Users"},
RequestBody: &xopenapi.RequestBody{
Description: "User creation payload",
Required: true,
Content: map[string]xopenapi.MediaType{
"application/json": {
Schema: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "string"},
"email": map[string]interface{}{"type": "string", "format": "email"},
},
"required": []string{"name", "email"},
},
},
},
},
Responses: map[string]xopenapi.Response{
"201": {
Description: "User created",
Content: map[string]xopenapi.MediaType{
"application/json": {
Schema: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"id": map[string]interface{}{"type": "integer"},
"name": map[string]interface{}{"type": "string"},
},
},
},
},
},
"400": {Description: "Invalid request"},
},
},
},
}); err != nil {
log.Fatal(err)
}Group-scoped documentation
For larger APIs, group routes by tag and scope them:
var userRoutes, adminRoutes []xopenapi.Route
// ... populate route metadata
xopenapi.Register(app, xopenapi.Config{
JSONPath: "/openapi.json",
DocsPath: "/docs",
Info: xopenapi.Info{Title: "Multi-scope API", Version: "2.0.0"},
Routes: append(userRoutes, adminRoutes...),
}) app.Run(":8080")
}What you get
/openapi.json— OpenAPI 3.0.3 JSON schema/docs— Swagger UI interactive documentation- Path parameters auto-detected from
{param}syntax
Key patterns
- Explicit metadata: Routes are documented manually (no reflection)
- Path auto-detection:
{id}in route paths auto-becomes a required path parameter - Swagger UI: Built-in at the configured
DocsPath - Group by tags: Use
Tagsto organize endpoints in Swagger UI
Recipe - File Upload & Download Service
Full-file service with multipart upload, type/size validation, streaming download with Range support, and static serving.
Recipe - Nested Route Groups with Middleware Inheritance
Deeply nested route groups with inherited middleware chains, group-level overrides, and route-specific middleware composition.