Documentation

Everything you need to scaffold, run, and ship a production Go backend with GooLang.

Introduction

GooLang Backend is a production-ready Go service template: CQRS application layer, an OpenAPI-first HTTP API with generated handlers, OpenTelemetry tracing/metrics/logs, an MCP (Model Context Protocol) server for AI agent integrations, pure-Go SQLite persistence, and Docker/Helm deployment out of the box.

It's a fork of gemyago/golang-backend-boilerplate, maintained by Swift Kimani. The goal of this fork: keep the original's architecture intact while adding a one-line scaffolding CLI and this documentation site — the same experience you'd expect from create-next-app, for Go.

💡 This site is self-hosted proof. dev.benardkimani.co.ke runs on the exact Docker Compose + Traefik pattern described in Deployment below — an nginx container serving this static site, proxying /api/* to the Go server sitting right next to it.

Quick Start

Scaffold a new project without cloning or forking anything:

npx github:swiftkimani/goolang-backend my-app

Then boot it:

cd my-app && go mod tidy && make test
go run ./cmd/server start --env local --noop

--noop dry-runs startup checks without requiring external dependencies — useful for verifying the setup before wiring a real database or OTEL collector. Drop it to actually serve traffic:

go run ./cmd/server start --env local
curl http://localhost:8080/health

Prefer a plain git clone? That works too, you'll just rename the Go module yourself:

git clone https://github.com/swiftkimani/goolang-backend.git my-app

CLI Reference

create-goolang-backend lives at cli/create-goolang-backend/ in the repo and runs entirely on your machine — no telemetry, no registry account needed.

npx github:swiftkimani/goolang-backend <project-directory>

What it does, in order:

  1. Shallow-clones the template repo into <project-directory>
  2. Removes .git and the cli/ folder (it's a template-only concern)
  3. Rewrites the Go module path (github.com/gemyago/golang-backend-boilerplate) to your project name across .go, .mod, .md, .yaml/.yml, .html, and Makefile/AGENTS.md files
  4. Leaves upstream attribution links (like the one in this page's License & Credits section) untouched — only import paths and slugs get renamed
  5. Initializes a fresh git repository with an initial commit

Requirements: git and node for the scaffolding step; Go 1.26+ (see go.mod) for everything after.

Project Structure

PathWhat's there
internal/Primary application code — API, app (CQRS), config, DI, infrastructure, telemetry, system
cmd/Binary entrypoints: server, jobs, mcp
build/Docker build tooling — multi-platform image builds
deploy/Helm chart for Kubernetes + this landing/docs site's own Docker Compose deployment
doc/Human docs, e.g. testing best practices
.github/CI/CD workflows

Nearest AGENTS.md wins for AI coding agents — root, internal/, build/, and deploy/ each carry one scoped to that subtree.

Architecture

Pragmatic layered architecture. Dependencies point inward only, wired at startup via uber/dig.

API Layer
HTTP, MCP — where the world meets your system
internal/api/http/ · internal/api/mcp/
↓ Consumer-Defined Interfaces
Application Layer
CQRS Commands & Queries — all business logic lives here
internal/app/
↓ Ports (Interfaces)
Infrastructure Layer
SQLite, Petstore API, HTTP clients — outbound adapters
internal/infrastructure/
↓
Cross-Cutting
Config, DI, Telemetry, Time, Identity
internal/config/ · internal/di/ · internal/telemetry/ · internal/system/

OpenAPI-first handlers

Routes are defined once in internal/api/http/v1routes.yaml. Type-safe handlers are generated from that spec via apigen — edit the YAML, run go generate, get compile-time-checked request/response types.

Configuration

Config is layered: internal/config/default.yaml → <env>.yaml → optional <env>-user.yaml (gitignored, for local overrides).

KeyPurposeDefault
defaultLogLevelBase log levelINFO
httpServer.portHTTP listen port8080
gracefulShutdownTimeoutDrain time on SIGTERM10s
database.dsnSQLite DSN (pure-Go driver, no CGO)./data/app.db
petstore.baseURLSample external HTTP client targetpetstore3.swagger.io
mcpServer.name / versionIdentity reported to MCP clientsgolang-backend-boilerplate-mcp
openTelemetry.enabledMaster switch for tracing/metrics/logs exportfalse

Every value is also settable via env var, prefixed APP_ with dots/dashes converted to underscores:

APP_ENV=local APP_HTTP_SERVER_PORT=8080 APP_DATABASE_DSN=/app/data/app.db APP_JSON_LOGS=true

Common CLI flags on every binary: --env, --log-level, --json-logs, --logs-file.

API Reference

Base path / on the Go server, proxied under /api/ on this site (see the live API explorer on the home page — every endpoint below is wired up and callable from there).

Health & Echo

MethodPathDescription
GET/healthLiveness check — {"status":"OK"}
POST/echoEchoes back {"message": string} — useful smoke test for the request pipeline

Users

MethodPathDescription
GET/usersList all users
POST/usersCreate a user — {name, email} → {userId}
GET/users/{userId}Get a user by id
PUT/users/{userId}Update name/email
DELETE/users/{userId}Delete a user

Pets (nested under a user)

MethodPathDescription
GET/users/{userId}/petsList a user's pets
POST/users/{userId}/petsAdd a pet — {name, status, photoUrls?}, status is one of available|pending|sold
DELETE/users/{userId}/pets/{petId}Remove a pet from a user

Full request/response schemas live in internal/api/http/v1routes.yaml (OpenAPI 3.0.3) — the source of truth apigen generates handlers from.

MCP Server

cmd/mcp exposes tools over the Model Context Protocol so AI agents can call into this service directly, over stdio or HTTP.

go run ./cmd/mcp stdio --env local --noop
go run ./cmd/mcp http --env local --noop

Tools registered out of the box:

ToolDescription
get_current_timeCurrent date/time in a requested format
calculateAdd, subtract, multiply, divide

Add your own under internal/api/mcp/controllers/ and register them alongside the existing ones.

Testing

make test
  • One top-level test function per component, nested t.Run per method/scenario
  • makeMockDeps for dependency setup — no repeated inline wiring
  • Faker (github.com/jaswdr/faker/v2) for random test data, via factory functions
  • apptime.NewMockProvider() for deterministic time, ident.NewMockGenerator() for deterministic UUIDs
  • Compare whole structs (assert.Equal(t, expected, actual)) over field-by-field checks
  • Mocks generated per mockery config in .mockery.yaml

Full detail in doc/testing-best-practices.md.

Deployment

Docker images

make -C build docker/.local-images

Multi-platform (linux/amd64 + arm64), distroless runtime. Configure platforms/registries in build/build.cfg.

Kubernetes via Helm

helm template deploy/helm/api-service --debug --name-template api-service -f deploy/helm/api-service/values.yaml
helm upgrade api-service deploy/helm/api-service --install --namespace community-manager -f deploy/helm/api-service/values.yaml --create-namespace --dry-run

Self-hosting a static + API site (this site)

deploy/site/ has the exact recipe used to run this page: an nginx container serving static assets and proxying /api/* to a distroless Go server container, both behind Traefik for TLS termination and routing.

FileRole
docker-compose.ymlnginx + go-server services, internal network between them
Dockerfile.nginx / Dockerfile.serverBuild steps for each container
nginx.confStatic asset serving, gzip, SPA fallback, /api/ reverse proxy
deploy.shrsync + remote docker compose up -d --build over SSH
./deploy/site/deploy.sh

License & Credits

MIT licensed. This project is a fork of gemyago/golang-backend-boilerplate — a well-crafted Go backend starter template. All original architecture and patterns are preserved; the fork adds the scaffolding CLI and this documentation site.

Fork maintained by Swift Kimani.

Copied to clipboard!