Files
DivaCode/The Holy Code Bible.md

40 KiB

id, aliases, tags
id aliases tags
The Holy Code Bible

"Bestowed upon the Devs by the Eternal Syntax, to bring order to the chaos of code."


1. The Law of Variables and Functions

"Name with purpose, type with faith, validate without doubt."

Realm Naming Form Divine Guidance
Go camelCase Exported → PascalCase (UserService), unexported → camelCase (userService)
TypeScript camelCase Strict types everywhere. No any. Prefer interface over type for objects.
Constants PascalCase (Go), UPPER_CASE (TS) Go: constants are PascalCase if exported. TS: UPPER_CASE for module-level constants.

Go Edicts

  • Exported identifiers are PascalCase. Unexported are camelCase.
  • Acronyms are all-caps: HTTPHandler, UserID, parseJSON.
  • No snake_case in Go identifiers. Ever.
  • Use short variable names for short scopes (i, n, err).
  • Prefer var for zero-value declarations, := for initialization.
  • Always handle errors. No silent discards.

TypeScript Edicts

  • Prefer const over let. No var.
  • Never use any. Use unknown if type is truly unknown.
  • Use strict: true in tsconfig. No exceptions.
  • Never use ==, always ===.
  • Use interface for object shapes, type for unions/primitives.
  • Use as const for literal types and enums.
  • Validate input at function boundaries with Zod or similar.

2. The Law of Structure (HTML, CSS, Tailwind)

"Let your style be clean and your markup semantic."

Type Style Notes
HTML classes kebab-case Matches query selectors
IDs kebab-case Reserved for unique elements
File names kebab-case Components, pages, layouts
Tailwind utility classes No custom CSS if Tailwind utility exists

Sacred Guidelines

  • Class names must be semantic and reusable.
  • IDs reserved for unique elements and anchor targets.
  • No inline styles within templates — Tailwind utilities only.
  • Custom CSS lives in assets/css/ with kebab-case filenames.
  • Tailwind theme is centralized in tailwind.config.ts. No arbitrary values ([color]) in templates unless absolutely necessary.
  • Prefer Tailwind's @apply in component classes only for repeated patterns.
  • Responsive design first: mobile-first with Tailwind breakpoints.

3. The Law of Files and Folders

"Order in structure is order in mind; chaos begins at the root."

Go Backend Layout

service-name/
├── cmd/
│   └── server/
│       └── main.go          # Entrypoint only
├── internal/
│   ├── handler/              # HTTP handlers (1 file per resource)
│   ├── service/              # Business logic
│   ├── repository/           # Database access
│   ├── middleware/            # Auth, logging, CORS, rate limiting
│   ├── dto/                  # Request/response types
│   ├── model/                # Domain models
│   └── config/               # Config struct + loader
├── migrations/                # SQL migration files
├── pkg/                      # Shared library (if re-usable outside)
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── Makefile
└── README.md

Nuxt/Vue Frontend Layout

frontend/
├── app.vue                   # Root component
├── nuxt.config.ts
├── tailwind.config.ts
├── pages/                    # File-based routing
│   ├── index.vue
│   ├── video/
│   │   ├── index.vue
│   │   └── [id].vue
│   └── blog/
├── components/
│   ├── shared/               # Reusable: Button, Input, Modal
│   └── <domain>/             # Page-specific: video/Player.vue
├── composables/              # useApi, useAuth, usePagination
├── stores/                   # Pinia stores: useAuthStore
├── types/                    # TypeScript interfaces
├── assets/
│   ├── css/                  # Custom CSS files
│   └── images/
├── public/
├── server/                   # API routes or middleware (Nuxt server)
├── .env.example
└── README.md

Library Package Layout (e.g., video player, blog editor)

package-name/
├── src/
│   ├── index.ts              # Public API
│   ├── components/
│   ├── types/
│   └── utils/
├── dist/                     # Built output
├── package.json
├── tsconfig.json
├── vite.config.ts            # or tsup.config.ts
├── README.md
└── LICENSE

4. The Immutable Rules of Naming

"A name unspoken in truth shall summon bugs."

