agentsclimarketplace

Gin architect

Skill ralvarezdev/ralvaskills/skills/frameworks/gin-architect

Framework-specific delta on rest-api-architect — Gin 1.12 on Go 1.26. Feature layout, struct-tag validation, RFC 7807 errors, in-house JWT or external IdP, route groups for URL-prefix versioning, OpenAPI. Read rest-api-architect first for the cross-cutting REST conventions. Use when scaffolding or reviewing a Gin service.From its SKILL.md

Install
npx -y skills add ralvarezdev/ralvaskills --skill gin-architect

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 1 command, including `swag init`.

SKILL.md

7.1 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

Gin Architecture

Targets Gin 1.12 on Go 1.26. Companion to go-architect, rest-api-architect, and sql-architect. Implementation skeletons in RECIPES.md; pinned deps in STACK.md.

1. Project structure — feature-based

One folder per bounded context. Each feature owns its routes, service, repo, DTOs, and SQL files. Mirrors fastapi-architect so polyglot teams can navigate either side. Full tree in RECIPES.md.

  • handlers.go depends on service.go; never reaches into repo.go directly.
  • service.go is pure Go — no gin imports. Easy to unit-test without a fake *gin.Context.
  • dto.go holds wire types with json: and binding: (validator) tags. Never reuse domain structs as DTOs — that's how internal fields leak into the API.

2. Routing & versioning

URL-prefix versioning via route groups. One group per version, one sub-group per feature. Registration skeleton in RECIPES.md.

  • One Register(rg, deps) function per feature — keeps main.go thin.
  • Path params typed at parse time: id, err := uuid.Parse(c.Param("user_id")) — return 400 on parse failure.
  • Use gin.RouterGroup, not bare Engine.GET, so versioning + per-group middleware stays clean.

3. Request validation

Use struct tags with go-playground/validator (canonical per go-architect). Bind via c.ShouldBindJSON / c.ShouldBindUri / c.ShouldBindQuery — never c.MustBindWith (panics; we don't panic in handlers).

type CreateUserReq struct {
    Email    string `json:"email"    binding:"required,email"`
    Password string `json:"password" binding:"required,min=12"`
}
  • binding:"required" on every field that isn't truly optional.
  • Custom validators registered once at startup: validate.RegisterValidation("uuid_v7", isUUIDv7).
  • binding:"omitempty" on PATCH partial-update DTOs — let absent fields mean "leave unchanged."

4. Response shaping

  • Return DTOs, not domain types. c.JSON(200, dto.UserResponse{...}) — DTOs control what leaks.
  • json:"-" on any DTO field that should never serialize (passwords, internal IDs).
  • Status code with c.JSON(http.StatusCreated, ...) — explicit, not Gin's default 200.
  • Empty body uses c.Status(http.StatusNoContent), not c.JSON(204, nil) (sends null).

5. Dependency injection

Explicit constructors per go-architect §3. No globals, no init() magic. Dependencies live in a Deps struct wired in main.go. For larger graphs use uber-go/fx (canonical per go-architect); for services with <10 dependencies, hand-wired is clearer.

6. Lifespan & graceful shutdown

Open shared resources in main.go, never per-request. Close them on shutdown signal via signal.NotifyContext (Go 1.26 records which signal fired). Full skeleton in RECIPES.md.

  • ReadHeaderTimeout is mandatory — without it, Slowloris can pin connections forever.
  • Graceful shutdown timeout > longest expected request duration.

7. Authentication & authorization

Patterns (in-house JWT vs external IdP, Argon2id, JWT lifetimes, JWKS verification, switching criterion) live in rest-api-architect/AUTH_PATTERNS.md. Gin specifics:

  • Pattern A — in-house JWT via golang-jwt/jwt/v5 + argon2 from golang.org/x/crypto. Middleware skeleton in RECIPES.md.
  • Pattern B — external IdP: jwt.ParseWithClaims with a Keyfunc that resolves keys via a JWKS client. Cache JWKS in-process with TTL.
  • Authorization per route, never global — RequireScope(...) composed alongside AuthRequired(secret) on the route declaration (see RECIPES.md).

8. Error handling — RFC 7807 middleware

A central problem package emits application/problem+json (per rest-api-architect §7). Handlers either call problem.Render(c, p) directly or c.Error(err) and let the recovery middleware convert. Renderer in RECIPES.md.

  • One handler per domain-error family — map known sentinel errors to Problem types in a single switch.
  • gin.Recovery with a custom RecoveryHandler that emits a 500 Problem with correlation_id — never a stack trace.

9. Middleware order

Outermost first; order matters.

r := gin.New()  // not gin.Default — we set logging ourselves
r.Use(
    middleware.RequestID(),             // 1. assign correlation_id
    middleware.SLog(),                  // 2. structured access log
    gin.Recovery(),                     // 3. convert panics → 500 problem
    middleware.CORS(cfg.CORS),          // 4. preflight handling
    gzip.Gzip(gzip.DefaultCompression), // 5. response compression
)
  • Never gin.Default() in production — its logger writes unstructured text to stdout. Use slog (per go-architect).
  • Auth is per-route middleware, never global (see §7).
  • Recovery before CORS — a panic that bypasses CORS handler returns no headers; the browser shows a misleading CORS error.

10. Concurrency, not "background tasks"

Go has no FastAPI-style BackgroundTasks. To run work after the response, derive a new context.Context from context.Background() (request context is cancelled the moment the response writes), set a timeout, log errors. Anything serious (retryable, distributed, scheduled) belongs in a real task queue, not a goroutine.

11. Testing

httptest.NewRecorder + the engine directly — no real socket. Skeleton in RECIPES.md.

  • Test-DB strategy: mirror sql-architect — wrap each test in a rolled-back transaction, or use a per-test schema with golang-migrate.
  • Table-driven tests (per go-architect §9) for request validation paths — one row per (input, expected status, expected error type).

12. OpenAPI generation

  • Default: swaggo/swag — // @ annotation comments above handlers; swag init generates docs/swagger.json and swagger.yaml. Predictable, mature.
  • For full OpenAPI 3.1 control: getkin/kin-openapi — write the spec in code; serve it; use it to validate requests at runtime. More work but no annotation noise.
  • CI snapshot-tests the spec (per rest-api-architect §15).
  • Internal endpoints excluded with // @Hidden (swag) or by not registering them in the spec route group.

What ships with it: 2 files

6.1 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.