Adding a Module
This is a practical wiring checklist. For the concepts behind each step, refer to the Engine Overview.
The example below adds a wishlist module.
Checklist
1. Create the module directory
internal/modules/wishlist/
├── module.go # engine.Module implementation
├── controller.go # HTTP handlers
├── service.go # business logic
└── domain.go # domain models + repository interface
See Module Lifecycle for what each file should contain and a full module.go example.
2. Implement engine.Module
In module.go, implement all six methods of the engine.Module interface: Name, Requires, BasePaths, Init, RegisterRoutes, and Shutdown.
3. Add configuration
Three files need to change to make your module toggle-able via config.yaml.
In internal/engine/config.go — add a config type and include it in ModulesConfig:
type WishlistModuleConfig struct {
Enabled bool `yaml:"enabled"`
}
type ModulesConfig struct {
// ... existing modules
Wishlist WishlistModuleConfig `yaml:"wishlist"`
}
Then set a default in defaultModulesConfig():
func defaultModulesConfig() ModulesConfig {
return ModulesConfig{
// ... existing modules
Wishlist: WishlistModuleConfig{Enabled: true},
}
}
In internal/engine/registry.go — add a case to the IsModuleEnabled switch:
case "wishlist":
return cfg.Modules.Wishlist.Enabled
In config.yaml — add the toggle:
modules:
wishlist:
enabled: true
Setting enabled: false causes the engine to skip the module's Init() and RegisterRoutes() and mount a 503 catch-all on its BasePaths() instead.
4. Declare service keys (if other modules will depend on yours)
In internal/engine/services.go, add a constant and a typed resolver:
const (
// ... existing keys
ServiceWishlist = "wishlist"
)
func ResolveWishlist(c *Container) wishlist.Service {
return c.MustResolve(ServiceWishlist).(wishlist.Service)
}
Then in your module's Init(), publish the service:
c.Provide(engine.ServiceWishlist, m.service)
See Dependency Injection for how Provide and MustResolve work.
5. Register in the master registry
In internal/modules/registry/registry.go, import your package and add it to the factories map:
import (
// ... existing imports
moduleswishlist "ecom-engine/internal/modules/wishlist"
)
var factories = map[string]func(engine.Config) engine.Module{
// ... existing entries
"wishlist": moduleswishlist.New,
}
6. Implement repositories
Define your repository interface in domain.go (no DB imports). Implement it for each driver and wire it in repoprovider.go.
See Repository Layer for the full pattern.
Verification
After completing the checklist, start the server:
go run ./cmd/server/main.go
The engine will log module boot order. Confirm your module appears, initialized after its dependencies. If a dependency is missing or misspelled, the engine will exit at startup with a clear error before any module boots.