docs: introduce comprehensive coding standards for the zhealth monorepo.

This commit is contained in:
2025-12-18 17:41:25 +05:30
parent 75c15ae73d
commit 9c0715637f

View File

@@ -0,0 +1,189 @@
# 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"
auth:
jwt_secret: "${JWT_SECRET}" # Loaded from env
token_expiry_hours: 24
ai:
provider: "gemini" # gemini | openai | anthropic
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