go-first/docs/DEVELOPMENT.md
2026-10-07 15:21:47 +02:00

12 KiB

Development Guide — go-first / URPI

This guide covers local development setup, workflows, and best practices.


🛠️ Prerequisites

Required Tools

Tool Version Install
Go 1.23+ brew install go / apt install golang
Node.js 20+ nvm install 20 / fnm install 20
Docker 24+ docker.com
Git 2.40+ brew install git / apt install git
  • IDE: VS Code with Go + TypeScript extensions
  • API Client: HTTPie, Postman, or VS Code REST Client
  • Database: TablePlus, DBeaver, or pgAdmin
  • Terminal: Warp, Ghostty, or Kitty

🚀 Getting Started

1. Clone & Setup

git clone https://github.com/dnoulet/go-first.git
cd go-first

# Install all dependencies
make install

# This runs:
# - go mod download
# - cd web && npm ci

2. Start Development Databases

# Start PostgreSQL + Redis only
docker compose up -d postgres redis

# Verify
docker compose ps
docker compose exec postgres pg_isready -U postgres
docker compose exec redis redis-cli ping

3. Configure Local Environment

cp .env.local.example .env.local

# Edit if needed (defaults work for Docker databases)
vim .env.local

4. Run Development Servers

# Option A: Both together (recommended)
make dev

# Option B: Separate terminals
# Terminal 1 - Backend
make dev-backend

# Terminal 2 - Frontend
make dev-frontend

5. Verify

Service URL
Frontend http://localhost:5173
Backend API http://localhost:8080/api/v1
Health Check http://localhost:8080/api/v1/health
PostgreSQL localhost:5432
Redis localhost:6379

🔄 Development Workflow

Backend Development

# Hot reload with air (already configured in .air.toml)
make dev-backend

# Or manually:
go run ./cmd/server

Adding a New Endpoint

  1. Model — Add types in internal/model/models.go
  2. Service — Create service in internal/service/
  3. Handler — Add handler in internal/handler/handler.go
  4. Routes — Register in handler.RegisterRoutes()
  5. Tests — Add tests in *_test.go files

Frontend Development

# Hot module replacement (Vite)
make dev-frontend

# Or manually:
cd web && npm run dev

Adding a New Page/Section

  1. Types — Add to web/src/types/index.ts
  2. API — Add endpoint to web/src/services/api.ts
  3. Hook — Create custom hook in web/src/hooks/
  4. Component — Create in web/src/components/sections/
  5. Register — Import and add to web/src/App.tsx

Code Generation

# Generate mocks for testing
make generate

# This runs: go generate ./...
# Uses: github.com/golang/mock/mockgen

🧪 Testing

Backend Tests

# Run all tests with coverage
make test-backend

# Run specific package
go test -v ./internal/service/...

# Run with race detector
go test -race ./...

# Generate coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html

Frontend Tests

# Run tests
make test-frontend

# Or manually:
cd web && npm test

# With UI
cd web && npm test -- --ui

# Coverage
cd web && npm test -- --coverage

E2E Tests (Optional)

# Install Playwright
cd web && npx playwright install

# Run E2E tests
cd web && npm run test:e2e

🔍 Code Quality

Linting

# All linters
make lint

# Backend only
make lint-backend
# Runs: golangci-lint run ./...

# Frontend only
make lint-frontend
# Runs: eslint + prettier check

Formatting

# Format all code
make fmt

# Backend
go fmt ./...
goimports -w .

# Frontend
cd web && npm run format

Pre-commit Hooks

# Install pre-commit
pip install pre-commit
pre-commit install

# Run manually
pre-commit run --all-files

.pre-commit-config.yaml

repos:
  - repo: https://github.com/golangci/golangci-lint
    rev: v1.56.0
    hooks:
      - id: golangci-lint

  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        types: [typescript, json, yaml, markdown]

  - repo: local
    hooks:
      - id: go-fmt
        name: go fmt
        entry: go fmt ./...
        language: system
        types: [go]

🗃️ Database Migrations

Creating Migrations

# Create new migration
make db-migrate-create name=add_users_table

# This creates:
# migrations/000001_add_users_table.up.sql
# migrations/000001_add_users_table.down.sql

Running Migrations

# Apply all pending
make db-migrate-up

# Rollback last
make db-migrate-down

# Check status
migrate -path ./migrations -database "$DSN" version

Migration Best Practices

  • Up migrations: Add columns, tables, indexes
  • Down migrations: Reverse exactly (drop what you added)
  • Never modify applied migrations
  • Test both up and down locally
  • Name clearly: add_user_email_index, not fix_db

🐳 Docker Development

Build Locally

# Build production image
make docker-build

# Run production image locally
make docker-run

# Or with docker-compose (includes DB)
docker compose up -d --build

Debugging in Container

# Run with shell
docker run -it --rm -p 8080:8080 ghcr.io/dnoulet/go-first:latest sh

# Or attach to running
docker exec -it go-first-app sh

Development with Docker Compose Override

Create docker-compose.override.yml:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app
      - /app/web/node_modules
    command: air -c .air.toml
    environment:
      - SERVER_MODE=debug

