# Coding Standards: zhealth Monorepo ## Core Principles 1. **Modularity First** — Every component should be independent and reusable. 2. **Self-Documenting Structure** — The folder tree and file names should explain purpose without needing comments. 3. **Small Files** — Max **200 lines** per file. A function belongs in a file **only if its purpose is obvious from the filename**. When in doubt, create a separate file. --- ## File & Folder Naming | Type | Convention | Example | |------|------------|---------| | Folders | `snake_case` | `auth_handlers/`, `biomarker_utils/` | | Rust files | `snake_case.rs` | `user_service.rs`, `jwt_middleware.rs` | | TypeScript/React files | `PascalCase.tsx` for components | `Dashboard.tsx`, `BiomarkerCard.tsx` | | TypeScript utilities | `camelCase.ts` | `apiClient.ts`, `formatDate.ts` | | Test files | `*.test.ts` / `*_test.rs` | `auth.test.ts`, `user_service_test.rs` | | Config files | `lowercase` with dots | `vite.config.ts`, `.env.local` | --- ## Folder Structure (Monorepo) ``` zhealth/ ├── PROJECT_MGMT/ # Project planning & docs ├── backend/ # Rust API │ ├── src/ │ │ ├── handlers/ # Route handlers (one file per resource) │ │ ├── models/ # SeaORM entities │ │ ├── services/ # Business logic │ │ ├── middleware/ # Auth, logging, etc. │ │ ├── utils/ # Shared helpers │ │ └── main.rs │ └── Cargo.toml ├── frontend/ # React + Vite │ ├── src/ │ │ ├── components/ # Reusable UI components │ │ ├── pages/ # Route-level components │ │ ├── hooks/ # Custom React hooks │ │ ├── services/ # API calls │ │ ├── utils/ # Helper functions │ │ └── App.tsx │ └── package.json └── shared/ # Shared types/constants (if needed) ``` --- ## Makefile as Command Runner All common tasks are executed through the root **Makefile**. Do not use raw `cargo`, `npm`, or tool-specific commands directly — always use `make`. | Command | Purpose | |---------|---------| | `make lint` | Run linters (Clippy + ESLint) | | `make typecheck` | Type checking (Rust + TypeScript) | | `make dev` | Start dev servers (backend + frontend) | | `make build` | Build for development | | `make release` | Build optimized production bundle | | `make serve` | Serve production build locally | | `make test` | Run all tests | | `make clean` | Clean build artifacts | ### Why Makefile? - **Single source of truth** for all commands - **Works across all platforms** (unlike npm scripts for Rust) - **Self-documenting** — run `make help` to see available targets - **Composable** — targets can depend on each other --- ## Configuration (`config.yaml`) All backend configuration is centralized in a **`config.yaml`** file at the backend root. Never hardcode paths, ports, or environment-specific values. ### Required Config Keys ```yaml # backend/config.yaml server: host: "0.0.0.0" port: 3000 paths: database: "./data/zhealth.db" logs: "./logs" logging: level: "info" # trace | debug | info | warn | error auth: session_secret: "${SESSION_SECRET}" # Loaded from env session_expiry_hours: 24 cookie_name: "zhealth_session" ai: provider: "gemini" # gemini | openai | anthropic model: "gemini-3-flash-preview" api_key: "${AI_API_KEY}" ``` ### Rules - **Secrets via env vars** — Use `${VAR_NAME}` syntax for sensitive values - **Paths are relative** to the backend folder (or absolute if needed) - **No hardcoding** — If it might change across environments, put it in config --- ## File Size Rules | Rule | Action | |------|--------| | File > 200 lines | Split into smaller modules | | Function > 50 lines | Extract to helper or break into sub-functions | | Single responsibility | One file = one purpose | ### Example: Splitting a Large Handler ❌ **Bad**: `handlers/biomarkers.rs` with 400 lines ✅ **Good**: ``` handlers/ ├── biomarkers/ │ ├── mod.rs # Re-exports │ ├── create.rs # POST /biomarkers │ ├── read.rs # GET /biomarkers │ ├── update.rs # PUT /biomarkers/:id │ └── delete.rs # DELETE /biomarkers/:id ``` --- ## Import & Module Organization ### Rust ```rust // 1. Standard library use std::collections::HashMap; // 2. External crates use axum::{Router, Json}; use serde::{Deserialize, Serialize}; // 3. Internal modules use crate::models::User; use crate::services::auth_service; ``` ### TypeScript ```typescript // 1. React/Framework import { useState, useEffect } from 'react'; // 2. External packages import axios from 'axios'; // 3. Internal components/utils import { BiomarkerCard } from '@/components/BiomarkerCard'; import { formatDate } from '@/utils/formatDate'; ``` --- ## Commit & Branch Naming | Type | Format | Example | |------|--------|---------| | Branch | `type/short-description` | `feat/biomarker-crud`, `fix/auth-token-expiry` | | Commit | `type: short description` | `feat: add biomarker create endpoint` | **Types**: `feat`, `fix`, `docs`, `refactor`, `test`, `chore` --- ## Code Comments - **Avoid obvious comments** — Code should be self-explanatory. - **Document "why", not "what"** — Explain non-obvious decisions. - **Use doc comments** for public APIs: - Rust: `///` for functions, `//!` for modules - TypeScript: JSDoc `/** */` for exported functions --- ## Enforcement - [ ] Pre-commit hooks for linting (Clippy for Rust, ESLint for TS) - [ ] CI pipeline checks for file size violations - [ ] PR reviews must verify modularity standards