Context Style Example
Go variables/functions (unexported) camelCase getUser, parseToken
Go functions/types (exported) PascalCase GetUser, UserService
Go acronyms ALL CAPS HTTPHandler, UserID, parseJSON
Go files snake_case user_handler.go, auth_middleware.go
Go tests snake_case user_handler_test.go
TypeScript variables/functions camelCase getUser, parseToken
TypeScript types/interfaces PascalCase UserResponse, AuthPayload
Component files PascalCase VideoPlayer.vue, BlogEditor.vue
Component names PascalCase <VideoPlayer />, <BlogEditor />
CSS classes / IDs kebab-case video-container, main-header
CSS/Tailwind files kebab-case custom-styles.css
Constants (Go exported) PascalCase MaxRetryCount
Constants (Go unexported) camelCase maxRetryCount
Constants (TS) UPPER_CASE MAX_RETRY_COUNT
Enums (TS) PascalCase members Status.Active, Role.Admin
DB tables/columns snake_case users, video_id, created_at
JSON fields camelCase "userId", "videoUrl"
Environment variables UPPER_SNAKE_CASE DATABASE_URL, REDIS_HOST
Docker image tags lowercase auth-service:1.0.0
Git branches kebab-case feat/video-transcoding, fix/auth-timeout
Git commits Conventional Commits feat: add video upload endpoint
Repository names kebab-case video-service, nuxt-commons

One naming style per context, no deviation. Filenames must mirror their contents exactly. No spaces or special characters.


5. The Scroll of Static Typing

"Types are truth — doubt them and runtime will punish thee."

Go

package user

import "time"

type User struct {
    ID        string    `json:"id"`
    Email     string    `json:"email"`
    Name      string    `json:"name"`
    CreatedAt time.Time `json:"createdAt"`
}

// GetUser returns a user by ID.
// Returns ErrNotFound if the user does not exist.
func GetUser(id string) (*User, error) {
    // ...
}
  • Every function returns error when it can fail.
  • Use error interface, not custom exception types.
  • Wrap errors: fmt.Errorf("get user %s: %w", id, err).
  • Use errors.Is() and errors.As() for error inspection.
  • Define sentinel errors: var ErrNotFound = errors.New("user not found").

TypeScript

interface User {
  id: string;
  email: string;
  name: string;
  createdAt: string; // ISO 8601
}

// Use Zod for runtime validation
import { z } from "zod";

const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
});

type CreateUserInput = z.infer<typeof CreateUserSchema>;

async function createUser(input: CreateUserInput): Promise<User> {
  const validated = CreateUserSchema.parse(input);
  // validated is fully typed
}
  • strict: true in tsconfig at all times.
  • No any. Use unknown + type narrowing.
  • Prefer interface over type for object types.
  • Use type for unions, intersections, and primitives.
  • All API responses have a corresponding TypeScript type in ~/types/.
  • Use Zod for runtime validation of API inputs and env vars.

6. The Ten Commandments of Clean Code

"Clean code is the only code that survives the test of time."

  1. One responsibility per function, per type, per file.
  2. Comment only to explain why, never what.
  3. No silent errors — handle or propagate every error.
  4. Always validate and sanitize all input at the boundary.
  5. No global state — use dependency injection.
  6. Never push secrets, configs, or build artifacts.
  7. Consistency outranks cleverness — write boring code.
  8. Fail fast, log properly, recover gracefully.
  9. No unused code, no dead branches, no commented-out blocks.
  10. Every public API must have a meaningful comment explaining what it does.

7. The Standard of the File Header

"Every file must declare its origin before it speaks."

Go

// Package handler provides HTTP handlers for the auth service.
package handler

import (
    "net/http"
)

Go files need only the package comment at the top. No author/date boilerplate — Git already has that.

TypeScript/Vue

/**
 * File: VideoPlayer.vue
 * Purpose: Hand-written video player with HLS.js and WebRTC/WHEP support.
 * See: https://git.db123.ir/db/VP
 */

TypeScript/Vue files benefit from a brief purpose comment if the purpose isn't obvious from the name.


8. The Law of Comments

"Explain not the obvious, but the reason behind the mystery."

// GOOD: explains why
// Refresh the token 5 minutes before expiry to avoid race conditions.
if time.Until(token.ExpiresAt) < 5*time.Minute {
    token, err = refreshToken(token)
}

