Coding Standards
Condensed from the 17 standards documents in docs/standards/. See those for full details.
Go
Naming
- Packages: Lowercase, single word (
invoice,generator,handlers) - Files: Lowercase with underscores (
invoice_handler.go,rate_rule.go) - Exported types: PascalCase (
InvoiceService,GenerateRequest) - Unexported: camelCase (
parseHTTPDSN,buildLineItems)
Error Handling
// Always wrap errors with context
if err != nil {
return fmt.Errorf("get invoice %s: %w", id, err)
}
// Check with errors.Is/errors.As, never string comparison
if errors.Is(err, ErrNotFound) {
return nil, ErrNotFound
}
// Sentinel errors per package
var (
ErrNotFound = errors.New("not found")
ErrConflict = errors.New("conflict")
ErrInvalidInput = errors.New("invalid input")
)
// Log at handler level, not deep in services
// Never log AND return the same error
Error → HTTP Mapping
| Error | HTTP Status |
|---|---|
ErrNotFound | 404 |
ErrConflict | 409 |
ErrInvalidInput | 400 |
| Unexpected | 500 |
Context
Every I/O function takes context.Context as the first parameter. Request IDs are propagated via context.
Logging
// slog only, JSON to stdout, snake_case keys
slog.Info("invoice generated",
"component", "generator",
"invoice_id", id.String(),
"deal_type", dealType,
)
// Never log secrets (tokens, passwords, API keys)
Financial Math
// Always use shopspring/decimal for money
amount := decimal.NewFromFloat(15000000.00)
total := amount.Add(overtime)
// Never float64 for financial calculations
Dependencies
Prefer stdlib. Pre-approved packages:
gin(HTTP),pgx/v5(PostgreSQL),clickhouse-go/v2shopspring/decimal(money),google/uuidtestify(testing),golang-migrateprometheus/client_golang,otel(observability)
TypeScript / React
Naming
- Components: PascalCase (
InvoiceRegistry) - Hooks:
use{Name}(useInvoices) - API functions: verb + noun (
fetchInvoices) - Event handlers:
handle{Event}(handleSubmit)
State Management
- React Query for server state (centralized keys in
query-keys.ts) - URL search params for filter state
- React
useStatefor local UI state - Custom hooks in
hooks/
UI
- shadcn/ui primitives in
components/ui/— do not modify sonnerfor toast notifications- Debounce search inputs at 300ms
aria-labelon icon buttonsaria-invalidon form inputs with errors
SQL
PostgreSQL
-- Plural snake_case tables
CREATE TABLE invoices (...);
CREATE TABLE invoice_line_items (...);
-- $1, $2 placeholders (never fmt.Sprintf)
SELECT * FROM invoices WHERE id = $1;
-- Named indexes
CREATE INDEX idx_invoices_status ON invoices(status);
ClickHouse
-- ? placeholders (never string interpolation)
SELECT * FROM tempo.worklogs_flat WHERE project_label IN (?) AND start_date >= ?;
-- Cast types for Go scanning
SELECT toFloat64(deal_amount), ifNull(monthly_limit, 0) FROM cdm.jira_applications;
Migrations
- Format:
{number}_{description}.{up|down}.sql - Every
up.sqlhas a matchingdown.sql - Immutable once merged to main
- Sequential numbering (000001, 000002, ...)