Project structure
Use this page as a map: when you need to change behaviour, jump to the row that matches your task, then open the listed paths.
Top-level directories
| Path | Responsibility |
|---|---|
cmd/ | main.go — process entry, wires config → App → modules → HTTP listen. |
config/ | Database connection, logging, email helpers, Init() aggregate. |
database/ | Migrations, entities, seeder, migration manager (create/rollback/status). |
middlewares/ | Cross-cutting HTTP: CORS, JWT authentication. |
modules/ | Feature modules (auth, user, …) each with RegisterModule. |
pkg/ | Small shared utilities: constants (DI keys, enums), helpers, HTTP helpers. |
providers/ | App struct and NewApp factory. |
script/ | CLI parsing and custom named scripts. |
Anatomy of one module (modules/<name>/)
Public contracts (importable across modules)
| Path | Contains |
|---|---|
<name>.go | Thin RegisterModule(app) delegating to internal/app/providers. |
dto/ | Request/response structs, error variables, message constants. |
domain/repositories/ | Interfaces implemented in internal/infrastructure. |
Auth additionally exposes:
| Path | Contains |
|---|---|
jwt/ | JWT issue/parse helpers used by services and middleware. |
Private implementation (internal/)
| Path | Contains |
|---|---|
internal/app/service/ | Business logic orchestrating repositories and external services. |
internal/app/providers/ | RegisterDependencies(app) — DI registrations + routes.Register(...). |
internal/app/queries/ | Optional query/filter types (e.g. pagination filters for list endpoints). |
internal/infrastructure/postgresql/ | GORM repository implementations. |
internal/presentation/controllers/ | Gin handlers. |
internal/presentation/routes/ | Route tables calling controller methods. |
internal/presentation/validation/ | Validator setup / custom rules when not covered by struct tags alone. |
Tests
modules/<name>/tests/ holds validation or unit tests colocated with the module.
database/ in more detail
| Path | Role |
|---|---|
migrations/*.go | Versioned schema changes registered in the migration registry. |
entities/*.go | GORM models used across repositories. |
migration.go | Wiring migration list / runner. |
manager.go | Create migration files, rollback batches, status printing. |
seeders/ | Seeder entry + JSON or code seeds. |
When you add a column, you usually touch migration, entity, DTO, and repository together — keep them in one commit.
pkg/ vs internal/
pkg/is for code reused by many packages at the root (middlewares,modules,script) without importingmodules/.../internal.internal/under a module hides implementation so the compiler helps you respect boundaries.
If something is only used inside one module, keep it under that module’s internal/ tree.
Adding a new module (checklist)
- Copy the pattern from
create_module.shoutput or mirroruser/auth. - Add
RegisterModule(app)incmd/main.goafter its dependencies. - Add navigation entry in this docs site (
lib/nav.ts+content/en+content/id).
Naming consistency (RegisterModule, internal/app/providers) makes onboarding predictable.