Claude Code Plugins

Community-maintained marketplace

Feedback

backend-dev-guidelines

@jhouser/actionphase
0
0

Comprehensive backend development guide for Go/Chi/PostgreSQL with Clean Architecture. Use when creating routes, handlers, services, interfaces, middleware, working with Chi APIs, sqlc database access, JWT authentication, request validation, correlation IDs, or async patterns. Covers layered architecture (routes → handlers → services → database), interface-first development, error handling, observability, testing strategies, and service decomposition patterns.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name backend-dev-guidelines
description Comprehensive backend development guide for Go/Chi/PostgreSQL with Clean Architecture. Use when creating routes, handlers, services, interfaces, middleware, working with Chi APIs, sqlc database access, JWT authentication, request validation, correlation IDs, or async patterns. Covers layered architecture (routes → handlers → services → database), interface-first development, error handling, observability, testing strategies, and service decomposition patterns.

Backend Development Guidelines

Purpose

Establish consistency and best practices for ActionPhase backend development using Go, Chi router, PostgreSQL with sqlc, and Clean Architecture principles.

When to Use This Skill

Automatically activates when working on:

  • Creating or modifying routes, endpoints, APIs
  • Building handlers, services, interfaces
  • Implementing middleware (auth, CORS, recovery, correlation IDs)
  • Database operations with sqlc
  • JWT authentication and refresh tokens
  • Input validation and error handling
  • Observability (structured logging, correlation IDs)
  • Backend testing and refactoring
  • Service decomposition

Quick Start

New Backend Feature Checklist

  • Migration: Database schema changes (if needed)
  • SQL Queries: Write queries in queries/*.sql
  • Code Generation: Run just sqlgen
  • Interface: Define in core/interfaces.go
  • Tests: Write unit tests first (TDD)
  • Service: Implement business logic
  • Handler: HTTP request handling
  • API Tests: Test endpoints with curl
  • Documentation: Update API docs

New Service Checklist

  • Interface definition in core/interfaces.go
  • Compile-time verification: var _ Interface = (*Implementation)(nil)
  • Constructor function with dependencies
  • Unit tests with mocks
  • Error handling with correlation IDs
  • Structured logging
  • Input validation

Architecture Overview

Layered Architecture

HTTP Request
    ↓
Middleware (correlation ID, auth, CORS, recovery)
    ↓
Routes (Chi router)
    ↓
Handlers (request binding, validation)
    ↓
Services (business logic)
    ↓
sqlc Queries (type-safe SQL)
    ↓
PostgreSQL

Key Principle: Each layer has ONE responsibility.

See: .claude/context/ARCHITECTURE.md for complete details.


Directory Structure

backend/
├── cmd/server/           # Application entry point
├── pkg/
│   ├── core/            # Domain models, interfaces, errors
│   │   ├── interfaces.go  # ALL service interfaces
│   │   ├── models.go      # Business entities
│   │   └── errors.go      # Typed errors
│   ├── db/
│   │   ├── queries/       # SQL files (*.sql)
│   │   ├── models/        # Generated by sqlc
│   │   ├── migrations/    # Schema migrations
│   │   └── services/      # Service implementations
│   │       ├── phases/    # Decomposed phase service
│   │       ├── actions/   # Decomposed action service
│   │       ├── messages/  # Decomposed message service
│   │       └── *.go       # Other services
│   ├── http/
│   │   ├── root.go        # Routing + middleware
│   │   ├── middleware/    # Custom middleware
│   │   └── */api.go       # HTTP handlers
│   └── util/             # Utilities
├── .env                  # Environment variables
└── justfile             # Development commands

Naming Conventions:

  • Packages: lowercase - services, middleware
  • Files: snake_case.go - user_service.go, auth_api.go
  • Types: PascalCase - GameService, UserHandler
  • Functions: PascalCase (exported), camelCase (private)
  • Interfaces: PascalCase + Interface - GameServiceInterface

Core Principles (8 Key Rules)

1. Interfaces First, Implementation Second

ALL service interfaces MUST be defined in backend/pkg/core/interfaces.go

// ✅ ALWAYS: Define interface first
type GameServiceInterface interface {
    CreateGame(ctx context.Context, req *CreateGameRequest) (*Game, error)
    GetGame(ctx context.Context, id int) (*Game, error)
}

// ✅ ALWAYS: Compile-time verification
var _ GameServiceInterface = (*GameService)(nil)