// BAD: restates the obvious
// Check if token is about to expire
if time.Until(token.ExpiresAt) < 5*time.Minute {

Same rule applies to TypeScript, Vue, CSS, and all languages:

  • Explain intent and context, not syntax.
  • No comments for self-documenting code.
  • TODO comments must include a ticket/issue reference: // TODO(db123): handle pagination limits (PROJ-42).

9. The Law of Strictness (Go)

"Without strictness, your logic shall wander."

package main

import (
    "log/slog"
)

func main() {
    slog.SetLogLoggerLevel(slog.LevelDebug)
    // ...
}
  • Run go vet ./... before every commit.
  • Use golangci-lint in CI with strict configuration.
  • CGO_ENABLED=0 for production builds.
  • No panic outside of main and initialization.
  • Use errgroup or sync.WaitGroup for goroutine management. Never use time.Sleep for synchronization.
  • Always set -race in tests and CI.

10. The Law of Strictness (TypeScript)

"An untyped variable is a vessel for chaos."

// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "exactOptionalPropertyTypes": true,
    "forceConsistentCasingInFileNames": true,
  },
}
  • ESLint with @typescript-eslint/strict config.
  • Prettier for formatting — run prettier --check in CI.
  • TypeScript 5.x+ with --strict mode. No // @ts-ignore or // @ts-expect-error without a comment explaining why.
  • Use satisfies operator for type-safe expressions without widening.

11. The Law of Security

"Trust no input, for deceit lives in every form field."

General

  • Never trust user input. Validate and sanitize at every boundary.
  • Always use prepared statements for SQL. Never concatenate query strings.
  • Escape all HTML output. Use template engines that auto-escape.
  • Validate on both client and server.
  • Rate limit all public endpoints.
  • Disable error display in production. Log instead.
  • Never expose .env, secrets, or stack traces to the client.
  • Use TLS everywhere. Auto-renew via Let's Encrypt.

Go Specific

  • Use httputil for reverse proxy security.
  • Set X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy headers.
  • Use bcrypt or argon2 for password hashing. Never SHA/MD5.
  • Validate UUIDs with uuid.Parse() before DB queries.

TypeScript Specific

  • Sanitize user input before rendering with DOMPurify.
  • Never use innerHTML with user content. Use textContent or Vue's template binding.
  • For Nuxt: validate API responses with Zod on the client side.

12. The Law of Git

"Commits are confessions — be honest, be precise."

  • Commit atomic changes only.
  • Branch names → kebab-case.
  • One purpose per branch (feature, fix, etc).
  • Commit format:
<type>(<scope>): <description>

[optional body]

[optional footer]

Types:

  • feat: — New feature
  • fix: — Bug fix
  • docs: — Documentation only
  • style: — Formatting, no logic change
  • refactor: — Restructure without behavior change
  • perf: — Performance improvement
  • test: — Add or fix tests
  • build: — Build system or dependency changes
  • ci: — CI config or script changes
  • chore: — Other changes not in src/test
  • revert: — Revert a previous commit

Scope: Service or package name (e.g., feat(auth):, fix(video-player):).

Footer (optional):

  • fixes #123
  • breaking change: ...

13. The Law of Configuration

"Keep your secrets sacred and your configs pure."

  • All configuration via environment variables. No config files in the repository (except .env.example).
  • Every service has a .env.example with all expected vars and sensible defaults.
  • Config is loaded at startup and immutable after boot.
  • Never commit .env, secrets, or local overrides.

Go Config Pattern

type Config struct {
    Port        string `env:"PORT" envDefault:":8080"`
    DatabaseURL string `env:"DATABASE_URL,required"`
    RedisURL    string `env:"REDIS_URL"`
    JWTSecret   string `env:"JWT_SECRET,required"`
}

Nuxt Config Pattern

// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiBaseUrl: process.env.API_BASE_URL || "http://localhost:8080",
    },
  },
});

14. The Law of Performance

