# api_tmpl A Go backend service template with a working authentication flow (register, login, email verification, refresh tokens), built to be cloned and renamed for new projects rather than run as-is. Included out of the box: - Gin-based HTTP API (`internal/handlers/http`) with an equivalent gRPC + grpc-gateway API (`internal/handlers/grpc`, currently wired up but disabled in `main.go` — see below) - PostgreSQL persistence via `sqlc`-generated queries (`internal/db/sqlc`) - Redis + Asynq background task queue, with an example "send verification email" task - PASETO/JWT auth token issuance and middleware, with role-based access control - Migrations via `golang-migrate` - Swagger/OpenAPI docs, served both via `swaggo` (Gin) and `grpc-gateway`'s generated spec - Bruno API collection for manual testing (`Bruno/`) --- ## Using this as a template 1. Rename the module: replace `github.com/FernandoJVideira/api_tmpl` with your own module path throughout the repo, and update `module` in [go.mod](go.mod). 2. Copy the env templates and fill in real values: ```bash cp api.env.example api.env cp api_test.env.example api_test.env ``` At minimum, set a real `AUTH_TOKEN_SECRET` (32+ random characters) and, if you plan to use the email-verification worker task, real SMTP credentials. Neither `api.env` nor `api_test.env` is tracked in git (see `.gitignore`) — don't commit real secrets into their place. 3. If you rename the module or the gRPC service, regenerate the protobuf/gateway/swagger code: ```bash make proto make mock ``` This requires `protoc`, `protoc-gen-go`, `protoc-gen-go-grpc`, `protoc-gen-grpc-gateway`, `protoc-gen-openapiv2`, and `statik` on your `PATH` (`brew install protobuf`, then `go install` the rest — see [Makefile](Makefile) `proto` target for the exact plugins). 4. Update `PROJ_NAME` / `SERVICE_NAME` in `api.env` and `api_test.env`, and the Swagger metadata in [cmd/api/main.go](cmd/api/main.go) (`@title`, `@description`, `@contact.email`) and [proto/service_api_tmpl.proto](proto/service_api_tmpl.proto). --- ## Prerequisites - Go 1.25+ - PostgreSQL, Redis (or use `docker-compose.yml` for local instances) - [`sqlc`](https://sqlc.dev), [`golang-migrate`](https://github.com/golang-migrate/migrate), [`air`](https://github.com/air-verse/air) (hot reload) — all optional but expected by the `Makefile` - `protoc` + Go plugins (only needed if you touch `proto/*.proto` — see above) --- ## Quickstart (development) 1. Copy env files and fill in secrets (see [Using this as a template](#using-this-as-a-template)). 2. Start local Postgres + Redis: ```bash make up ``` 3. Run DB migrations: ```bash make migrate-up ``` 4. Run the server with hot reload: ```bash make server ``` Or without `air`: ```bash go run ./cmd/api ``` 5. Verify: - HTTP API: `http://localhost:8080/api/v1/...` (see routes in [internal/handlers/http/server.go](internal/handlers/http/server.go)) - Swagger UI: `http://localhost:8080/swagger/index.html` - Redis Commander (from `docker-compose.yml`): `http://localhost:8081` By default `main.go` only starts the Gin HTTP server and the Asynq task processor — the gRPC server and grpc-gateway (`runGrpcServer` / `runGatewayServer` in [cmd/api/main.go](cmd/api/main.go)) are implemented but commented out. Uncomment them if you want the gRPC/gateway path running alongside the Gin server. --- ## Background worker (Asynq) - Tasks are enqueued by the app and processed by an Asynq server embedded in the same binary. - `internal/worker/distributer.go` — enqueues tasks (`TaskDistributor`). - `internal/worker/processor.go` — consumes tasks, registers handlers, configures queue weights. - `internal/worker/task_send_verify_email.go` — example task: sends a verification email after user registration. - `internal/worker/logger.go` adapts Asynq's logger to `zerolog`; edit it to change log formatting. --- ## Environment variables See `api.env.example` for the full list with defaults. Notable ones: - Server: `HTTP_SERVER_ADDR`, `GRPC_SERVER_ADDR`, `ENVIRONMENT`, `ALLOWED_ORIGINS` - Database: `DB_ADDR`, `MIGRATIONS_URL` - Redis: `REDIS_ADDR`, `REDIS_PASSWORD`, `REDIS_DB` - Auth: `AUTH_TOKEN_SECRET`, `AUTH_TOKEN_MIN_KEY_SIZE`, `AUTH_TOKEN_EXP`, `REFRESH_TOKEN_EXP`, `AUTH_TOKEN_ISS`, `AUTH_TOKEN_AUD` - Email: `EMAIL_FROM`, `EMAIL_FROM_NAME`, `EMAIL_SMTP_PASSWORD` - Rate limiter: `RATE_LIMITER_REQS_COUNT`, `RATE_LIMITER_TIME_FRAME`, `RATE_LIMITER_ENABLED` --- ## Testing ```bash make test # go test -v -cover -short ./... ``` `internal/db/sqlc` tests hit a real Postgres instance (`make up && make migrate-up` first). Everything else runs against mocks generated with `mockgen` (`make mock`). --- ## Project layout - `cmd/api/main.go` — application entrypoint (wires config, DB, Redis, servers) - `cmd/db/migrations`, `cmd/db/query` — SQL migrations and queries consumed by `sqlc` - `internal/handlers/http` — Gin HTTP handlers, routes, middleware - `internal/handlers/grpc` — gRPC server + grpc-gateway wiring - `internal/service` — business logic shared by both HTTP and gRPC handlers - `internal/db/sqlc` — generated DB access layer (`Store` interface + queries) - `internal/auth` — PASETO/JWT token makers - `internal/security` — password hashing - `internal/worker` — Asynq task distributor/processor - `internal/mailer` — email sending - `internal/config` — env-based configuration (`viper`) - `internal/val` — request validators - `internal/domain/role` — role constants for RBAC - `pb/` — generated protobuf/gRPC/gateway code (regenerate via `make proto`) - `docs/` — Swagger/OpenAPI specs and the `statik`-embedded swagger UI - `Bruno/` — Bruno collection for manually exercising the API --- ## Makefile targets Run `make `: | Target | Description | |---|---| | `test` | Run unit/integration tests | | `mock` | Regenerate mocks (`Store`, `TaskDistributor`, services) | | `up` / `down` / `reload` | Manage local Docker Compose infra (Postgres, Redis) | | `server` | Run with hot reload (`air`) | | `migration ` | Create a new migration file | | `migrate-up` / `migrate-down` | Apply/rollback migrations | | `sqlc` | Regenerate `internal/db/sqlc` from SQL queries | | `proto` | Regenerate `pb/`, `docs/swagger`, `docs/statik` from `proto/*.proto` | | `dbdocs` / `dbschema` | Generate DB docs / SQL schema from `docs/db.dbml` | | `lint` | Run `golangci-lint` | --- ## Contributing - Keep changes small and focused; add/update unit tests where appropriate.