Skip to content

Conventions

Coding standards enforced across the project. See also CLAUDE.md at the repository root for the complete AI-enforced rules.

Naming Conventions

Context Convention Example
Database columns snake_case created_at, office_id
API JSON fields camelCase createdAt, officeId
Rust structs PascalCase CaseStatus, DeedType
Rust fields snake_case office_id, created_at
TypeScript types PascalCase CaseStatus, DeedType
TypeScript fields camelCase officeId, createdAt
Svelte files PascalCase.svelte CaseDetail.svelte
SQL migrations NNN_description.sql 001_initial_schema.sql
Route segments kebab-case /donnees-reference
CSS classes Semantic tokens text-muted-foreground

Rust ↔ JSON Mapping

All API structs use #[serde(rename_all = "camelCase")]:

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CaseResponse {
    pub id: Uuid,
    pub office_id: Uuid,      // → "officeId" in JSON
    pub created_at: DateTime,  // → "createdAt" in JSON
}

TypeScript types must exactly match the serialized field names.

Language Rules

Context Language
Code, comments, logs English
User-facing validation errors French
Breadcrumb labels French (with accents: Étude, Données)
UI text, button labels French

Indentation

File Type Style
.svelte Tabs
.ts, .js Tabs
.rs 4 spaces (rustfmt)
.sql 4 spaces

When editing existing files, always match the indentation style already present.

UUID Generation

Always use Uuid::now_v7() in Rust code. Never use Uuid::new_v4().

UUID v7 is time-ordered, providing better database index performance and natural chronological sorting.

Optimistic Locking

Every mutable table has version INTEGER NOT NULL DEFAULT 0.

Update Pattern

UPDATE cases
SET name = $1, version = version + 1
WHERE id = $2 AND version = $3

When rows_affected() == 0, distinguish NotFound from VersionConflict via SELECT EXISTS.

API Pattern

  • Response DTOs include version
  • Update request DTOs require version
  • 409 Conflict handled globally with a toast on the client

Validation

  • Dual validation mandatory: every field validated both frontend (TypeScript) AND backend (Rust)
  • No browser native validation: always novalidate on <form> elements
  • Instant error display: validate on blur, show inline errors immediately
  • French error messages: inline below the field, in red
  • Use <a href> for all navigation links (SvelteKit intercepts automatically)
  • Use goto() only for programmatic navigation (after form submit, delete, etc.)
  • Never use stopPropagation() on <a> elements (breaks SvelteKit router)
  • prerender = false in +layout.ts (Tauri SPA)

PR Checklist

Before submitting a pull request:

  • [ ] cargo build — 0 errors, 0 warnings
  • [ ] cargo test — All tests pass
  • [ ] npm run check — Svelte/TypeScript checks pass
  • [ ] No dead code left (imports, unused variables, removed components)
  • [ ] Indentation matches file type conventions
  • [ ] API types match between backend serde and frontend TypeScript
  • [ ] User-facing messages in French
  • [ ] version column on new mutable tables
  • [ ] covers: frontmatter on new doc files