"Do not make the machine work in vain."

  • No unnecessary allocations in hot paths. Pre-allocate slices: make([]T, 0, n).
  • Cache expensive queries with Redis. Set TTL appropriate to the data.
  • Use connection pooling (DB, Redis, HTTP clients).
  • Lazy load Nuxt pages and components.
  • Minify assets for production. Nuxt does this by default.
  • Use streaming for large responses (video, file downloads).
  • Avoid N+1 queries. Use eager loading or batch queries.
  • Profile before optimizing. Don't guess.

15. The Law of Naming (Final Recap)

"Every form of name has its place — and none shall trespass."

camelCase         -> Go vars (unexported), Go file names, TS vars/functions, JSON fields
PascalCase        -> Go exported types/funcs, TS types/interfaces, Vue components
snake_case        -> DB tables, DB columns, migration files
kebab-case        -> HTML classes, CSS files, Git branches, repo names
UPPER_CASE        -> TS constants, env vars (UPPER_SNAKE_CASE)
ALL CAPS          -> Go acronyms in identifiers

16. The Law of Environment

"The env is the covenant — never share it, never expose it."

  • .env.example checked into every repository.
  • .env in .gitignore for every repository.
  • All secrets (DB passwords, API keys, JWT secrets) are environment variables.
  • Docker Compose files reference ${VARIABLE} with .env file.
  • Production secrets injected via Docker secrets or the orchestrator, never in the image.

17. The Law of Testing

"Faith without tests is blind."

Go

  • Unit tests alongside code: handler_test.go, service_test.go.
  • Use testing stdlib + testify/assert or testify/require.
  • Integration tests in tests/ — use Testcontainers for PostgreSQL/Redis.
  • Run go test -race ./... before every push.
  • Aim for 80%+ coverage on business logic. Critical paths (auth, payments) 90%+.

TypeScript/Vue/Nuxt

  • Vitest for unit tests. Test composables, stores, and utility functions.
  • Playwright or Vitest browser mode for E2E tests.
  • Component tests with @vue/test-utils + Vitest.
  • Run vitest run before every push.
  • Test API calls in composables by mocking $fetch.

General

  • All logic must be verifiable by tests.
  • Unit tests for functions, integration tests for systems.
  • Run tests before every merge and deployment.
  • Never rely on manual testing alone.

18. The Law of Documentation

"Unwritten knowledge is forgotten truth."

  • Every repository requires a README.md with: purpose, local setup steps, env vars, API endpoints.
  • Every major module or package has a short summary comment.
  • Architecture diagrams in /docs/architecture.md.
  • Deployment steps in /docs/deployment.md.
  • Update docs immediately after code changes.
  • Use Markdown and simple language.

19. The Law of Dependencies

"Rely not on that which you do not control."

  • Only install what is truly needed.
  • Lock dependency versions.
  • Remove unused or outdated packages.
  • Never commit vendor/, node_modules/, or build artifacts.
  • Keep dependency files clean and ordered.
  • Pin exact versions in Dockerfiles for base images.
  • Regularly audit for vulnerabilities (govulncheck, npm audit).

20. The Law of Error Handling

"An error unhandled is chaos unleashed."

Go

if err != nil {
    return fmt.Errorf("create user %s: %w", email, err)
}
  • Always check errors. No _ = error discards.
  • Wrap errors with context.
  • Define typed sentinel errors for expected failures.
  • Use errors.Is() and errors.As() for inspection.
  • Log errors at the boundary (handler), not deep in business logic.

TypeScript

try {
  const user = await createUser(input);
} catch (error) {
  if (error instanceof ValidationError) {
    // handle validation error
  }
  throw error;
}
  • Use typed error classes or Zod validation errors.
  • Never catch and swallow without logging or re-throwing.
  • In Nuxt: use useError or error pages for user-facing errors.

General

  • Define global error and exception handlers in every service.
  • Never expose raw errors to users — return structured error responses.
  • Always fail gracefully with clear internal logs.

21. The Law of Review

"Only through scrutiny does code ascend."

  • All significant merges must be reviewed.
  • No code enters main without a second pair of eyes.
  • Review for: correctness, readability, security, consistency, test coverage.
  • A review is protection, not criticism.
  • CI must pass before merge (lint, type check, test, build).

22. The Law of Architecture

