System Design
Purpose
This skill provides the knowledge base for designing and reviewing fullstack applications built with Go (backend) and React (frontend) with PostgreSQL as the data layer. It covers two operating modes:
- Design Mode (Phase 1): Produce a complete system design document from a PRD -- API contracts, database schema, component architecture, and Go project structure.
- Review Mode (Phase 4): Verify implemented code conforms to the design document, flagging deviations, anti-patterns, and missing pieces.
Key Patterns
1. REST API Design (OpenAPI/Swagger)
Endpoint Naming Conventions:
- Use plural nouns for resource collections:
/api/v1/users, /api/v1/projects
- Use path parameters for specific resources:
/api/v1/users/{id}
- Nest related resources max 2 levels deep:
/api/v1/projects/{id}/tasks
- Use query parameters for filtering, sorting, pagination:
?status=active&sort=created_at&order=desc&page=1&limit=20
- API versioning in path prefix:
/api/v1/, /api/v2/
- Use kebab-case for multi-word paths:
/api/v1/user-profiles
HTTP Methods:
| Method |
Purpose |
Idempotent |
Request Body |
Success Code |
| GET |
Retrieve resource(s) |
Yes |
No |
200 |
| POST |
Create resource |
No |
Yes |
201 |
| PUT |
Full replace |
Yes |
Yes |
200 |
| PATCH |
Partial update |
Yes |
Yes |
200 |
| DELETE |
Remove resource |
Yes |
No |
204 |
Standard Status Codes:
200 OK -- Successful GET, PUT, PATCH
201 Created -- Successful POST (include Location header)
204 No Content -- Successful DELETE
400 Bad Request -- Validation errors, malformed input
401 Unauthorized -- Missing or invalid authentication
403 Forbidden -- Authenticated but not authorized
404 Not Found -- Resource does not exist
409 Conflict -- Duplicate resource, version conflict
422 Unprocessable Entity -- Semantically invalid input
500 Internal Server Error -- Unexpected server failure
Standard Error Response Schema:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable description",
"details": [
{
"field": "email",
"message": "must be a valid email address"
}
]
}
}
Pagination Response Envelope:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"total_pages": 8
}
}
2. Database Schema Design (PostgreSQL)
Table Conventions:
- Table names: plural, snake_case (
users, project_tasks)
- Column names: snake_case (
created_at, user_id)
- Every table MUST have:
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
- Soft delete via
deleted_at TIMESTAMPTZ column (nullable, NULL = active)
- Foreign keys always have explicit
ON DELETE clause (CASCADE, SET NULL, or RESTRICT)
- Create indexes on: foreign keys, columns used in WHERE clauses, columns used in ORDER BY, unique constraints
Migration Conventions:
- Sequential numbered files:
001_create_users.up.sql, 001_create_users.down.sql
- Every UP migration has a corresponding DOWN migration
- DOWN migrations must be reversible (drop what UP created)
- Use
golang-migrate/migrate or pressly/goose format
- Never modify existing migrations in production -- create new ones
Common Patterns:
-- Audit columns trigger
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Apply to every table
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON {table_name}
FOR EACH ROW
EXECUTE FUNCTION update_updated_at();
-- Soft delete index (only index active rows)
CREATE INDEX idx_{table}_active ON {table} (id) WHERE deleted_at IS NULL;
Relationship Patterns:
- One-to-many: FK on the "many" side (
user_id UUID REFERENCES users(id))
- Many-to-many: Junction table with composite PK (
user_roles with user_id + role_id)
- One-to-one: FK with UNIQUE constraint
- Self-referential: FK referencing same table (
parent_id UUID REFERENCES categories(id))
3. React Component Architecture
Component Hierarchy:
App
Layout
Header (auth state, navigation)
Sidebar (navigation menu)
Main
Page (route-level, fetches data)
Container (state logic, data transformation)
Presentational (UI rendering, props only)
Component Classification:
- Page Components (
pages/): Route entry points. Own data fetching via hooks. Pass data down.
- Container Components (
containers/): Business logic, state management, API calls. Minimal JSX.
- Presentational Components (
components/): Pure rendering. Props in, JSX out. No side effects.
- Layout Components (
layouts/): Page structure (header, sidebar, footer). Render children.
State Management Strategy:
- Server state: React Query / TanStack Query (caching, refetching, optimistic updates)
- Local UI state:
useState / useReducer (form inputs, toggles, modals)
- Global app state: React Context (auth, theme, feature flags) -- NOT for server data
- URL state: React Router search params (filters, pagination, sort)
Props Flow Rules:
- Props flow DOWN only. Never pass setters more than 2 levels.
- If prop drilling exceeds 2 levels, extract to Context or compose with render props.
- Define explicit TypeScript interfaces for all props.
- Use
children for composition over configuration.
File Naming:
- Components: PascalCase (
UserProfile.tsx, TaskList.tsx)
- Hooks: camelCase with
use prefix (useAuth.ts, useTasks.ts)
- Utils: camelCase (
formatDate.ts, validators.ts)
- Types: PascalCase in dedicated files (
types.ts or User.types.ts)
4. Go Project Structure
Standard Layout (handler -> service -> repository):
cmd/
server/
main.go # Entry point: config, DI, server startup
internal/
config/
config.go # Environment/config loading
handler/
user_handler.go # HTTP handlers (parse request, call service, write response)
user_handler_test.go
middleware.go # Auth, logging, CORS, recovery middleware
service/
user_service.go # Business logic (validation, orchestration, rules)
user_service_test.go
repository/
user_repository.go # Database access (queries, transactions)
user_repository_test.go
model/
user.go # Domain models (structs, enums, constants)
errors.go # Domain error types
dto/
user_dto.go # Request/response DTOs (separate from domain models)
validation.go # DTO validation rules
router/
router.go # Route definitions, middleware chaining
pkg/
response/
response.go # Standard JSON response helpers
pagination/
pagination.go # Pagination parsing and response
migrations/
001_create_users.up.sql
001_create_users.down.sql
api/
openapi.yaml # OpenAPI 3.0 specification
Layer Responsibilities:
| Layer |
Does |
Does NOT |
| Handler |
Parse HTTP request, validate input, call service, write HTTP response |
Contain business logic, access DB directly |
| Service |
Business rules, validation, orchestrate repositories, error wrapping |
Know about HTTP, parse requests, write responses |
| Repository |
SQL queries, scan results into models, manage transactions |
Contain business logic, know about HTTP |
| Model |
Define domain types, constants, domain errors |
Import from handler/service/repository |
| DTO |
Define API request/response shapes, input validation |
Contain business logic |
Dependency Direction:
handler -> service -> repository
| | |
v v v
dto model model
Handlers depend on services. Services depend on repositories. All depend on models. Never reverse this flow.
Interface Pattern (dependency injection):
// Define interface in the CONSUMER package (service defines what it needs from repo)
type UserRepository interface {
GetByID(ctx context.Context, id uuid.UUID) (*model.User, error)
Create(ctx context.Context, user *model.User) error
Update(ctx context.Context, user *model.User) error
Delete(ctx context.Context, id uuid.UUID) error
List(ctx context.Context, filter UserFilter) ([]model.User, int, error)
}
// Implement in the PROVIDER package
type userRepository struct {
db *sql.DB
}
func NewUserRepository(db *sql.DB) UserRepository {
return &userRepository{db: db}
}
Error Handling:
- Define domain errors in
model/errors.go
- Services wrap repository errors with domain context
- Handlers map domain errors to HTTP status codes
- Never expose internal error details to clients
// model/errors.go
var (
ErrNotFound = errors.New("resource not found")
ErrAlreadyExists = errors.New("resource already exists")
ErrForbidden = errors.New("access denied")
)
5. API Contract Definition
Request/Response Type Rules:
- Every endpoint has explicitly defined request and response types
- Request types: only fields the client sends (no
id, no created_at)
- Response types: what the client receives (includes
id, timestamps)
- List endpoints return paginated envelope, not raw arrays
- Use
omitempty on optional fields in Go structs
- Validate requests at the handler/DTO layer, not in services
Go DTO Patterns:
// CreateUserRequest -- POST /api/v1/users
type CreateUserRequest struct {
Email string `json:"email" validate:"required,email"`
Name string `json:"name" validate:"required,min=2,max=100"`
Password string `json:"password" validate:"required,min=8"`
}
// UserResponse -- returned by all user endpoints
type UserResponse struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// ListResponse[T] -- generic paginated response
type ListResponse[T any] struct {
Data []T `json:"data"`
Pagination Pagination `json:"pagination"`
}
TypeScript API Types (frontend mirror):
// types/api.ts
interface CreateUserRequest {
email: string;
name: string;
password: string;
}
interface UserResponse {
id: string;
email: string;
name: string;
created_at: string;
updated_at: string;
}
interface PaginatedResponse<T> {
data: T[];
pagination: {
page: number;
limit: number;
total: number;
total_pages: number;
};
}
6. Code Review Patterns
Conformance Checking (Design vs Implementation):
- Every endpoint in the design doc MUST exist in the router
- Every DB table in the design doc MUST have a migration file
- Every React component in the design doc MUST exist as a file
- Request/response types MUST match the design doc field-for-field
- HTTP methods and status codes MUST match the design doc
Anti-Pattern Detection:
| Anti-Pattern |
What to Flag |
Correct Pattern |
| Fat handler |
Business logic in handler |
Move to service layer |
| Anemic service |
Service just passes through to repo |
Add validation/rules to service |
| Direct DB in handler |
sql.DB used in handler |
Use repository interface |
| God component |
React component > 200 lines |
Split into container + presentational |
| Prop drilling |
Props passed > 2 levels |
Use Context or composition |
| Raw SQL strings |
Unparameterized queries |
Use parameterized queries ($1, $2) |
| Missing error handling |
Unchecked err returns |
Always check and handle errors |
| N+1 queries |
Query in a loop |
Use JOINs or batch queries |
| Hardcoded config |
Connection strings in code |
Use environment variables |
| Missing indexes |
FK columns without indexes |
Add indexes on FK columns |
Severity Levels:
- CRITICAL: Security vulnerability, data loss risk, broken functionality. MUST fix before merge.
- HIGH: Design deviation, missing validation, incorrect status code. Should fix before merge.
- MEDIUM: Anti-pattern, suboptimal structure, missing index. Fix in this PR or next.
- LOW: Style issue, naming convention, minor improvement. Suggestion only.
Conventions
- API-first design: Define endpoints and contracts BEFORE writing code.
- One migration per change: Each schema change gets its own numbered migration pair.
- Interface-driven Go: Define interfaces in consumers, implement in providers.
- Strict layer separation: Handlers never import repositories. Services never import
net/http.
- TypeScript strict mode: All React projects use
"strict": true in tsconfig.
- Explicit error types: No generic error strings. Define typed errors in
model/errors.go.
- Context propagation: Every Go function that does I/O takes
context.Context as first parameter.
- UUID primary keys: Always use UUIDs, never auto-increment integers, for all public-facing IDs.
- Timestamps are UTC: All
TIMESTAMPTZ values stored and transmitted in UTC.
- JSON field naming: Use
snake_case in JSON (Go tags + TypeScript interfaces must match).
Knowledge Strategy
- Patterns to capture: Successful API designs, reusable SQL migration templates, component tree patterns that scaled well, Go error handling chains that worked cleanly.
- Examples to collect: Complete design documents that passed review, review reports that caught real issues, migration sequences that handled complex schema evolution.
- Update permission: Agents may freely add/update files in
references/. Changes to SKILL.md or scripts/ require user approval.
1---2name: system-design3description: System design and code review skill for fullstack Go+React apps. Use when designing architecture or reviewing code against design specifications.4---56# System Design78## Purpose910This skill provides the knowledge base for designing and reviewing fullstack applications built with Go (backend) and React (frontend) with PostgreSQL as the data layer. It covers two operating modes:1112- **Design Mode (Phase 1):** Produce a complete system design document from a PRD -- API contracts, database schema, component architecture, and Go project structure.13- **Review Mode (Phase 4):** Verify implemented code conforms to the design document, flagging deviations, anti-patterns, and missing pieces.1415## Key Patterns1617### 1. REST API Design (OpenAPI/Swagger)1819**Endpoint Naming Conventions:**20- Use plural nouns for resource collections: `/api/v1/users`, `/api/v1/projects`21- Use path parameters for specific resources: `/api/v1/users/{id}`22- Nest related resources max 2 levels deep: `/api/v1/projects/{id}/tasks`23- Use query parameters for filtering, sorting, pagination: `?status=active&sort=created_at&order=desc&page=1&limit=20`24- API versioning in path prefix: `/api/v1/`, `/api/v2/`25- Use kebab-case for multi-word paths: `/api/v1/user-profiles`2627**HTTP Methods:**28| Method | Purpose | Idempotent | Request Body | Success Code |29|--------|---------|------------|--------------|--------------|30| GET | Retrieve resource(s) | Yes | No | 200 |31| POST | Create resource | No | Yes | 201 |32| PUT | Full replace | Yes | Yes | 200 |33| PATCH | Partial update | Yes | Yes | 200 |34| DELETE | Remove resource | Yes | No | 204 |3536**Standard Status Codes:**37- `200 OK` -- Successful GET, PUT, PATCH38- `201 Created` -- Successful POST (include `Location` header)39- `204 No Content` -- Successful DELETE40- `400 Bad Request` -- Validation errors, malformed input41- `401 Unauthorized` -- Missing or invalid authentication42- `403 Forbidden` -- Authenticated but not authorized43- `404 Not Found` -- Resource does not exist44- `409 Conflict` -- Duplicate resource, version conflict45- `422 Unprocessable Entity` -- Semantically invalid input46- `500 Internal Server Error` -- Unexpected server failure4748**Standard Error Response Schema:**49```json50{51 "error": {52 "code": "VALIDATION_ERROR",53 "message": "Human-readable description",54 "details": [55 {56 "field": "email",57 "message": "must be a valid email address"58 }59 ]60 }61}62```6364**Pagination Response Envelope:**65```json66{67 "data": [...],68 "pagination": {69 "page": 1,70 "limit": 20,71 "total": 142,72 "total_pages": 873 }74}75```7677### 2. Database Schema Design (PostgreSQL)7879**Table Conventions:**80- Table names: plural, snake_case (`users`, `project_tasks`)81- Column names: snake_case (`created_at`, `user_id`)82- Every table MUST have: `id UUID PRIMARY KEY DEFAULT gen_random_uuid()`, `created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`, `updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()`83- Soft delete via `deleted_at TIMESTAMPTZ` column (nullable, NULL = active)84- Foreign keys always have explicit `ON DELETE` clause (CASCADE, SET NULL, or RESTRICT)85- Create indexes on: foreign keys, columns used in WHERE clauses, columns used in ORDER BY, unique constraints8687**Migration Conventions:**88- Sequential numbered files: `001_create_users.up.sql`, `001_create_users.down.sql`89- Every UP migration has a corresponding DOWN migration90- DOWN migrations must be reversible (drop what UP created)91- Use `golang-migrate/migrate` or `pressly/goose` format92- Never modify existing migrations in production -- create new ones9394**Common Patterns:**95```sql96-- Audit columns trigger97CREATE OR REPLACE FUNCTION update_updated_at()98RETURNS TRIGGER AS $$99BEGIN100 NEW.updated_at = NOW();101 RETURN NEW;102END;103$$ LANGUAGE plpgsql;104105-- Apply to every table106CREATE TRIGGER set_updated_at107 BEFORE UPDATE ON {table_name}108 FOR EACH ROW109 EXECUTE FUNCTION update_updated_at();110111-- Soft delete index (only index active rows)112CREATE INDEX idx_{table}_active ON {table} (id) WHERE deleted_at IS NULL;113```114115**Relationship Patterns:**116- One-to-many: FK on the "many" side (`user_id UUID REFERENCES users(id)`)117- Many-to-many: Junction table with composite PK (`user_roles` with `user_id` + `role_id`)118- One-to-one: FK with UNIQUE constraint119- Self-referential: FK referencing same table (`parent_id UUID REFERENCES categories(id)`)120121### 3. React Component Architecture122123**Component Hierarchy:**124```125App126 Layout127 Header (auth state, navigation)128 Sidebar (navigation menu)129 Main130 Page (route-level, fetches data)131 Container (state logic, data transformation)132 Presentational (UI rendering, props only)133```134135**Component Classification:**136- **Page Components** (`pages/`): Route entry points. Own data fetching via hooks. Pass data down.137- **Container Components** (`containers/`): Business logic, state management, API calls. Minimal JSX.138- **Presentational Components** (`components/`): Pure rendering. Props in, JSX out. No side effects.139- **Layout Components** (`layouts/`): Page structure (header, sidebar, footer). Render `children`.140141**State Management Strategy:**142- **Server state:** React Query / TanStack Query (caching, refetching, optimistic updates)143- **Local UI state:** `useState` / `useReducer` (form inputs, toggles, modals)144- **Global app state:** React Context (auth, theme, feature flags) -- NOT for server data145- **URL state:** React Router search params (filters, pagination, sort)146147**Props Flow Rules:**148- Props flow DOWN only. Never pass setters more than 2 levels.149- If prop drilling exceeds 2 levels, extract to Context or compose with render props.150- Define explicit TypeScript interfaces for all props.151- Use `children` for composition over configuration.152153**File Naming:**154- Components: PascalCase (`UserProfile.tsx`, `TaskList.tsx`)155- Hooks: camelCase with `use` prefix (`useAuth.ts`, `useTasks.ts`)156- Utils: camelCase (`formatDate.ts`, `validators.ts`)157- Types: PascalCase in dedicated files (`types.ts` or `User.types.ts`)158159### 4. Go Project Structure160161**Standard Layout (handler -> service -> repository):**162```163cmd/164 server/165 main.go # Entry point: config, DI, server startup166internal/167 config/168 config.go # Environment/config loading169 handler/170 user_handler.go # HTTP handlers (parse request, call service, write response)171 user_handler_test.go172 middleware.go # Auth, logging, CORS, recovery middleware173 service/174 user_service.go # Business logic (validation, orchestration, rules)175 user_service_test.go176 repository/177 user_repository.go # Database access (queries, transactions)178 user_repository_test.go179 model/180 user.go # Domain models (structs, enums, constants)181 errors.go # Domain error types182 dto/183 user_dto.go # Request/response DTOs (separate from domain models)184 validation.go # DTO validation rules185 router/186 router.go # Route definitions, middleware chaining187pkg/188 response/189 response.go # Standard JSON response helpers190 pagination/191 pagination.go # Pagination parsing and response192migrations/193 001_create_users.up.sql194 001_create_users.down.sql195api/196 openapi.yaml # OpenAPI 3.0 specification197```198199**Layer Responsibilities:**200201| Layer | Does | Does NOT |202|-------|------|----------|203| Handler | Parse HTTP request, validate input, call service, write HTTP response | Contain business logic, access DB directly |204| Service | Business rules, validation, orchestrate repositories, error wrapping | Know about HTTP, parse requests, write responses |205| Repository | SQL queries, scan results into models, manage transactions | Contain business logic, know about HTTP |206| Model | Define domain types, constants, domain errors | Import from handler/service/repository |207| DTO | Define API request/response shapes, input validation | Contain business logic |208209**Dependency Direction:**210```211handler -> service -> repository212 | | |213 v v v214 dto model model215```216Handlers depend on services. Services depend on repositories. All depend on models. Never reverse this flow.217218**Interface Pattern (dependency injection):**219```go220// Define interface in the CONSUMER package (service defines what it needs from repo)221type UserRepository interface {222 GetByID(ctx context.Context, id uuid.UUID) (*model.User, error)223 Create(ctx context.Context, user *model.User) error224 Update(ctx context.Context, user *model.User) error225 Delete(ctx context.Context, id uuid.UUID) error226 List(ctx context.Context, filter UserFilter) ([]model.User, int, error)227}228229// Implement in the PROVIDER package230type userRepository struct {231 db *sql.DB232}233234func NewUserRepository(db *sql.DB) UserRepository {235 return &userRepository{db: db}236}237```238239**Error Handling:**240- Define domain errors in `model/errors.go`241- Services wrap repository errors with domain context242- Handlers map domain errors to HTTP status codes243- Never expose internal error details to clients244```go245// model/errors.go246var (247 ErrNotFound = errors.New("resource not found")248 ErrAlreadyExists = errors.New("resource already exists")249 ErrForbidden = errors.New("access denied")250)251```252253### 5. API Contract Definition254255**Request/Response Type Rules:**256- Every endpoint has explicitly defined request and response types257- Request types: only fields the client sends (no `id`, no `created_at`)258- Response types: what the client receives (includes `id`, timestamps)259- List endpoints return paginated envelope, not raw arrays260- Use `omitempty` on optional fields in Go structs261- Validate requests at the handler/DTO layer, not in services262263**Go DTO Patterns:**264```go265// CreateUserRequest -- POST /api/v1/users266type CreateUserRequest struct {267 Email string `json:"email" validate:"required,email"`268 Name string `json:"name" validate:"required,min=2,max=100"`269 Password string `json:"password" validate:"required,min=8"`270}271272// UserResponse -- returned by all user endpoints273type UserResponse struct {274 ID uuid.UUID `json:"id"`275 Email string `json:"email"`276 Name string `json:"name"`277 CreatedAt time.Time `json:"created_at"`278 UpdatedAt time.Time `json:"updated_at"`279}280281// ListResponse[T] -- generic paginated response282type ListResponse[T any] struct {283 Data []T `json:"data"`284 Pagination Pagination `json:"pagination"`285}286```287288**TypeScript API Types (frontend mirror):**289```typescript290// types/api.ts291interface CreateUserRequest {292 email: string;293 name: string;294 password: string;295}296297interface UserResponse {298 id: string;299 email: string;300 name: string;301 created_at: string;302 updated_at: string;303}304305interface PaginatedResponse<T> {306 data: T[];307 pagination: {308 page: number;309 limit: number;310 total: number;311 total_pages: number;312 };313}314```315316### 6. Code Review Patterns317318**Conformance Checking (Design vs Implementation):**319- Every endpoint in the design doc MUST exist in the router320- Every DB table in the design doc MUST have a migration file321- Every React component in the design doc MUST exist as a file322- Request/response types MUST match the design doc field-for-field323- HTTP methods and status codes MUST match the design doc324325**Anti-Pattern Detection:**326327| Anti-Pattern | What to Flag | Correct Pattern |328|--------------|-------------|----------------|329| Fat handler | Business logic in handler | Move to service layer |330| Anemic service | Service just passes through to repo | Add validation/rules to service |331| Direct DB in handler | `sql.DB` used in handler | Use repository interface |332| God component | React component > 200 lines | Split into container + presentational |333| Prop drilling | Props passed > 2 levels | Use Context or composition |334| Raw SQL strings | Unparameterized queries | Use parameterized queries (`$1`, `$2`) |335| Missing error handling | Unchecked `err` returns | Always check and handle errors |336| N+1 queries | Query in a loop | Use JOINs or batch queries |337| Hardcoded config | Connection strings in code | Use environment variables |338| Missing indexes | FK columns without indexes | Add indexes on FK columns |339340**Severity Levels:**341- **CRITICAL:** Security vulnerability, data loss risk, broken functionality. MUST fix before merge.342- **HIGH:** Design deviation, missing validation, incorrect status code. Should fix before merge.343- **MEDIUM:** Anti-pattern, suboptimal structure, missing index. Fix in this PR or next.344- **LOW:** Style issue, naming convention, minor improvement. Suggestion only.345346## Conventions3473481. **API-first design:** Define endpoints and contracts BEFORE writing code.3492. **One migration per change:** Each schema change gets its own numbered migration pair.3503. **Interface-driven Go:** Define interfaces in consumers, implement in providers.3514. **Strict layer separation:** Handlers never import repositories. Services never import `net/http`.3525. **TypeScript strict mode:** All React projects use `"strict": true` in tsconfig.3536. **Explicit error types:** No generic error strings. Define typed errors in `model/errors.go`.3547. **Context propagation:** Every Go function that does I/O takes `context.Context` as first parameter.3558. **UUID primary keys:** Always use UUIDs, never auto-increment integers, for all public-facing IDs.3569. **Timestamps are UTC:** All `TIMESTAMPTZ` values stored and transmitted in UTC.35710. **JSON field naming:** Use `snake_case` in JSON (Go tags + TypeScript interfaces must match).358359## Knowledge Strategy360361- **Patterns to capture:** Successful API designs, reusable SQL migration templates, component tree patterns that scaled well, Go error handling chains that worked cleanly.362- **Examples to collect:** Complete design documents that passed review, review reports that caught real issues, migration sequences that handled complex schema evolution.363- **Update permission:** Agents may freely add/update files in `references/`. Changes to `SKILL.md` or `scripts/` require user approval.