Your first module
This page plays out the first step of the shop sample application: from an empty project to a booting module serving requests. Every command works the same in Fiber and chi projects: where the output differs, we show both.
Generate the module
go tool gpsystem new module shop
This creates:
- the entry point (
cmd/shop/main.go): withfiberx.Runin a Fiber project,chix.Runin a chi project; - the module wiring (
internal/modules/shop/register.go): aDependenciesstruct + an exportedRegisterApi(router, deps)function; - an
apisurface undersurfaces/api/: a handler bound to the generated strict interface, a minimalservice/seam, apolicy/registry stub, plus a kept-emptyhttp/mapper/folder for your own code; - the module-level shared skeletons:
core/(home of the rules and sentinel errors the surfaces share) andrepository/(the module's single persistence layer); - the TypeSpec contract (
spec/typespec/modules/shop/) and the codegen config (api/oapi-codegen/shop-api.yaml); - then registers everything via anchor insertions (
main.tsp,cmd/shop/main.go).
Run the codegen chain
mise run generate
This compiles TypeSpec to OpenAPI (api/openapi/), runs oapi-codegen with the project's template set (the kit's vendored Fiber v3 templates for Fiber, upstream chi-server + the kit's strict overrides for chi), places the output under internal/modules/shop/surfaces/api/http/gen/, tidies and builds. The sample handler implements the generated strict interface, so the project compiles immediately: spec/code drift is a compile error.
Boot it
go run ./cmd/shop
Try it
curl localhost:3000/api/v1/shop/
[]
The scaffold handler returns an empty list; replace its body once you've built the module's core/ and repository/ layers, with the surface's service/ seam serving from them.
Errors are RFC 9457 problem documents by default, in the same shape regardless of engine (Error responses):
curl localhost:3000/api/v1/nope
{
"type": "about:blank",
"title": "Not Found",
"status": 404,
"detail": "Not Found",
"instance": "/api/v1/nope"
}
Press Ctrl+C: the server waits out in-flight requests, closes the pool, flushes telemetry and exits cleanly. That's the app lifecycle at work, which both fiberx.Run and chix.Run sit on.
During development it's worth switching on the Monolog-style console log (LOG_FORMAT=monolog): you'll see error chains in the readable format you know from PHP.
Where to next
From here you can follow the path of the shop sample application:
- Another surface (e.g.
admin): add surface - Adding endpoints: add handler
- An event, a listener and a scheduled job: worker generators
- What exactly the chassis does: Architecture