"Without structure, even perfect code collapses."

  • Use layered architecture: Handler → Service → Repository. No skipping layers.
  • Each package must be self-contained and dependency-injected.
  • Shared code lives in /internal/ or /pkg/ — never copied.
  • Define clear boundaries between layers (API, Business Logic, Data).
  • Avoid circular dependencies — they are heresy.
  • Services communicate only through defined APIs (REST or events).

23. The Law of Modularity (Services)

"Divide to conquer, integrate to rule."

  • Each microservice owns its data. No direct database access across services.
  • Services communicate via REST APIs (synchronous) or RabbitMQ events (asynchronous).
  • Every service has its own PostgreSQL database and Redis instance.
  • API versioning via URL prefix: /v1/, /v2/.
  • Event contracts are documented and versioned. Breaking changes = new event type.
  • No cross-service shortcuts or "temporary hacks."

24. The Law of API Design

"An API is a contract — break it and integrations shall crumble."

Rule Standard
Base URL https://api.db123.ir/v1/{resource}
Methods GET (list/read), POST (create), PUT (replace), PATCH (partial), DELETE (remove)
Success response {"data": ..., "meta": {...}}
Error response {"error": {"code": "ERR_CODE", "message": "...", "details": {...}}}
Pagination ?page=1&per_page=20{"page": 1, "per_page": 20, "total": 100, "total_pages": 5}
IDs UUID v7 for all resource IDs
Timestamps RFC 3339 (ISO 8601) in UTC
Sorting ?sort=field:asc,field2:desc
Filtering ?filter[field]=value
Status codes 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable, 429 Too Many, 500 Internal

Error Codes (Consistent Across All Services)

ERR_VALIDATION     — Input validation failed
ERR_NOT_FOUND      — Resource not found
ERR_UNAUTHORIZED   — Missing or invalid authentication
ERR_FORBIDDEN      — Authenticated but insufficient permissions
ERR_CONFLICT       — Duplicate resource or state conflict
ERR_INTERNAL       — Unexpected server error
ERR_RATE_LIMITED   — Too many requests

Every error payload includes a details field with specific field-level errors when applicable.


25. The Law of Database

"Guard thy data as thou guardest thy secrets."

  • Each service owns its own PostgreSQL database. No cross-service DB access.
  • Migration files in migrations/, SQL only. Tool: golang-migrate/migrate.
  • File naming: YYYYMMDDHHMMSS_description.up.sql / .down.sql.
  • Connection pool configured via env vars: max open, max idle, max lifetime.
  • Table names: plural snake_case (users, video_metadata).
  • Column names: snake_case (created_at, updated_at, video_id).
  • Primary keys: UUID v7. Never auto-increment integers for public IDs.
  • Every table has created_at and updated_at columns (TIMESTAMPTZ).
  • Soft deletes: deleted_at TIMESTAMPTZ NULL for recoverable data.
  • Indexes on foreign keys and frequently queried columns.
  • Use EXPLAIN ANALYZE before shipping new queries.

26. The Law of Docker

"Build once, run anywhere — but build it right."

Dockerfile Standards

  • Multi-stage builds: builder stage + distroless/alpine runtime stage.
  • CGO_ENABLED=0 for Go builds.
  • Distroless base image for production (gcr.io/distroless/static-debian12 or alpine:3.23).
  • Non-root user in runtime stage.
  • No unnecessary packages in final image.
  • Label images: org.opencontainers.image.source, org.opencontainers.image.version.
  • Pin base image version digests in CI.

Docker Compose Standards

  • One docker-compose.yml per service for local development.
  • Root docker-compose.yml at the monorepo root (if any) or a shared infra/ repo for orchestrating all services locally.
  • Service names match the repository name.
  • Volume mounts for live reload in development.
  • Default networks: internal (service-to-service), external (API gateway).

27. The Law of Observability

"Thou shalt not fly blind."

Logging

  • Structured JSON logs via log/slog (Go) or pino/consola (Nuxt).
  • Every log line includes: level, msg, service, request_id, duration, error.
  • Log levels: debug (development), info (normal ops), warn (expected issues), error (unexpected failures).
  • No sensitive data in logs (passwords, tokens, PII).

Metrics

  • Every service exposes Prometheus metrics at GET /metrics.
  • Standard metrics: request count, request duration (histogram), error count, active connections.
  • Business metrics: registered users, videos uploaded, orders placed (per service).

