Encore.dev is a platform for building and running cloud applications with Go and Typescript. Although Encore provides various examples and templates, I felt the need for a template for slightly more complex applications. This repository is a starter repository for building slightly more complex applications with Go and Encore.
If you are looking for a repository with even more depth, check out Bill Kennedy's Encore repository. Compared to that repository, this repository is a bit simpler. For example, it merges the service
and application
layers.
- Auth Service: A bearer token based auth service. User can also login to obtain a token.
- User Service: A CRUD service for users.
- Email Service: A mocked email service, called through pubsub.
- Service Layer: is where all the Encore services are defined. It serves as the API layer and does authentication/authorization, validation, etc.
- Business Layer: is where all the business logic is defined. It is relatively thin in this example repository, but in a real-world application, it would contain all the business logic.
- Storage Layer: is how data is persisted. Storage is unlocked to each business service via an interface and is abstracted away from the business logic. This repository uses PostgreSQL as the database.
- Integrations: is where all the external services are defined. This repository has a mocked email service, called through pubsub as an example.
Authentication is handled by a bearer token in the auth service. The auth service is responsible for generating and validating tokens. The token is passed in the Authorization
header of each request.
Authorization is handled by Open Policy Agent (OPA) in a middleware for each service. The middleware checks if a user can perform an action against a central policy. The policy is defined in the opa
directory.
Authorization can be enforced by adding the tag:authorize
tag to an encore API definition within a service.
- Single Database: This repository uses a single database across services. This is fine for smaller projects, but for larger projects, you might want to split the database.
- sqlc: sqcl is used to generate type-safe SQL queries. The sqlc configuration file is
sqlc.yaml
. If you split your database, or if you add new services, you will need to update this file.
├── services // API layer: HTTP handlers, validation, authentication, authorization, etc
│ ├── auth // Auth service: bearer token and auth middleware
│ └── user // User service: CRUD operations for a user
├── business // Business logic layer:
│ ├── auth // Auth business logic
│ │ └── db // Auth storage repository
| | ├── queries.sql // Definition of SQL queries for the auth service
│ │ └── postgres // Auth storage implementation for postgres, generated by sqlc
│ └── user // User business logic
│ └── db // User storage repository
| ├── queries.sql // Definition of SQL queries for the user service
│ └── postgres // User storage implementation for postgres, generated by sqlc
├── integrations // External services
│ ├── authorization // Authorization (OPA)
│ ├── appdb // Database defintion
│ │ └── migrations // Database migrations
│ └── sendmail // Email integration
├── utils // Utility functions
│ └── slices // Slice utility functions
└── sqlc.yaml // sqlc configuration file
If you have any suggestions or improvements, feel free to open an issue or a pull request.