What the generated Go app contains
Application structure (clean architecture)
cmd/
api/
main.go # chi.NewRouter, server setup
internal/
config/
config.go # reads from os.Getenv, raises on missing vars
database/
db.go # pgxpool connection pool
migrate.go # goose migration runner
handlers/
auth.go # POST /auth/login, /auth/refresh, /auth/logout
user.go
{entity}.go # one file per entity (GET, POST, PUT, DELETE)
middleware/
auth.go # JWT validation, sets userID in context
ratelimit.go # per-IP token bucket
cors.go
tenant.go # multi-tenant workspace scoping
models/
user.go # pgx row structs + domain types
{entity}.go
services/
auth_service.go
email_service.go
{entity}_service.go
router/
router.go # all routes registered with middleware chains
migrations/
001_initial_schema.sql
002_create_{entity}.sql # one migration per entity
go.mod
go.sum
Makefile # make dev, make test, make migrate, make lint
Dockerfile
docker-compose.yml # app + PostgreSQL + Redis
openapi.yaml
Database layer
pgx/v5— PostgreSQL driver with connection pool, no ORM magicgoosemigrations — one.sqlfile per entity, version-controlled- All foreign key columns indexed
- Multi-tenant filter on every protected query:
WHERE workspace_id = $1 - Named parameters via pgx
pgxscan— no raw string concat - PostgreSQL — never SQLite
Auth and security
- JWT issued as httpOnly, Secure, SameSite=Lax cookies
middleware.Authvalidates token and injectsuserIDinto request contextbcryptpassword hashing viagolang.org/x/crypto- All secrets from
os.Getenv()— nothing hardcoded - Per-IP rate limiting on auth endpoints
API design
go-chi/chirouter with clean route groups per entity- Routes match the generated OpenAPI 3.1 spec
- Consistent error format:
{"error": "snake_case_code", "message": "Human readable description."} - Pagination:
page,per_page,totalin list responses - 201 for creation, 422 for validation errors, 403 for auth/permission, 404 for not found
Tests
testifytest suite with table-driven tests- Integration tests spin up a test PostgreSQL database via
testcontainers-go - Auth tests: login, logout, token refresh, password reset
- Handler tests: correct HTTP status codes, error responses, auth enforcement, tenant isolation
- Coverage target: every handler and service function
Infrastructure
- Multi-stage Dockerfile (golang:alpine build → distroless production — binary under 20MB)
docker-compose.yml: Go API + PostgreSQL + Redis (when rate limiting or job queues used)Makefilefor common dev tasks:make dev,make test,make migrate,make lint- GitHub Actions:
golangci-lint→go test ./...→docker build→ deploy
Go Chi vs Gin vs Echo — which to pick
Choose Go Chi when:
- You want minimal magic — chi is just a router, the rest is standard library
- You want maximum compatibility with
net/httpmiddleware - You value composition over conventions (chi middleware chains are composable)
- Long-term maintainability matters more than initial scaffold speed
Choose Gin when:
- Your team already uses Gin and knows its binding layer
- You need the large Gin ecosystem of existing middleware
Choose Echo when:
- You prefer built-in data binding and validation helpers
- You're building an API gateway pattern
Archiet generates Go Chi. It's the choice that ages best: no framework churn, idiomatic Go, full compatibility with the standard library.
vs other Go starters
Generic Go starters like golang-standards/project-layout, evrone/go-clean-template, or repository-level go new commands give you a project skeleton.
What they don't give you: your entities, your handlers, your business logic, your migrations, your tests — the 85% of the application that is specific to your product.
Archiet starts where those starters end. Paste in your requirements, get back a production-grade Go API with your domain fully implemented.
CTA
Generate a complete Go Chi + Next.js application from your requirements — free plan, no credit card.
Describe your product, pick Go Chi, download a production-ready codebase in 90 seconds.
Start free at archiet.com.