🎨 Frontend Architecture

Component Structure

web/src/components/
├── ui/              # Reusable primitives (Button, Card, Input, Badge)
├── layout/          # Page structure (Header, Footer)
├── sections/        # Page sections (Hero, Services, Projects, etc.)
└── forms/           # Form-specific components

State Management

  • Server state: useApi hook (React Query pattern)
  • Local state: useState, useReducer
  • Forms: Controlled components with validation
  • No global store (Redux/Zustand) — keep it simple

Styling

  • Tailwind CSS utility-first
  • Custom design system in tailwind.config.js
  • CSS variables for theming (dark mode ready)
  • Component variants via clsx + tailwind-merge

Adding Icons

# Use lucide-react (already installed)
import { IconName } from 'lucide-react'

# Or add to public/ and use <img>

🔧 Backend Architecture

Clean Architecture Layers

cmd/server/           # Entry point, wiring
internal/
├── config/           # Configuration (YAML + env)
├── handler/          # HTTP layer (Gin)
├── middleware/       # Cross-cutting concerns
├── model/            # Domain models, DTOs
└── service/          # Business logic

Dependency Injection

Services are instantiated in main.go and passed to handlers:

skillService := service.NewSkillService()
h := handler.NewHandler(skillService, ...)

Adding Database Support

  1. Add DB config to config.yaml
  2. Create internal/repository/ package
  3. Implement interfaces in service/
  4. Use database/sql or sqlx or gorm
  5. Add migrations

Middleware Chain

router.Use(
    middleware.Recovery(),      // Panic recovery
    middleware.Logger(),        // Request logging
    middleware.SecurityHeaders(), // Security headers
    middleware.CORS(...),       // CORS
)

📝 Git Workflow

Branch Naming

Type Pattern Example
Feature feat/short-description feat/contact-form-validation
Fix fix/short-description fix/cors-header-missing
Docs docs/short-description docs/update-api-docs
Refactor refactor/short-description refactor/service-layer
Chore chore/short-description chore/update-dependencies

Commit Messages

Follow Conventional Commits:

feat: add contact form validation
fix: resolve CORS issue on production
docs: update API documentation
refactor: extract service interfaces
chore: update Go dependencies

Pull Requests

  1. Create feature branch from main
  2. Make changes with tests
  3. Run make lint && make test
  4. Push and open PR
  5. Require: CI passing, 1 approval
  6. Squash merge to main

🐛 Debugging

Backend Debugging

# Delve debugger
dlv debug ./cmd/server

# VS Code launch.json
{
  "type": "go",
  "request": "launch",
  "mode": "debug",
  "program": "${workspaceFolder}/cmd/server",
  "env": {
    "SERVER_MODE": "debug"
  }
}

Frontend Debugging

# React DevTools (browser extension)
# Redux DevTools (if using)

# VS Code debug config:
{
  "type": "chrome",
  "request": "launch",
  "url": "http://localhost:5173",
  "webRoot": "${workspaceFolder}/web/src"
}

Database Debugging

# Connect to PostgreSQL
docker compose exec postgres psql -U postgres -d go_first

# Common queries
\dt                    # List tables
\d users               # Describe table
SELECT * FROM skills;  # Query data

📦 Dependency Management

Go Dependencies

# Add dependency
go get github.com/new/package

# Update all
go get -u ./...
go mod tidy

# Check outdated
make check-deps

Frontend Dependencies

# Add dependency
cd web && npm install package-name

# Add dev dependency
cd web && npm install -D package-name

# Update
cd web && npm update

# Audit
cd web && npm audit

🚀 Performance Tips

Backend

  • Use connection pooling (configured in config)
  • Add Redis caching for expensive queries
  • Enable gzip compression (NGINX)
  • Use pprof for profiling: import _ "net/http/pprof"

Frontend

  • Code splitting (Vite does this automatically)
  • Lazy load sections: const Section = lazy(() => import('./Section'))
  • Optimize images (WebP, proper sizing)
  • Use React.memo for expensive components

🔐 Environment Variables

Required for Development

Variable Description Default
SERVER_MODE debug or release debug
DATABASE_HOST PostgreSQL host localhost
DATABASE_PASSWORD PostgreSQL password postgres
JWT_SECRET JWT signing key dev-secret
CORS_ALLOWED_ORIGINS Comma-separated origins http://localhost:3000,http://localhost:5173

Optional

Variable Description
EMAIL_SMTP_* SMTP config for contact form emails
LOGGING_LEVEL debug, info, warn, error
REDIS_* Redis connection (for caching/sessions)

📚 Resources


❓ FAQ

Q: How do I add a new API field? A: Update model → service → handler → frontend types → component

Q: Why is my frontend not updating? A: Check Vite HMR, clear browser cache, check console for errors

Q: How do I test email sending locally? A: Use mock email service (default) or configure Mailhog/SMTP

Q: Can I use a different database? A: Yes, implement repository interface in internal/repository/

Q: How do I deploy a preview environment? A: Use make deploy-staging or create PR preview with GitHub Actions