Tracing

  • OpenTelemetry with trace ID propagated via x-trace-id header.
  • Trace ID generated at the API gateway if not present.
  • Traces across service boundaries via HTTP headers or RabbitMQ message headers.

Health

  • GET /health — Returns 200 with {"status": "ok"}. Indicates the process is alive.
  • GET /ready — Returns 200 when DB, Redis, and critical dependencies are reachable. 503 otherwise.

28. The Law of Resilience

"Expect failure. Design for it."

  • Every outbound HTTP call has a timeout. No infinite waits.
  • Use circuit breakers for calls to other services. Return cached or degraded response on failure.
  • Retry transient failures with exponential backoff + jitter. Max 3 retries.
  • Idempotency keys for mutation endpoints (POST/PATCH) — reject duplicate requests.
  • Graceful shutdown: Listen for SIGTERM/SIGINT, drain active connections, finish in-flight requests, then exit.
  • Rate limit all public endpoints. Return 429 with Retry-After header.
  • Queue-based load leveling: incoming work goes to RabbitMQ, workers consume at their own pace.

29. The Law of Events (RabbitMQ)

"An event is a promise — deliver it or die trying."

  • Events for cross-service communication (profile updates, video processed, order placed).
  • One exchange per event type, one queue per consumer per service.
  • Event payload includes: event_type, event_id (UUID v7), timestamp, data, version.
  • Events are durable (persistent delivery). Queues are durable.
  • Configure dead letter exchanges for every queue. Messages that fail after 3 retries land in the DLQ.
  • Monitor DLQ size. Periodically inspect and manually replay corrected messages.
  • Consumers are idempotent — processing the same event twice produces the same result.
  • For job priority, use separate queues per priority level. Workers drain high-priority queues first.
  • Document every event contract: docs/events/ with schema examples.

30. The Law of Caching (Redis)

"Cache with purpose, expire with discipline."

  • Redis is a cache, not a primary data store. Data loss must be acceptable.
  • Every cache key has a TTL. No infinite caches.
  • Key naming: service:entity:id (e.g., auth:user:550e8400).
  • Use cache-aside pattern: check Redis → miss → query DB → store in Redis with TTL → return.
  • Cache invalidation strategies (choose by data type):
    • TTL: Let data expire naturally. Good for slightly-staleable data.
    • Explicit invalidation: Delete/update cache keys when source data changes. Requires discipline.
    • Tag-based: Assign tags to related cache entries and delete by tag on updates. Complex but powerful.
  • Use Redis for: session data, rate limiting counters, job queues (via RabbitMQ if async needed), hot data with low TTL.
  • Do NOT store large objects in Redis. Use S3 for blobs, Redis for metadata.
  • Connection pooling with timeout. Handle Redis failures gracefully — fall back to DB.

31. The Law of Continuous Integration

"Let machines judge first, lest chaos reach production."

CI Pipeline (.gitea/workflows/build.yml)

  1. Lint (golangci-lint / eslint)
  2. Type check (go vet / tsc --noEmit)
  3. Unit tests + integration tests (with -race flag for Go)
  4. Vulnerability scanning: govulncheck (Go), npm audit (TS), Trivy (Docker image CVEs)
  5. Build Docker image (multi-stage, distroless, non-root)
  6. Push to registry (tagged :latest, :{{sha}}, and semver tag)
  7. Deploy to dev environment
  8. Health check after deploy

Requirements

  • CI runs on every push to any branch.
  • No merge allowed on failed pipelines.
  • Staging mirrors production environment.
  • Production deploys only from main via CI/CD.
  • Tag releases semantically: v1.2.0, v1.2.1.

32. The Law of Deployment

"Release with reverence, rollback with readiness."

  • Blue-green deployments via Docker Compose (different project names: -p auth-blue, -p auth-green).
  • Health check passes before traffic switches.
  • Rollback by switching back to the previous stack.
  • Database migrations run before the new version starts.
  • Migrations must be backward-compatible (add columns/drop columns in separate releases).
  • Never deploy on Friday unless you enjoy weekend debugging.

33. The Law of Version Control Discipline