type GameService struct {
    DB *pgxpool.Pool
}

func (s *GameService) CreateGame(ctx context.Context, req *CreateGameRequest) (*Game, error) {
    // Implementation
}

Benefits: Easy mocking, clear contracts, compile-time safety, dependency injection.

2. Use sqlc for Type-Safe SQL

// ❌ NEVER: Raw SQL with manual mapping
row := db.QueryRow("SELECT id, title FROM games WHERE id = $1", id)
var game Game
row.Scan(&game.ID, &game.Title)

// ✅ ALWAYS: sqlc-generated queries
queries := db.New(pool)
game, err := queries.GetGame(ctx, id)

Workflow: Write SQL → just sqlgen → Use generated code

3. Handlers Only Handle HTTP, Services Contain Logic

// ❌ NEVER: Business logic in handlers
func (h *Handler) CreateGame(w http.ResponseWriter, r *http.Request) {
    // 200 lines of validation, business logic, database calls
}

// ✅ ALWAYS: Delegate to service layer
func (h *Handler) CreateGame(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    correlationID := middleware.GetCorrelationID(ctx)

    var req core.CreateGameRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        core.WriteError(w, core.ErrInvalidRequest(err, correlationID))
        return
    }

    game, err := h.service.CreateGame(ctx, &req)
    if err != nil {
        core.WriteError(w, err)
        return
    }

    core.WriteJSON(w, http.StatusCreated, game)
}

4. Always Use Correlation IDs

// Generate in middleware
correlationID := uuid.New().String()
ctx = context.WithValue(ctx, middleware.CorrelationIDKey, correlationID)

// Use in logging
log.Info().
    Str("correlation_id", correlationID).
    Str("user_id", userID).
    Msg("Game created")

// Include in errors
return core.ErrNotFound("game", gameID, correlationID)

5. Structured Logging with Context

// ✅ ALWAYS: Use zerolog with structured fields
log.Info().
    Str("correlation_id", correlationID).
    Str("user_id", userID).
    Int("game_id", gameID).
    Str("action", "create_game").
    Msg("Game created successfully")

// ❌ NEVER: fmt.Println or log.Println
fmt.Println("Game created:", gameID)

6. Validate All Input at Handler Layer

// Validate before passing to service
if req.Title == "" {
    return core.ErrInvalidRequest(
        errors.New("title is required"),
        correlationID,
    )
}

if len(req.Title) > 255 {
    return core.ErrInvalidRequest(
        errors.New("title too long"),
        correlationID,
    )
}

7. Use Typed Errors with Context

// Define in core/errors.go
type APIError struct {
    Code          string `json:"code"`
    Message       string `json:"message"`
    CorrelationID string `json:"correlation_id,omitempty"`
    HTTPStatus    int    `json:"-"`
}

// Usage
if game == nil {
    return nil, core.ErrNotFound("game", gameID, correlationID)
}

8. Test-Driven Development (TDD)

// Write test first (should fail)
func TestCreateGame(t *testing.T) {
    service := &GameService{DB: mockDB}
    game, err := service.CreateGame(ctx, req)
    require.NoError(t, err)
    assert.Equal(t, "Test Game", game.Title)
}

// Then implement
// Then verify test passes

Common Imports

// HTTP and routing
import (
    "net/http"
    "github.com/go-chi/chi/v5"
    "github.com/go-chi/chi/v5/middleware"
    "github.com/go-chi/cors"
)

// Database
import (
    "github.com/jackc/pgx/v5/pgxpool"
    "actionphase/backend/pkg/db"
)

// Logging
import (
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"
)

// JWT
import (
    "github.com/golang-jwt/jwt/v5"
)

// Testing
import (
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
)

// Context and errors
import (
    "context"
    "errors"
)

Quick Reference

HTTP Status Codes

Code Use Case
200 Success
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
500 Server Error

justfile Commands

just dev              # Start server with .env
just sqlgen           # Generate Go from SQL
just test             # Run all tests
just test-mocks       # Fast unit tests (~300ms)
just migrate          # Apply migrations
just make_migration   # Create new migration

Database Name

CRITICAL: Database name is actionphase, NOT database

postgres://postgres:example@localhost:5432/actionphase

Anti-Patterns to Avoid

❌ Business logic in handlers ❌ Raw SQL without sqlc ❌ Missing correlation IDs ❌ No error handling ❌ No input validation ❌ fmt.Println instead of structured logging ❌ Direct process.env in code (use config) ❌ Forgetting interface definitions ❌ Skipping tests


