Architecture
Package Map
Every bkgo package has exactly one place in the generated project. This map shows which packages belong in which file — so you always know what to import.
The CLI generates all imports automatically
When you run bkgo g module user, every file is generated with the correct bkgo imports already in place. You only write your entity fields, business rules, and SQL migrations — nothing else.
Layer → Package mapping
cmd/api/main.goEntry point — connects all adapters together
💡 Only place that imports concrete adapters
internal/<module>/handler.goHTTP handler — parses requests, sends responses
💡 Calls usecase, never touches DB directly
internal/<module>/usecase.goPure business rules — no framework, no DB driver
💡 Depends only on the Repository interface (PORT)
internal/<module>/domain.goEntity struct + Repository interface — pure Go
no imports — pure Go💡 Zero bkgo imports — stays framework-free forever
internal/<module>/repository.goPostgreSQL implementation of the Repository interface
💡 Implements the PORT defined in domain.go
internal/<module>/usecase_test.goUnit tests — mocks the Repository, no real DB needed
💡 mock/ ships function-override test doubles for every contract
Packages you add manually
Three packages are not generated by the CLI because they are only needed in specific situations. Add them yourself when the condition below applies to your module.
bkgo/hashadd manuallyimport "github.com/BounkhongDev/bkgo/hash"
hashed, err := hash.Password(input.Password)
ok := hash.CheckPassword(input.Password, user.HashedPassword)bkgo/adapter/minioadd manuallyimport "github.com/BounkhongDev/bkgo/adapter/minio"
store, err := minio.New(ctx, cfg.MinIO)
url, err := store.Upload(ctx, "avatar.png", fileBytes, "image/png")
presigned := store.PresignedURL(ctx, "avatar.png", time.Hour)bkgo/adapter/postgresadd manuallyimport "github.com/BounkhongDev/bkgo/adapter/postgres"
// Use instead of adapter/gorm — satisfies contract.Database
db, err := postgres.New(ctx, cfg.Postgres)The one rule
Dependencies only point inward. Outer layers know about inner ones — inner layers never import outer ones.
main.go → knows about handler, repository, adapters handler.go → knows about usecase usecase.go → knows about domain.Repository (interface only) repository.go → implements domain.Repository domain.go → knows nothing — pure structs + interfaces
Swap PostgreSQL for any other database by writing a new repository.go — zero changes to usecase or handler.