# 1.1 Development Environment Setup - Detailed Implementation Plan ## Overview | Attribute | Value | |-----------|-------| | **Priority** | CRITICAL | | **Duration** | 2-3 days | | **Dependencies** | None (first step) | | **Team Size** | 1 developer | ## Objectives 1. Establish a reproducible development environment for all team members 2. Configure Go multi-module monorepo structure 3. Set up frontend workspace with proper tooling 4. Create containerized local infrastructure (PostgreSQL, Redis, Zitadel) 5. Implement consistent linting and formatting standards 6. Document onboarding process --- ## Task Breakdown ### Task 1: Initialize Go Workspace (go.work) **Duration:** 2-3 hours #### 1.1.1 Create Root go.work File Create the Go workspace file at repository root to manage multiple modules. **File:** `/go.work` ```go go 1.25 use ( ./backend/services/game-session-service ./backend/services/question-bank-service ./backend/services/user-service ./backend/services/leaderboard-service ./backend/services/admin-service ./backend/services/gateway-service ./backend/shared ) ``` #### 1.1.2 Initialize Each Service Module For each service, create the go.mod file: **Directory Structure to Create:** ``` backend/ ├── go.work ├── services/ │ ├── game-session-service/ │ │ ├── go.mod │ │ ├── go.sum │ │ └── cmd/ │ │ └── main.go │ ├── question-bank-service/ │ │ ├── go.mod │ │ ├── go.sum │ │ └── cmd/ │ │ └── main.go │ ├── user-service/ │ │ ├── go.mod │ │ ├── go.sum │ │ └── cmd/ │ │ └── main.go │ ├── leaderboard-service/ │ │ ├── go.mod │ │ ├── go.sum │ │ └── cmd/ │ │ └── main.go │ ├── admin-service/ │ │ ├── go.mod │ │ ├── go.sum │ │ └── cmd/ │ │ └── main.go │ └── gateway-service/ │ ├── go.mod │ ├── go.sum │ └── cmd/ │ └── main.go └── shared/ ├── go.mod ├── go.sum └── .gitkeep ``` **Example go.mod for game-session-service:** ```go module knowfoolery/backend/services/game-session-service go 1.25 require ( github.com/gofiber/fiber/v3 v3.0.0 knowfoolery/backend/shared v0.0.0 ) replace knowfoolery/backend/shared => ../../shared ``` **Example go.mod for shared package:** ```go module knowfoolery/backend/shared go 1.25 require ( github.com/rs/zerolog v1.31.0 github.com/go-playground/validator/v10 v10.16.0 github.com/prometheus/client_golang v1.17.0 go.opentelemetry.io/otel v1.21.0 ) ``` #### 1.1.3 Create Stub Main Files **File:** `backend/services/game-session-service/cmd/main.go` ```go package main import ( "log" "github.com/gofiber/fiber/v3" ) func main() { app := fiber.New(fiber.Config{ AppName: "Know Foolery - Game Session Service", }) app.Get("/health", func(c fiber.Ctx) error { return c.JSON(fiber.Map{"status": "healthy", "service": "game-session"}) }) log.Fatal(app.Listen(":8080")) } ``` **Repeat for each service with appropriate port:** | Service | Port | |---------|------| | game-session-service | 8080 | | question-bank-service | 8081 | | user-service | 8082 | | leaderboard-service | 8083 | | admin-service | 8085 | | gateway-service | 8086 | #### Verification Steps: ```bash cd backend go work sync go build ./... ``` --- ### Task 2: Set Up Shared Packages Structure **Duration:** 2-3 hours #### 1.2.1 Create Shared Package Directory Structure ``` backend/shared/ ├── go.mod ├── go.sum ├── domain/ │ ├── errors/ │ │ ├── errors.go # Base error types │ │ └── codes.go # Error code constants │ ├── events/ │ │ ├── event.go # Event interface │ │ └── contracts.go # Event type definitions │ ├── types/ │ │ ├── id.go # ID type wrappers │ │ ├── pagination.go # Pagination types │ │ └── enums.go # Common enums │ └── valueobjects/ │ ├── player_name.go # PlayerName value object │ └── score.go # Score value object └── infra/ ├── auth/ │ ├── zitadel/ │ │ ├── client.go # Zitadel client │ │ └── middleware.go # JWT middleware │ └── rbac/ │ └── roles.go # Role definitions ├── database/ │ ├── postgres/ │ │ └── client.go # PostgreSQL connection factory │ └── redis/ │ └── client.go # Redis connection factory ├── observability/ │ ├── logging/ │ │ └── logger.go # Zerolog setup │ ├── tracing/ │ │ └── tracer.go # OpenTelemetry setup │ └── metrics/ │ └── prometheus.go # Prometheus registration ├── security/ │ └── sanitize.go # Input sanitization └── utils/ ├── httputil/ │ ├── errors.go # HTTP error responses │ ├── response.go # Standard response format │ └── pagination.go # Pagination helpers └── validation/ └── validator.go # Validation helpers ``` #### 1.2.2 Create Placeholder Files Create minimal placeholder implementations for each file to establish the structure. **File:** `backend/shared/domain/errors/errors.go` ```go package errors import "fmt" // DomainError represents a domain-level error type DomainError struct { Code string Message string Err error } func (e *DomainError) Error() string { if e.Err != nil { return fmt.Sprintf("[%s] %s: %v", e.Code, e.Message, e.Err) } return fmt.Sprintf("[%s] %s", e.Code, e.Message) } func (e *DomainError) Unwrap() error { return e.Err } // Common domain errors var ( ErrNotFound = &DomainError{Code: "NOT_FOUND", Message: "Resource not found"} ErrValidation = &DomainError{Code: "VALIDATION", Message: "Validation failed"} ErrUnauthorized = &DomainError{Code: "UNAUTHORIZED", Message: "Unauthorized access"} ErrConflict = &DomainError{Code: "CONFLICT", Message: "Resource conflict"} ErrInternalServer = &DomainError{Code: "INTERNAL", Message: "Internal server error"} ) ``` **File:** `backend/shared/infra/observability/logging/logger.go` ```go package logging import ( "os" "time" "github.com/rs/zerolog" ) // NewLogger creates a new zerolog logger func NewLogger(serviceName, environment string) zerolog.Logger { zerolog.TimeFieldFormat = time.RFC3339Nano var logger zerolog.Logger if environment == "development" { logger = zerolog.New(zerolog.ConsoleWriter{ Out: os.Stdout, TimeFormat: "15:04:05", }).With().Timestamp().Logger() } else { logger = zerolog.New(os.Stdout).With().Timestamp().Logger() } return logger.With(). Str("service", serviceName). Str("environment", environment). Logger() } ``` #### Verification Steps: ```bash cd backend/shared go mod tidy go build ./... ``` --- ### Task 3: Configure Linting (golangci-lint, ESLint) **Duration:** 2-3 hours #### 1.3.1 Backend Linting (golangci-lint) **File:** `backend/.golangci.yml` ```yaml run: timeout: 5m tests: true go: "1.25" linters: enable: - gofmt - goimports - govet - errcheck - staticcheck - unused - gosimple - ineffassign - typecheck - gosec - misspell - lll - unconvert - dupl - goconst - gocyclo - prealloc - bodyclose - noctx - exhaustive linters-settings: lll: line-length: 120 gocyclo: min-complexity: 15 dupl: threshold: 150 goconst: min-len: 3 min-occurrences: 3 misspell: locale: US gosec: excludes: - G104 # Unhandled errors (we use errcheck) issues: exclude-rules: - path: _test\.go linters: - gocyclo - errcheck - dupl - gosec - path: cmd/main\.go linters: - gocyclo max-issues-per-linter: 50 max-same-issues: 10 ``` #### 1.3.2 Frontend Linting (ESLint) **File:** `frontend/.eslintrc.json` ```json { "root": true, "env": { "browser": true, "es2022": true, "node": true }, "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:solid/recommended", "prettier" ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "plugins": [ "@typescript-eslint", "solid" ], "rules": { "@typescript-eslint/explicit-function-return-type": "warn", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-explicit-any": "warn", "prefer-const": "error", "no-var": "error", "object-shorthand": "error", "prefer-template": "error", "no-console": ["warn", { "allow": ["warn", "error"] }] }, "ignorePatterns": [ "dist", "node_modules", "*.config.js", "*.config.ts" ] } ``` **File:** `frontend/.prettierrc` ```json { "semi": false, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "printWidth": 100, "bracketSpacing": true } ``` #### 1.3.3 Editor Configuration **File:** `.editorconfig` (repository root) ```ini root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.go] indent_style = tab indent_size = 4 [*.md] trim_trailing_whitespace = false [Makefile] indent_style = tab ``` #### Verification Steps: ```bash # Backend cd backend golangci-lint run ./... # Frontend cd frontend npx eslint . --ext .ts,.tsx npx prettier --check . ``` --- ### Task 4: Create Docker Compose for Local Development **Duration:** 3-4 hours #### 1.4.1 Development Docker Compose **File:** `infrastructure/dev/docker-compose.yml` ```yaml version: "3.9" services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: knowfoolery-postgres environment: POSTGRES_USER: knowfoolery POSTGRES_PASSWORD: devpassword POSTGRES_DB: knowfoolery ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d healthcheck: test: ["CMD-SHELL", "pg_isready -U knowfoolery -d knowfoolery"] interval: 10s timeout: 5s retries: 5 networks: - knowfoolery-network # Redis Cache redis: image: redis:7-alpine container_name: knowfoolery-redis ports: - "6379:6379" volumes: - redis_data:/data command: redis-server --appendonly yes healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 networks: - knowfoolery-network # Zitadel Authentication (optional for initial setup) zitadel: image: ghcr.io/zitadel/zitadel:latest container_name: knowfoolery-zitadel command: start-from-init --masterkeyFromEnv --tlsMode disabled environment: ZITADEL_MASTERKEY: "MasterkeyNeedsToHave32Characters" ZITADEL_DATABASE_COCKROACH_HOST: crdb ZITADEL_EXTERNALSECURE: false ZITADEL_FIRSTINSTANCE_ORG_NAME: "KnowFoolery" ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME: "admin" ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD: "AdminPassword123!" ports: - "8080:8080" depends_on: crdb: condition: service_healthy networks: - knowfoolery-network profiles: - auth # CockroachDB for Zitadel crdb: image: cockroachdb/cockroach:latest container_name: knowfoolery-crdb command: start-single-node --insecure --http-addr :9090 ports: - "26257:26257" - "9090:9090" volumes: - crdb_data:/cockroach/cockroach-data healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9090/health?ready=1"] interval: 10s timeout: 5s retries: 10 networks: - knowfoolery-network profiles: - auth # Prometheus Metrics prometheus: image: prom/prometheus:latest container_name: knowfoolery-prometheus ports: - "9091:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.enable-lifecycle' networks: - knowfoolery-network profiles: - observability # Grafana Dashboards grafana: image: grafana/grafana:latest container_name: knowfoolery-grafana ports: - "3001:3000" environment: GF_SECURITY_ADMIN_USER: admin GF_SECURITY_ADMIN_PASSWORD: admin GF_USERS_ALLOW_SIGN_UP: false volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning depends_on: - prometheus networks: - knowfoolery-network profiles: - observability # Jaeger Tracing jaeger: image: jaegertracing/all-in-one:latest container_name: knowfoolery-jaeger ports: - "16686:16686" # UI - "14268:14268" # Collector HTTP - "6831:6831/udp" # Agent environment: COLLECTOR_ZIPKIN_HOST_PORT: ":9411" networks: - knowfoolery-network profiles: - observability volumes: postgres_data: redis_data: crdb_data: prometheus_data: grafana_data: networks: knowfoolery-network: driver: bridge ``` #### 1.4.2 Database Initialization Script **File:** `infrastructure/dev/init-scripts/01-create-databases.sql` ```sql -- Create separate databases for each service CREATE DATABASE IF NOT EXISTS game_sessions; CREATE DATABASE IF NOT EXISTS questions; CREATE DATABASE IF NOT EXISTS users; CREATE DATABASE IF NOT EXISTS leaderboards; CREATE DATABASE IF NOT EXISTS admin; -- Grant privileges GRANT ALL PRIVILEGES ON DATABASE game_sessions TO knowfoolery; GRANT ALL PRIVILEGES ON DATABASE questions TO knowfoolery; GRANT ALL PRIVILEGES ON DATABASE users TO knowfoolery; GRANT ALL PRIVILEGES ON DATABASE leaderboards TO knowfoolery; GRANT ALL PRIVILEGES ON DATABASE admin TO knowfoolery; ``` #### 1.4.3 Prometheus Configuration **File:** `infrastructure/dev/prometheus/prometheus.yml` ```yaml global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'game-session-service' static_configs: - targets: ['host.docker.internal:8080'] metrics_path: /metrics - job_name: 'question-bank-service' static_configs: - targets: ['host.docker.internal:8081'] metrics_path: /metrics - job_name: 'user-service' static_configs: - targets: ['host.docker.internal:8082'] metrics_path: /metrics - job_name: 'leaderboard-service' static_configs: - targets: ['host.docker.internal:8083'] metrics_path: /metrics - job_name: 'gateway-service' static_configs: - targets: ['host.docker.internal:8086'] metrics_path: /metrics ``` #### 1.4.4 Environment Variables **File:** `infrastructure/dev/.env` ```bash # Database POSTGRES_USER=knowfoolery POSTGRES_PASSWORD=knowfoolery POSTGRES_HOST=localhost POSTGRES_PORT=5432 POSTGRES_DB=knowfoolery # Redis REDIS_HOST=localhost REDIS_PORT=6379 # Zitadel (when auth profile is enabled) ZITADEL_URL=http://localhost:8080 ZITADEL_PROJECT_ID=your-project-id ZITADEL_CLIENT_ID=your-client-id # Environment ENVIRONMENT=development LOG_LEVEL=debug # Service Ports GAME_SESSION_PORT=8080 QUESTION_BANK_PORT=8081 USER_SERVICE_PORT=8082 LEADERBOARD_PORT=8083 ADMIN_SERVICE_PORT=8085 GATEWAY_PORT=8086 ``` #### Verification Steps: ```bash cd infrastructure/dev docker-compose up -d postgres redis docker-compose ps docker-compose logs postgres ``` --- ### Task 5: Initialize Frontend Workspace (Yarn Workspaces) **Duration:** 2-3 hours #### 1.5.1 Root Package Configuration **File:** `frontend/package.json` ```json { "name": "knowfoolery-frontend", "private": true, "workspaces": [ "shared/*", "apps/*" ], "scripts": { "dev": "yarn workspace @knowfoolery/web dev", "build": "yarn workspaces foreach -A run build", "lint": "eslint . --ext .ts,.tsx", "lint:fix": "eslint . --ext .ts,.tsx --fix", "format": "prettier --write .", "format:check": "prettier --check .", "test": "yarn workspaces foreach -A run test", "clean": "yarn workspaces foreach -A run clean" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.0.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-solid": "^0.13.0", "prettier": "^3.0.0", "typescript": "^5.0.0" }, "packageManager": "yarn@4.0.0" } ``` Note: Yarn is configured to use `nodeLinker: node-modules` (no PnP files). #### 1.5.2 Web Application Package **File:** `frontend/apps/web/package.json` ```json { "name": "@knowfoolery/web", "private": true, "version": "0.0.1", "type": "module", "scripts": { "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", "test": "vitest", "clean": "rm -rf dist node_modules/.vite" }, "dependencies": { "solid-js": "^1.9.0", "@solidjs/router": "^0.10.0", "@suid/material": "^0.16.0", "@suid/icons-material": "^0.7.0" }, "devDependencies": { "vite": "^5.0.0", "vite-plugin-solid": "^2.8.0", "vitest": "^1.0.0", "@solidjs/testing-library": "^0.8.0" } } ``` **File:** `frontend/apps/web/vite.config.ts` ```typescript import { defineConfig } from 'vite' import solid from 'vite-plugin-solid' export default defineConfig({ plugins: [solid()], server: { port: 3000, proxy: { '/api': { target: 'http://localhost:8086', changeOrigin: true, }, }, }, build: { target: 'esnext', }, }) ``` **File:** `frontend/apps/web/tsconfig.json` ```json { "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "jsx": "preserve", "jsxImportSource": "solid-js", "types": ["vite/client"], "noEmit": true, "isolatedModules": true, "strict": true, "skipLibCheck": true, "resolveJsonModule": true, "baseUrl": ".", "paths": { "@/*": ["src/*"], "@shared/*": ["../../shared/*"] } }, "include": ["src"] } ``` **File:** `frontend/apps/web/index.html` ```html Know Foolery - Quiz Game
``` **File:** `frontend/apps/web/src/main.tsx` ```typescript import { render } from 'solid-js/web' import App from './App' import './styles/global.css' const root = document.getElementById('root') if (!root) { throw new Error('Root element not found') } render(() => , root) ``` **File:** `frontend/apps/web/src/App.tsx` ```typescript import type { Component } from 'solid-js' const App: Component = () => { return (

Know Foolery

Quiz game coming soon...

) } export default App ``` **File:** `frontend/apps/web/src/styles/global.css` ```css :root { font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; line-height: 1.5; font-weight: 400; color-scheme: light dark; color: rgba(255, 255, 255, 0.87); background-color: #242424; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } * { box-sizing: border-box; margin: 0; padding: 0; } #root { max-width: 1280px; margin: 0 auto; padding: 2rem; } ``` #### 1.5.3 Shared UI Components Package **File:** `frontend/shared/ui-components/package.json` ```json { "name": "@knowfoolery/ui-components", "private": true, "version": "0.0.1", "type": "module", "main": "src/index.ts", "scripts": { "test": "vitest", "build": "echo 'No build needed for shared package'", "clean": "echo 'Nothing to clean'" }, "dependencies": { "solid-js": "^1.9.0", "@suid/material": "^0.16.0" }, "devDependencies": { "vitest": "^1.0.0" }, "peerDependencies": { "solid-js": "^1.9.0" } } ``` **File:** `frontend/shared/ui-components/src/index.ts` ```typescript // UI Components barrel export // Components will be added as they are developed export {} ``` #### Verification Steps: ```bash cd frontend yarn install yarn dev # Open http://localhost:3000 ``` --- ### Task 6: Create Makefile for Development Commands **Duration:** 1-2 hours **File:** `Makefile` (repository root) ```makefile .PHONY: help dev dev-full dev-auth dev-obs stop clean \ backend-lint backend-test backend-build \ frontend-lint frontend-test frontend-build \ db-up db-down db-logs db-shell redis-shell \ lint test build # Default target help: @echo "KnowFoolery Development Commands" @echo "" @echo "Development Environment:" @echo " make dev - Start core infrastructure (PostgreSQL, Redis)" @echo " make dev-full - Start all infrastructure including observability" @echo " make dev-auth - Start infrastructure with Zitadel auth" @echo " make stop - Stop all containers" @echo " make clean - Stop containers and remove volumes" @echo "" @echo "Backend:" @echo " make backend-lint - Run Go linters" @echo " make backend-test - Run Go tests" @echo " make backend-build - Build all services" @echo "" @echo "Frontend:" @echo " make frontend-dev - Start frontend dev server" @echo " make frontend-lint - Run ESLint and Prettier" @echo " make frontend-test - Run frontend tests" @echo " make frontend-build - Build frontend for production" @echo "" @echo "Database:" @echo " make db-logs - Show PostgreSQL logs" @echo " make db-shell - Open PostgreSQL shell" @echo " make redis-shell - Open Redis CLI" @echo "" @echo "All:" @echo " make lint - Run all linters" @echo " make test - Run all tests" @echo " make build - Build everything" # ============================================================================= # Development Environment # ============================================================================= dev: @echo "Starting core infrastructure..." cd infrastructure/dev && docker-compose up -d postgres redis @echo "Waiting for services to be healthy..." @sleep 5 @echo "" @echo "Infrastructure ready:" @echo " PostgreSQL: localhost:5432 (user: knowfoolery, password: devpassword)" @echo " Redis: localhost:6379" dev-full: dev @echo "Starting observability stack..." cd infrastructure/dev && docker-compose --profile observability up -d @echo "" @echo "Observability ready:" @echo " Prometheus: http://localhost:9091" @echo " Grafana: http://localhost:3001 (admin/admin)" @echo " Jaeger: http://localhost:16686" dev-auth: @echo "Starting full stack with authentication..." cd infrastructure/dev && docker-compose --profile auth up -d @echo "" @echo "Zitadel ready at http://localhost:8080" @echo "Admin credentials: admin / AdminPassword123!" stop: @echo "Stopping all containers..." cd infrastructure/dev && docker-compose --profile auth --profile observability down clean: @echo "Stopping containers and removing volumes..." cd infrastructure/dev && docker-compose --profile auth --profile observability down -v # ============================================================================= # Backend # ============================================================================= backend-lint: @echo "Running Go linters..." cd backend && golangci-lint run ./... backend-test: @echo "Running Go tests..." cd backend && go test -v -race -cover ./... backend-build: @echo "Building all services..." cd backend && go build ./... # ============================================================================= # Frontend # ============================================================================= frontend-dev: @echo "Starting frontend development server..." cd frontend && yarn dev frontend-lint: @echo "Running frontend linters..." cd frontend && yarn lint && yarn format:check frontend-test: @echo "Running frontend tests..." cd frontend && yarn test frontend-build: @echo "Building frontend..." cd frontend && yarn build # ============================================================================= # Database Utilities # ============================================================================= db-logs: cd infrastructure/dev && docker-compose logs -f postgres db-shell: docker exec -it knowfoolery-postgres psql -U knowfoolery -d knowfoolery redis-shell: docker exec -it knowfoolery-redis redis-cli # ============================================================================= # Combined Commands # ============================================================================= lint: backend-lint frontend-lint @echo "All linters passed!" test: backend-test frontend-test @echo "All tests passed!" build: backend-build frontend-build @echo "Build complete!" ``` --- ### Task 7: Create Developer Onboarding Documentation **Duration:** 1-2 hours **File:** `docs/DEVELOPMENT.md` ```markdown # KnowFoolery Development Guide ## Prerequisites Before you begin, ensure you have the following installed: | Tool | Version | Installation | |------|---------|--------------| | Go | 1.25+ | https://go.dev/dl/ | | Node.js | 20+ | https://nodejs.org/ or use nvm | | Yarn | 4.x | `corepack enable` | | Docker | 24+ | https://docs.docker.com/get-docker/ | | Docker Compose | 2.x | Included with Docker Desktop | | golangci-lint | latest | `go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest` | ## Quick Start ### 1. Clone the Repository ```bash git clone https://gitea.paas.celticinfo.fr/oabrivard/knowfoolery.git cd knowfoolery ``` ### 2. Start Infrastructure ```bash # Start PostgreSQL and Redis make dev # Or start everything including observability make dev-full ``` ### 3. Install Dependencies ```bash # Backend cd backend go mod download # Frontend cd frontend yarn install ``` ### 4. Start Development Servers **Backend Services** (run each in a separate terminal): ```bash cd backend/services/game-session-service && go run cmd/main.go cd backend/services/question-bank-service && go run cmd/main.go # ... repeat for other services ``` **Frontend**: ```bash cd frontend yarn dev ``` ### 5. Access the Application - **Web App**: http://localhost:3000 - **API Gateway**: http://localhost:8086 - **Prometheus** (if running): http://localhost:9091 - **Grafana** (if running): http://localhost:3001 - **Jaeger** (if running): http://localhost:16686 ## Project Structure ``` knowfoolery/ ├── backend/ │ ├── go.work # Go workspace file │ ├── shared/ # Shared packages │ └── services/ # Microservices ├── frontend/ │ ├── package.json # Yarn workspace root │ ├── apps/ # Applications (web, cross-platform) │ └── shared/ # Shared components ├── infrastructure/ │ └── dev/ # Docker Compose for local dev ├── docs/ # Documentation └── Makefile # Development commands ``` ## Common Commands | Command | Description | |---------|-------------| | `make help` | Show all available commands | | `make dev` | Start core infrastructure | | `make dev-full` | Start infrastructure + observability | | `make lint` | Run all linters | | `make test` | Run all tests | | `make stop` | Stop all containers | | `make clean` | Stop containers and remove data | ## Environment Variables Copy the example environment file: ```bash cp infrastructure/dev/.env.example infrastructure/dev/.env ``` ## Database Access ### PostgreSQL ```bash # Via make command make db-shell # Or directly docker exec -it knowfoolery-postgres psql -U knowfoolery -d knowfoolery ``` ### Redis ```bash # Via make command make redis-shell # Or directly docker exec -it knowfoolery-redis redis-cli ``` ## Troubleshooting ### Port Conflicts If you get port conflict errors: 1. Check what's using the port: `lsof -i :5432` 2. Stop the conflicting service or change ports in docker-compose.yml ### Docker Memory Issues If containers are slow or crashing: 1. Increase Docker Desktop memory allocation (Settings > Resources) 2. Recommended: 4GB+ RAM ### Go Module Issues ```bash cd backend go work sync go mod tidy ``` ### Frontend Build Issues ```bash cd frontend rm -rf node_modules yarn cache clean yarn install ``` ## IDE Setup ### VS Code Recommended extensions: - Go (golang.go) - ESLint - Prettier - Docker - YAML ### GoLand/IntelliJ 1. Open the `backend` folder as your Go project 2. Enable "Go Modules integration" 3. Set GOROOT to your Go 1.25+ installation ## Contributing 1. Create a feature branch: `git checkout -b feature/my-feature` 2. Make your changes 3. Run linters: `make lint` 4. Run tests: `make test` 5. Commit with conventional commits: `git commit -m "feat: add new feature"` 6. Push and create a PR ``` --- ## Deliverables Checklist | Deliverable | Status | Notes | |-------------|--------|-------| | Go workspace (go.work) | [ ] | Multi-module monorepo | | Service module stubs | [ ] | 6 services with health endpoints | | Shared packages structure | [ ] | domain/ and infra/ directories | | golangci-lint config | [ ] | .golangci.yml | | ESLint + Prettier config | [ ] | .eslintrc.json, .prettierrc | | EditorConfig | [ ] | .editorconfig | | Docker Compose (dev) | [ ] | PostgreSQL, Redis, optional stacks | | Makefile | [ ] | Development commands | | Developer documentation | [ ] | DEVELOPMENT.md | --- ## Verification Checklist ### Backend Verification ```bash # 1. Go workspace builds cd backend && go build ./... # 2. Linter runs without config errors cd backend && golangci-lint run ./... # 3. All modules resolve correctly cd backend && go work sync ``` ### Frontend Verification ```bash # 1. Dependencies install cd frontend && yarn install # 2. Dev server starts cd frontend && yarn dev # 3. Linters pass cd frontend && yarn lint ``` ### Infrastructure Verification ```bash # 1. Docker Compose starts cd infrastructure/dev && docker-compose up -d postgres redis # 2. PostgreSQL is accessible docker exec knowfoolery-postgres pg_isready -U knowfoolery # 3. Redis is accessible docker exec knowfoolery-redis redis-cli ping ``` --- ## Estimated Time Breakdown | Task | Duration | Cumulative | |------|----------|------------| | Task 1: Go Workspace | 2-3 hours | 3 hours | | Task 2: Shared Packages | 2-3 hours | 6 hours | | Task 3: Linting Config | 2-3 hours | 9 hours | | Task 4: Docker Compose | 3-4 hours | 13 hours | | Task 5: Frontend Workspace | 2-3 hours | 16 hours | | Task 6: Makefile | 1-2 hours | 18 hours | | Task 7: Documentation | 1-2 hours | 20 hours | | **Buffer & Testing** | 4 hours | **24 hours (3 days)** | --- ## Next Steps After Completion Once this phase is complete, proceed to: - **Phase 1.2**: Implement shared backend packages (errors, logging, metrics, tracing) - Begin development of Question Bank Service (Phase 2.1)