Service Decomposition Pattern

When to Decompose

Decompose a service when:

  • File exceeds 500 lines
  • Multiple distinct responsibilities emerge
  • Testing becomes difficult
  • Code navigation is hard

How to Decompose

Example: Phase service decomposition (1056 lines → 6 files)

services/phases.go (1056 lines)
    ↓
services/phases/
├── service.go        # Main service struct + constructor
├── crud.go           # Create, Read, Update, Delete
├── transitions.go    # State transitions
├── validation.go     # Validation logic
├── history.go        # History tracking
└── converters.go     # Model conversions

Pattern:

  1. Create package directory: services/phases/
  2. Move service struct to service.go
  3. Group related methods into focused files
  4. Update imports across codebase
  5. Run tests to verify

See: .claude/planning/REFACTOR_00_MASTER_PLAN.md


Navigation Guide

Need to... Read this
Understand architecture .claude/context/ARCHITECTURE.md
See complete patterns .claude/reference/BACKEND_ARCHITECTURE.md
Handle errors properly .claude/reference/ERROR_HANDLING.md
Implement logging .claude/reference/LOGGING_STANDARDS.md
Document APIs .claude/reference/API_DOCUMENTATION.md
Write tests .claude/context/TESTING.md
Use test fixtures .claude/context/TEST_DATA.md

Key Files Reference

Must Read Before Coding:

  • backend/pkg/core/interfaces.go - ALL service contracts
  • backend/pkg/core/models.go - Business entities
  • backend/pkg/core/errors.go - Error types
  • backend/pkg/http/root.go - Routing + middleware

Implementation Examples:

  • backend/pkg/db/services/games.go - Simple service
  • backend/pkg/db/services/phases/ - Decomposed service
  • backend/pkg/db/queries/games.sql - sqlc patterns

Testing Requirements

MANDATORY: Tests for all new features and bug fixes

Test Types

  1. Unit Tests (FAST - run first)

    • Mock dependencies using interfaces
    • Test business logic in isolation
    • Run: just test-mocks (~300ms)
  2. Integration Tests (with database)

    • Test with real PostgreSQL
    • Use test fixtures
    • Run: SKIP_DB_TESTS=false just test
  3. API Tests (curl verification)

    • Verify endpoints return correct data
    • Test before E2E tests
    • Pattern: ./backend/scripts/api-test.sh
  4. E2E Tests (LAST)

    • Only after unit + API + component tests pass
    • See: .claude/context/TESTING.md

Bug Fix Process

  1. Write test that reproduces bug (should fail)
  2. Fix the bug
  3. Verify test passes
  4. Commit test and fix together

See: .claude/context/TESTING.md for complete testing guide


Authentication Pattern

JWT Access Tokens (15 min) + Refresh Tokens (7 days)

  • Access tokens for API requests (in Authorization header)
  • Refresh tokens stored in database sessions
  • User ID NOT in JWT - fetched from /api/v1/auth/me
  • Automatic refresh via frontend interceptors

Security: JWT only contains sub (username), exp, iat, jti

See: /docs/adrs/003-authentication-strategy.md


Related Context Files

  • .claude/context/ARCHITECTURE.md - Complete architecture patterns
  • .claude/context/TESTING.md - Testing philosophy and patterns
  • .claude/context/TEST_DATA.md - Test fixtures overview
  • .claude/reference/BACKEND_ARCHITECTURE.md - Detailed implementation guide
  • .claude/reference/ERROR_HANDLING.md - Error patterns
  • .claude/reference/LOGGING_STANDARDS.md - Logging best practices
  • .claude/reference/API_DOCUMENTATION.md - API endpoint docs

ADR References

  • ADR-001: Technology Stack Selection (Go, Chi, PostgreSQL, sqlc)
  • ADR-002: Database Design (Hybrid relational-document with JSONB)
  • ADR-003: Authentication Strategy (JWT + Refresh Tokens)
  • ADR-004: API Design Principles (RESTful, versioned)
  • ADR-006: Observability Approach (Structured logging, correlation IDs)
  • ADR-007: Testing Strategy (Test pyramid, TDD)

Location: /docs/adrs/


Skill Status: COMPLETE ✅ Line Count: < 500 ✅ Tech Stack: Go, Chi, PostgreSQL, sqlc ✅ Progressive Disclosure: Links to detailed context files ✅