"Branches are parallel worlds — merge only when peace is achieved."

  • main is stable and deployable at all times.
  • Feature branches from main. Squash merge with conventional commit message.
  • PR description includes: what changed, why, how to test, screenshots (if UI).
  • No direct pushes to main. Only merge requests.
  • Keep a CHANGELOG.md per service for every release.

34. The Law of Cross-Cutting Concerns

"Some truths apply everywhere — code them once."

Concern Standard
Health checks GET /health (alive), GET /ready (dependencies)
Metrics GET /metrics (Prometheus format)
Tracing x-trace-id header propagated. OpenTelemetry spans.
Graceful shutdown SIGTERM → drain → shutdown (max 30s)
Rate limiting Per-IP, per-route configurable. 429 with Retry-After.
CORS Whitelist *.db123.ir origins. No wildcard in production.
Auth JWT bearer token. Validated in middleware. Forward user info via context.

35. The Law of the API Gateway

"The gateway is the gatekeeper — let nothing pass untested."

Tool

  • Start with Nginx. Migrate to Traefik when you need dynamic service discovery (Traefik reads container labels and auto-configures routes).

Standards

  • Route by path prefix: api.db123.ir/v1/auth/* → auth service, api.db123.ir/v1/video/* → video service.
  • SSL termination with Let's Encrypt auto-renewal (Certbot or Traefik automatic).
  • Rate limiting per IP at the gateway level. Return 429 with Retry-After header.
  • Inject X-Request-Id if missing. Forward to upstream services.
  • Enable HTTP/2 for better client performance.
  • Set security headers: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy.
  • Strip the version prefix when proxying to services (configurable per service).
  • CORS headers for allowed origins. Whitelist *.db123.ir.
  • Serve static assets (CDN) with appropriate cache headers and far-future expiry.

36. The Law of the Frontend (Nuxt)

"The frontend is the face of thy platform — make it consistent and swift."

  • Shared Tailwind theme in tailwind.config.ts with brand colors, spacing, typography.
  • No inline arbitrary Tailwind values. All values in the theme config.
  • Centralized API client in ~/composables/useApi.ts with auth header injection, error normalization, request/response logging.
  • Pinia stores per domain: useAuthStore, useVideoStore, useBlogStore.
  • Every domain page uses its own layout in ~/layouts/.
  • Shared UI components (Button, Input, Modal, Card) in ~/components/shared/.
  • Import the video player and blog editor as npm packages from the local Gitea registry.
  • TypeScript types for every API response in ~/types/.
  • Use useAsyncData or useFetch with proper keys for cache deduplication.
  • No inline styles. No style tag without scoped and only when Tailwind can't express it.

37. The Law of Tailwind

"Utility classes are the atoms of your design — combine them with discipline."

  • Customize the default theme via tailwind.config.ts. Never override base styles with custom CSS unless absolutely necessary.
  • Use @apply in component classes only for patterns that appear in 5+ places.
  • Responsive design: use Tailwind breakpoints (sm:, md:, lg:, xl:, 2xl:). Mobile-first.
  • Dark mode via class strategy. Toggle with a JS class on <html>.
  • No inline style attributes. No <style> tags without scoped.
  • Colors, fonts, spacing all come from theme.extend in config.
  • Use group and peer variants for state-based styling.
  • Animations: use Tailwind's built-in animate- or define custom keyframes in theme.extend.animation.


38. The Law of File Storage (Minio / S3)

"Blobs belong in buckets, not in databases."

  • Use Minio (S3-compatible) for all file storage: user uploads, images, documents, video assets.
  • Pre-signed URLs: Instead of routing file uploads through your backend, generate pre-signed URLs. Clients upload directly to Minio, then notify the backend to process the file.
  • Buckets are private by default. Use pre-signed URLs for controlled access.
  • For public assets, put a CDN (e.g. Cloudflare) in front of Minio.
  • Configure lifecycle policies to automatically expire old or temporary objects.
  • Enable versioning and object locking for protection against accidental deletion.
  • Mirror buckets to remote storage for disaster recovery.

39. The Law of Reliable Messaging (Outbox Pattern)

"Publish not without protection, lest thy message be lost to the void."

  • In the same database transaction as your business data, insert a record into an outbox table containing the serialised message.
  • A separate relay process (outbox relay) polls the outbox table and publishes messages to RabbitMQ.
  • After successful publication, mark the outbox record as sent or delete it.
  • This guarantees at-least-once delivery — the message survives service crashes.
  • Consumers must be idempotent: include a unique message_id and skip already-processed messages.

40. The Law of Sagas (Distributed Transactions)

"A transaction spanning services is a journey — prepare for detours."

When a business process spans multiple services (e.g. Place Order → Reserve Inventory → Process Payment → Ship):

  • Choreography: Each service listens to events, performs its local transaction, then emits the next event. Simple flows only.
  • Orchestration: A central saga coordinator sends commands to each service and handles compensation (rollback) if a step fails. Use for complex flows.
  • Every saga step must be idempotent.
  • Design compensating transactions for every mutating step.

41. The Law of Schema Management

"Contracts between services are sacred — version them or break them."

  • Define event and API schemas in a shared repository or registry.
  • Use JSON Schema for simple JSON payloads, Protobuf or Avro for compact binary formats.
  • Version every schema: order.v1.Event, order.v2.Event.
  • Never change a schema without versioning — old consumers must not break.
  • Run contract tests in CI to verify producers and consumers agree on the schema.

42. The Law of the BFF (Backend For Frontend)

"The frontend shall not chase a dozen services — one gate, one answer."

  • Introduce a thin BFF service specifically for the Nuxt.js app.
  • The BFF aggregates data from multiple microservices into a single response.
  • It handles authentication, forwards user context, and hides internal service layout.
  • Implement as a dedicated Go service or use the API gateway for basic aggregation.
  • Direct file uploads: client requests a pre-signed URL, uploads directly to Minio, then notifies the BFF via API to process the file.

43. The Law of Alerting

"A silent failure is a failure twice over."

  • Configure Prometheus Alertmanager with rules for:
    • High HTTP error rate (5xx > 1% of traffic)
    • RabbitMQ queue depth exceeding threshold
    • Disk space running low (< 20%)
    • Service unavailable (health probe fails)
  • Route alerts to a notification channel (Telegram, Slack, email).
  • Set up on-call rotation for production incidents.
  • Every alert must be actionable — no alert fatigue.

44. The Law of Feature Flags

"Deploy is not release — separate the act from the unveiling."

  • Decouple deploying code from releasing features using configuration-driven flags.
  • Use environment variables or a lightweight feature-flag service.
  • Enable features for a percentage of users for gradual rollout.
  • Instantly disable broken features without redeploying.
  • Perform A/B testing by routing different user cohorts to different flag values.
  • Remove flags once the feature is fully rolled out and stable.

45. The Law of Backup and Disaster Recovery

"A backup untested is a prayer unanswered."

  • PostgreSQL: Schedule automated pg_dump or use WAL archiving for Point-In-Time Recovery. Store off-site.
  • Redis: Configure RDB snapshots (if used for persistence) and backup those files.
  • Minio: Mirror buckets to remote storage using mc mirror or bucket replication.
  • Elasticsearch: Take snapshots to a shared repository (S3/Minio).
  • Test restores regularly — if you haven't tested it, it's not a backup.
  • Document the disaster recovery runbook and practice it.

46. The Law of Infrastructure as Code

"Servers built by hand are cattle without brands — untracked, unversioned, unrepeatable."

  • Define all infrastructure (servers, networks, databases, DNS) using Terraform or Pulumi.
  • Store IaC configurations in Git. Review changes via merge requests.
  • Replicate environments (dev, staging, production) from the same codebase.
  • Never SSH into servers to make manual changes — if it's not in code, it doesn't exist.

47. The Law of Cost Management

"Thou shalt not waste compute on idle thoughts."

  • Set Kubernetes resource requests and limits on every container.
  • Right-size database instances — monitor and adjust.
  • Define retention policies on logs, metrics, and cached data.
  • Monitor cloud/electricity bills and set budget alerts.
  • Use spot/preemptible instances for non-critical workloads.
  • Remove unused resources: orphaned volumes, stale load balancers, idle instances.

"Code shall read like scripture: strict, clean, and unambiguous. Cleverness is temptation; clarity is salvation." — db123

Thus ends the Holy Code Bible. Follow it, or face undefined behavior.