This guide walks you through building your first modkit app: a simple HTTP server with one module, one provider, and one controller.
What you'll build: A /greet endpoint that returns a greeting message.
Prerequisites: Go 1.25.x and familiarity with net/http.
CI is pinned to Go 1.25.7. See the Stability and Compatibility Policy for support expectations.
go get github.com/go-modkit/modkitCreate a module with a provider (the greeting string) and a controller (the HTTP handler):
package app
import (
"net/http"
mkhttp "github.com/go-modkit/modkit/modkit/http"
"github.com/go-modkit/modkit/modkit/module"
)
// Token identifies the greeting provider
const TokenGreeting module.Token = "greeting"
// Controller handles HTTP requests
type GreetingController struct {
greeting string
}
func (c *GreetingController) RegisterRoutes(r mkhttp.Router) {
r.Handle(http.MethodGet, "/greet", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte(c.greeting))
}))
}
// Module defines the app structure
type AppModule struct{}
func (m *AppModule) Definition() module.ModuleDef {
return module.ModuleDef{
Name: "app",
Providers: []module.ProviderDef{
{
Token: TokenGreeting,
Build: func(r module.Resolver) (any, error) {
return "Hello, modkit!", nil
},
},
},
Controllers: []module.ControllerDef{
{
Name: "GreetingController",
Build: func(r module.Resolver) (any, error) {
value, err := module.Get[string](r, TokenGreeting)
if err != nil {
return nil, err
}
return &GreetingController{greeting: value}, nil
},
},
},
Exports: []module.Token{TokenGreeting},
}
}Key points:
- Modules must be passed as pointers (
&AppModule{}) for stable identity - Controllers must implement
mkhttp.RouteRegistrar - Providers are built on first access and cached as singletons
Create your main.go:
package main
import (
"log"
mkhttp "github.com/go-modkit/modkit/modkit/http"
"github.com/go-modkit/modkit/modkit/kernel"
"your/module/app"
)
func main() {
// Bootstrap the app
appInstance, err := kernel.Bootstrap(&app.AppModule{})
if err != nil {
log.Fatal(err)
}
// Create router and register controllers
router := mkhttp.NewRouter()
if err := mkhttp.RegisterRoutes(mkhttp.AsRouter(router), appInstance.Controllers); err != nil {
log.Fatal(err)
}
// Start server
log.Println("Listening on :8080")
if err := mkhttp.Serve(":8080", router); err != nil {
log.Fatal(err)
}
}Run your app:
go run main.goTest the endpoint:
curl http://localhost:8080/greet
# Hello, modkit!If you want a quick database-backed example without Docker, try the SQLite example module:
export SQLITE_PATH="/tmp/modkit.db"
go run ./examples/hello-sqlite/cmd/api/main.goThen:
curl http://localhost:8080/health- Modules Guide — Learn about imports, exports, and visibility
- Testing Guide — Testing patterns for modkit apps
- Architecture Guide — How modkit works under the hood
- Example App — Full CRUD API with MySQL, migrations, and Swagger
- SQLite Example — Fast local eval, no Docker required
modkit: command not found: install CLI withgo install github.com/go-modkit/modkit/cmd/modkit@latestand ensure$(go env GOPATH)/binis inPATH.go run cmd/api/main.gofails after scaffolding: rungo mod tidyin the scaffolded app directory, then retry.- Endpoint check fails: if you scaffolded with the CLI, retry
curl http://localhost:8080/health; if you followed this guide manually, testcurl http://localhost:8080/greet.