HTTP and PostgreSQL live in external adapters. The Article application service uses the Repository interface rather than a concrete database driver. Bootstrap connects implementations when assembling the application.
Custom hooks join the same use case through declared interfaces. Generation can therefore update standard handling while your checks and actions evolve in custom code.
Package responsibilities
| Package | Responsibility |
|---|---|
domain |
Entity types and shared errors. Imports neither HTTP nor PostgreSQL. |
app/article |
Article commands, queries and use cases. Declares Repository and Hooks interfaces. |
adapters |
HTTP handlers and the PostgreSQL repository using pgx and explicit SQL. |
infrastructure |
Database connections, migrations and technical mechanisms. |
generated/bootstrap |
Composition of configuration, repository, service, hooks and HTTP handlers. |
The tree shows main paths using Article as an example, not a complete inventory. Files depend on the model and project capabilities.
backend/ — Article CRUD example
cmd/api/main.go
internal/
├── domain/
│ └── article.go
├── app/
│ ├── article/
│ │ ├── commands.go
│ │ ├── queries.go
│ │ └── service.go
│ └── listquery/query.go
├── adapters/
│ ├── http/generated/
│ │ ├── article_handler.go
│ │ ├── article_mapper.go
│ │ └── article_routes.go
│ └── postgres/generated/
│ ├── article_repository.go
│ └── article_queries.sql
├── infrastructure/
│ ├── database/database.go
│ └── migrations/migrations.go
├── generated/
│ ├── bootstrap/app.go
│ ├── config/config.go
│ ├── registry/entities.go
│ └── customcontracts/composition.go
└── custom/
├── app/
│ ├── composition.go
│ └── routes.go
└── article/hooks.go
domain — entity types and errors
This package defines entity types and shared errors. It imports neither HTTP nor PostgreSQL. An HTTP mapper converts requests; the storage adapter converts database rows. Model files remain generator-owned even when their paths do not contain generated.
app — use cases and their interfaces
article/service.go declares Repository, Hooks and Service. Commands and queries define use-case inputs. Interfaces belong to their consumer: the service declares the operations it needs from storage and custom extensions.
adapters — HTTP and PostgreSQL
HTTP handlers receive requests, call application services and produce responses. The PostgreSQL repository implements Repository with pgx and explicit SQL. At runtime the service calls the repository through its interface; in source the adapter depends on the app contract, not the reverse.
infrastructure — technical mechanisms
Database connections, migration execution and file storage when media is enabled are separated from Article handling. Connection and storage configuration do not become record-level business logic.
bootstrap — connecting implementations
cmd/api/main.go starts the application assembled in generated/bootstrap/app.go. Bootstrap connects configuration, repository, service, hooks and HTTP handlers. Connect your dependencies through custom composition instead of editing generated bootstrap.
Package dependencies and runtime calls
adapters/http ──────→ app/article ──────→ domain
adapters/postgres ──→ app/article
custom/article ─────→ app/article + domain
bootstrap → adapters + app + infrastructure + custom
Arrows show source dependencies: the package on the left uses the contract on the right. A service can call a PostgreSQL repository through an interface without importing postgres. Custom identifies implementation ownership rather than adding a fifth architectural layer.
Request flow: creating an Article
After access checks at the HTTP boundary, successful record creation follows these steps.
HTTP → Service
The handler reads the request body, maps it to entity data and passes it to the Article service.
validateCreate → BeforeCreate
The service checks standard requirements, then invokes the custom hook for additional validation or data transformation.
Repository.Create
The PostgreSQL adapter writes the data and returns the created entity.
AfterCreate → HTTP response
After creation, the service invokes AfterCreate. The result is then mapped to the API response.
If BeforeCreate returns an error, no record is written. AfterCreate runs after Repository.Create: an error from it does not itself guarantee rollback. If your actions need a shared transaction, define that behavior explicitly in your project.
Where to add your logic
Use backend/internal/custom/article/hooks.go for entity checks and actions. Connect dependencies through custom/app/composition.go. Custom routes use custom/app/routes.go and RegisterRoutes. Do not edit generated bootstrap to connect extensions.