Documentation
¶
Overview ¶
migrate-from-gin example — mechanical port of a gin-style API to zip.
gin before:
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
c.JSON(200, gin.H{"id": c.Param("id")})
})
zip after — Sinatra/Express idiom is preserved; gin.Context becomes *zip.Ctx; gin.H becomes any map-shaped value.
The port is two steps, and stopping after the first loses the point ¶
STEP 1 is mechanical and shown below: the handler shape is the same, so a route moves in one edit. It is a WAY-STATION. An untyped route registers no operation, so after step 1 the endpoint is in no OpenAPI document, is no MCP tool, has no command, and no service can reach it with zip.Call — which is exactly the surface gin gave you, and the surface you are migrating away from.
STEP 2 declares the In/Out types the handler was already parsing by hand and registers the route as a typed op. That is where the projections turn on. Port mechanically to get it running, then type it; do not ship a service that stopped halfway.
A gin codebase built on router groups keeps them: zip.Get takes the App or any Group of it, so a group's prefix is part of the op exactly as it is part of an untyped route. The port does not have to flatten the router to type it.