evrone/go-clean-template
Clean Architecture template for Golang services
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓3 active contributors
- ✓MIT licensed
Show all 7 evidence items →Show less
- ✓CI configured
- ⚠Small team — 3 contributors active in recent commits
- ⚠Concentrated ownership — top contributor handles 60% of recent commits
- ⚠No test directory detected
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/evrone/go-clean-template)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/evrone/go-clean-template on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: evrone/go-clean-template
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/evrone/go-clean-template shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit today
- 3 active contributors
- MIT licensed
- CI configured
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Concentrated ownership — top contributor handles 60% of recent commits
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live evrone/go-clean-template
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/evrone/go-clean-template.
What it runs against: a local clone of evrone/go-clean-template — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in evrone/go-clean-template | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of evrone/go-clean-template. If you don't
# have one yet, run these first:
#
# git clone https://github.com/evrone/go-clean-template.git
# cd go-clean-template
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of evrone/go-clean-template and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "evrone/go-clean-template(\\.git)?\\b" \\
&& ok "origin remote is evrone/go-clean-template" \\
|| miss "origin remote is not evrone/go-clean-template (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "cmd/app/main.go" \\
&& ok "cmd/app/main.go" \\
|| miss "missing critical file: cmd/app/main.go"
test -f "internal/app/app.go" \\
&& ok "internal/app/app.go" \\
|| miss "missing critical file: internal/app/app.go"
test -f "config/config.go" \\
&& ok "config/config.go" \\
|| miss "missing critical file: config/config.go"
test -f "internal/controller/restapi/router.go" \\
&& ok "internal/controller/restapi/router.go" \\
|| miss "missing critical file: internal/controller/restapi/router.go"
test -f "internal/controller/grpc/router.go" \\
&& ok "internal/controller/grpc/router.go" \\
|| miss "missing critical file: internal/controller/grpc/router.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/evrone/go-clean-template"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
A production-grade Clean Architecture template for Go microservices that implements four concurrent server types: REST API (Fiber), gRPC, AMQP RPC (RabbitMQ), and MQ RPC (NATS). It demonstrates how to structure business logic independently from transport layers using Robert Martin's Clean Architecture principles, with integrated database migrations, Swagger docs, structured logging via ZeroLog, and Prometheus metrics. Layered Clean Architecture: cmd/app/main.go is the entry point; internal/app/app.go orchestrates initialization and migrations; internal/controller/ separates REST (http), gRPC, AMQP RPC, and MQ RPC routers; internal/usecase/ holds business logic; internal/entity/ defines domain models; config/config.go centralizes environment-based configuration via caarlos0/env. Proto definitions in docs/proto/v1/ generate gRPC stubs.
👥Who it's for
Go backend engineers building scalable microservices who need architectural patterns that prevent spaghetti code, maintain business logic independence, and support multiple communication protocols (REST, gRPC, message queues) without rewriting domain code for each transport.
🌱Maturity & risk
Actively maintained and production-ready. The repo has comprehensive CI/CD via GitHub Actions (.github/workflows/ci.yml), established test coverage with Testify and mock generation via go.uber.org/mock, docker-compose orchestration for local dev, and uses Go 1.26. The templated structure indicates regular use in real projects.
Low risk for a template. Dependencies are well-established (Fiber, gRPC, PostgreSQL driver jackc/pgx/v5, golang-migrate). No single-maintainer risk evident (Evrone company-backed). Main consideration: template evolves with Go versions and dependency updates—verify your Go version aligns with go 1.26 in go.mod and pin specific versions in your fork.
Active areas of work
No specific PR or commit data visible in the file list, but the template is stable. Focus appears to be on demonstrated examples: internal/controller/ contains working implementations across four transport types, integration-test/ has end-to-end tests for task, translation, and user operations, and docs/ includes Swagger definitions and protobuf schemas ready to extend.
🚀Get running
git clone https://github.com/evrone/go-clean-template.git
cd go-clean-template
cp .env.example .env
make migrate-up
make run
The Makefile provides commands for local dev; docker-compose.yml spins up PostgreSQL, RabbitMQ, and NATS for local integration testing.
Daily commands:
make run # Start all services (REST, gRPC, AMQP, MQ)
make test # Run unit and integration tests
make migrate-up # Apply database migrations
make docker-up # Spin up PostgreSQL, RabbitMQ, NATS containers
Or docker-compose up to orchestrate the full stack. Swagger docs available at http://localhost:8080/swagger/index.html (REST API port inferred from typical Fiber defaults).
🗺️Map of the codebase
cmd/app/main.go— Application entry point that initializes the app, database, and starts all controllers (REST, gRPC, AMQP, NATS)internal/app/app.go— Core application struct that orchestrates dependency injection and manages all service layersconfig/config.go— Configuration loading via environment variables; all runtime settings depend on thisinternal/controller/restapi/router.go— REST API router setup using Fiber; defines all HTTP endpoints and middleware chaininternal/controller/grpc/router.go— gRPC service router; entry point for proto-based RPC handlersdocs/proto/v1/auth.proto— Protocol Buffer definitions for authentication service; source of truth for gRPC contractsgo.mod— Go module definition with all dependencies; Go 1.26 targeting with critical packages like Fiber, gRPC, and JWT
🛠️How to make changes
Add a new REST API endpoint
- Create request DTO with validation tags in internal/controller/restapi/v1/request/ (
internal/controller/restapi/v1/request/task.go) - Create response DTO in internal/controller/restapi/v1/response/ (
internal/controller/restapi/v1/response/task.go) - Implement handler in internal/controller/restapi/v1/controller.go or new file (
internal/controller/restapi/v1/controller.go) - Register route with middleware in internal/controller/restapi/router.go (
internal/controller/restapi/router.go) - Update Swagger docs using swag comments above handler function (
internal/controller/restapi/v1/controller.go) - Run 'make swag' to regenerate docs/swagger.yaml (
Makefile)
Add a new gRPC service
- Define service contract and messages in docs/proto/v1/yourservice.proto (
docs/proto/v1/auth.proto) - Run 'make gen' to generate *pb.go and *_grpc.pb.go files (
Makefile) - Implement service handler in internal/controller/grpc/v1/yourservice_controller.go (
internal/controller/grpc/v1/auth_controller.go) - Register service in internal/controller/grpc/router.go (
internal/controller/grpc/router.go) - Add gRPC interceptor logic if auth needed in internal/controller/grpc/middleware/ (
internal/controller/grpc/middleware/auth.go)
Add a new business entity (e.g., User, Task, Translation)
- Define entity struct and any value objects in internal/entity/ (not shown, inferred) (
internal/controller/restapi/v1/response/task.go) - Create repository interface in internal/repo/ (not shown, inferred from patterns) (
internal/controller/restapi/v1/controller.go) - Implement repository with SQL queries in internal/repo/postgres/ using Squirrel query builder (
internal/controller/restapi/v1/controller.go) - Create use case/service logic in internal/usecase/ (not shown, inferred) (
internal/controller/restapi/v1/controller.go) - Wire service into app.go dependency injection and pass to controllers (
internal/app/app.go) - Create REST, gRPC, AMQP, and NATS handlers using new service (
internal/controller/restapi/v1/controller.go)
Add environment configuration variable
- Add new field to Config struct with 'env' tag in config/config.go (
config/config.go) - Add example value to .env.example (
.env.example) - Reference config value in internal/app/app.go or controller where needed (
internal/app/app.go) - Update docker-compose.yml environment section if needed for local dev (
docker-compose.yml)
🔧Why these technologies
- Fiber (Go HTTP framework) — Lightweight, fast, Express.js-like API for rapid REST endpoint development with built-in middleware ecosystem
- gRPC + Protocol Buffers — Type-safe, binary RPC protocol for inter-service communication; supports streaming and strong contracts
- JWT (golang-jwt/jwt) — Stateless authentication tokens; enables distributed systems without session centralization
- PostgreSQL + golang-migrate — Relational database with schema versioning; enables reproducible migrations across environments
- Squirrel query builder — Type-safe SQL composition; reduces raw SQL strings
🪤Traps & gotchas
- Database migrations run automatically on app startup (internal/app/migrate.go)—ensure migration files exist or app will panic. 2) All four servers (HTTP REST, gRPC, AMQP RPC, MQ RPC) start in the same process—if you only need one, you must modify cmd/app/main.go to skip the others. 3) Environment variables are required (see .env.example); missing POSTGRES_URL, RABBITMQ_URL, or NATS_URL will cause startup failure. 4) gRPC proto files require protoc compiler and plugin binaries (protoc-gen-go, protoc-gen-go-grpc in go.mod); missing these breaks
make generateorswag init.
🏗️Architecture
💡Concepts to learn
- Clean Architecture (Onion Architecture) — The entire codebase is structured around this principle—entity (domain) → usecase (business logic) → controller (transport agnostic) → framework (HTTP/gRPC/AMQP)—keeping logic independent of frameworks and enabling easy testing
- Request-Reply Pattern (Message Queue RPC) — Used in internal/controller/amqp_rpc/ and internal/controller/mq_rpc/ to implement synchronous RPC over asynchronous message brokers (RabbitMQ, NATS), enabling reliable service-to-service communication
- Dependency Injection — internal/app/app.go manually wires all dependencies (repositories, use cases, controllers) making the system testable and loosely coupled; allows swapping implementations without modifying business logic
- Protocol Buffers (protobuf) — docs/proto/v1/ defines gRPC services and message schemas; protobuf ensures type-safe, version-compatible serialization across services and generates Go code automatically
- Repository Pattern — Data access is abstracted in internal/repository/ with interfaces, allowing use cases to remain database-agnostic and enabling easy mocking in tests
- Database Migrations — golang-migrate in internal/app/migrate.go applies versioned schema changes on startup; ensures repeatable, auditable database evolution across environments
- Structured Logging — ZeroLog produces JSON-formatted logs with context fields; essential for production observability and log aggregation in microservices
🔗Related repos
golang-standards/project-layout— Defines the standard Go project directory structure that this template follows (cmd/, internal/, pkg/)cosmtrek/air— Hot-reload development tool for Go; often used alongside this template for faster iterationgoogle/wire— Dependency injection code generator for Go; alternative to manual DI in internal/app/app.gogofiber/fiber— The REST framework used in internal/controller/http/; power user reference for Fiber-specific handlers and middlewaregrpc/grpc-go— Official gRPC Go implementation; reference for gRPC service patterns used in docs/proto/v1/
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for gRPC middleware (auth_test.go expansion)
The repo has internal/controller/grpc/middleware/auth_test.go but the file structure shows multiple middleware components (auth.go exists) with no visible tests for error cases, token validation edge cases, or integration with the JWT dependency (github.com/golang-jwt/jwt/v5). This is critical for a template repo as it demonstrates best practices for securing gRPC endpoints.
- [ ] Expand internal/controller/grpc/middleware/auth_test.go with test cases for: expired tokens, malformed tokens, missing authorization headers, and valid JWT validation
- [ ] Add table-driven tests covering all jwt.Token validation scenarios from the auth middleware
- [ ] Ensure tests mock external dependencies properly using go.uber.org/mock as already configured in go.mod
- [ ] Update README.md with a section on 'Testing gRPC Middleware' to guide contributors
Add missing integration tests for AMQP RPC controller
The repo has comprehensive integration tests for HTTP (task_test.go, user_test.go, translation_test.go) and uses RabbitMQ (github.com/rabbitmq/amqp091-go in dependencies), but no integration test file exists for the internal/controller/amqp_rpc layer. This is a significant gap for a template demonstrating Clean Architecture with multiple transport layers.
- [ ] Create
integration-test/amqp_rpc_test.gowith test cases for auth, task, and translation AMQP RPC endpoints (mirroring existing HTTP integration tests) - [ ] Extend
docker-compose-integration-test.ymlto ensure RabbitMQ service is running during integration tests - [ ] Add helper functions in
integration-test/helpers_test.gofor AMQP RPC client setup and request/response handling - [ ] Document the AMQP RPC testing approach in README.md
Add GitHub Actions workflow for security scanning with govulncheck
The repo includes golang.org/x/vuln/cmd/govulncheck as a tool dependency but no GitHub Actions workflow exists to run vulnerability checks. The .github/workflows/ci.yml likely exists but appears incomplete. Adding automated security scanning ensures dependencies stay secure—critical for a template used across organizations.
- [ ] Create
.github/workflows/security.ymlwith govulncheck step that runsgovulncheck ./...on all PRs and merges to master - [ ] Add step to check for known vulnerabilities in go.mod and go.sum dependencies
- [ ] Configure workflow to fail on any detected vulnerabilities and produce actionable error messages
- [ ] Document the security scanning process in CONTRIBUTING.md or add a Security section to README.md
🌿Good first issues
- Add unit tests for internal/usecase/ (translation, task, user services) with go.uber.org/mock stubs—currently only integration tests exist in integration-test/
- Extend the Swagger documentation in docs/swagger.yaml with response examples and error codes for all REST endpoints (especially auth and protected routes)
- Create a reference implementation of a new domain entity (e.g., 'project' or 'team') that spans all four transports: add .proto definition, REST handlers, use case, repository, and integration tests
⭐Top contributors
Click to expand
Top contributors
- @soltanoff — 60 commits
- @dependabot[bot] — 39 commits
- @Dawe257 — 1 commits
📝Recent commits
Click to expand
Recent commits
4f1e48a— Merge pull request #423 from evrone/dependabot/go_modules/github.com/caarlos0/env/v11-11.4.1 (soltanoff)d638565— chore(deps): bump github.com/caarlos0/env/v11 from 11.4.0 to 11.4.1 (dependabot[bot])dabd721— Merge pull request #424 from evrone/dependabot/go_modules/google.golang.org/grpc-1.81.0 (soltanoff)281a993— chore(deps): bump google.golang.org/grpc from 1.80.0 to 1.81.0 (dependabot[bot])7dd1ac8— Merge pull request #422 from evrone/chore/github-ci-cd (soltanoff)8675b7b— chore(ci): update linting actions to use fail_level for error reporting (soltanoff)2820d96— Merge pull request #419 from Dawe257/refactor/encapsulate-config-types (soltanoff)5da4151— refactor: make nested config structs unexported (Dawe257)bff8295— Merge pull request #421 from evrone/feat/upd-packages (soltanoff)bedbeb9— chore(deps): update dependencies and modify linting rules (soltanoff)
🔒Security observations
Failed to generate security analysis.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.