# 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](https://docker.com) | | Git | 2.40+ | `brew install git` / `apt install git` | ### Recommended Tools - **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 ```bash 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 ```bash # 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 ```bash cp .env.local.example .env.local # Edit if needed (defaults work for Docker databases) vim .env.local ``` ### 4. Run Development Servers ```bash # 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 ```bash # 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 ```bash # 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 ```bash # Generate mocks for testing make generate # This runs: go generate ./... # Uses: github.com/golang/mock/mockgen ``` --- ## ๐Ÿงช Testing ### Backend Tests ```bash # 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 ```bash # 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) ```bash # Install Playwright cd web && npx playwright install # Run E2E tests cd web && npm run test:e2e ``` --- ## ๐Ÿ” Code Quality ### Linting ```bash # All linters make lint # Backend only make lint-backend # Runs: golangci-lint run ./... # Frontend only make lint-frontend # Runs: eslint + prettier check ``` ### Formatting ```bash # Format all code make fmt # Backend go fmt ./... goimports -w . # Frontend cd web && npm run format ``` ### Pre-commit Hooks ```bash # Install pre-commit pip install pre-commit pre-commit install # Run manually pre-commit run --all-files ``` #### `.pre-commit-config.yaml` ```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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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`: ```yaml 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 ```bash # Use lucide-react (already installed) import { IconName } from 'lucide-react' # Or add to public/ and use ``` --- ## ๐Ÿ”ง 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: ```go 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 ```go 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](https://www.conventionalcommits.org/): ``` 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # Add dependency go get github.com/new/package # Update all go get -u ./... go mod tidy # Check outdated make check-deps ``` ### Frontend Dependencies ```bash # 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 - [Go Project Layout](https://github.com/golang-standards/project-layout) - [Effective Go](https://go.dev/doc/effective_go) - [React Beta Docs](https://react.dev) - [Tailwind CSS Docs](https://tailwindcss.com/docs) - [Gin Framework](https://gin-gonic.com/docs/) - [Zerolog](https://github.com/rs/zerolog) - [Vite Guide](https://vitejs.dev/guide/) --- ## โ“ 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