Cookest
Contributing

Best Practices

Commit conventions, PR workflows, code style, and development standards for the Cookest ecosystem

Best Practices

This page defines the development standards for all Cookest repositories. Follow these conventions for consistent, reviewable, and maintainable contributions.

Commit Message Format

All commits follow Conventional Commits. The format is:

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Types

TypeWhen to use
featNew feature or capability
fixBug fix
docsDocumentation only changes
styleFormatting, missing semicolons (no code logic change)
refactorCode restructuring without changing behavior
perfPerformance improvement
testAdding or fixing tests
buildBuild system or dependency changes
ciCI/CD configuration changes
choreMaintenance tasks (deps update, config changes)

Scopes

Use the component or module name as scope:

RepositoryExample Scopes
apiauth, recipe, meal-plan, chat, store, subscription, middleware
UIauth, home, recipes, pantry, shopping, chat, theme, navigation
webhero, features, nav, i18n, seo
cuclbutton, input, card, modal, tokens, styles, storybook, build
docsbackend, mobile, etl, i18n, architecture, contributing, ai, cucl
etlextract, transform, load, usda, mealdb

Commit Granularity

Each commit must represent one logical change. A logical change is a single entity, service, handler, component, or configuration — not a batch of loosely related files.

Rules:

  1. One domain concept per commit — adding an ingredient entity is one commit, adding a recipe entity is another
  2. Don't bundle files just because they were created at the same time — "add 7 model files" is too broad; each model should be its own commit
  3. Tightly coupled files can share a commit — a handler and its route registration, or a service and its module re-export, are fine together
  4. Infrastructure changes are their own commits — Cargo.toml, Dockerfile, docker-compose, CI config each get separate commits
  5. The commit message must describe what changed specifically — not just the category of change

Good — specific and atomic:

feat(recipe): add recipe entity with dietary flags and slug-based lookup
feat(recipe): add ingredient allergen entity with 17 allergen types
refactor(auth): add JWT token service with access and refresh encoding
refactor(meal-plan): add meal plan service with AI-scored weekly generation
build: add multi-stage Dockerfile for food-api

Bad — too broad or vague:

feat(recipe): add food-api entities           # which entities? too many files
refactor(auth): add app-api services          # which services? what do they do?
refactor: add request/response models         # meaningless without specifics
feat: update various files                    # completely useless

No AI Co-authorship Trailers

Do not add Co-authored-by trailers for AI tools (GitHub Copilot, Claude, ChatGPT, etc.) in commit messages. AI tools are assistants, not co-authors. All commits are authored by the human developer who reviews and approves the changes.

# ❌ Wrong — do not add AI co-author trailers
feat(auth): add refresh token rotation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

# ✅ Correct — just the commit message
feat(auth): add refresh token rotation

Examples

feat(auth): add refresh token rotation on reuse detection
fix(recipe): correct dietary tag filtering for vegan+gluten-free
docs(backend): add PDF pipeline endpoint documentation
refactor(meal-plan): extract scoring logic into separate service
ci(api): add Rust clippy lint step to CI workflow
docs(i18n): add French translation for architecture overview

Breaking Changes

For breaking changes, add ! after the type/scope and explain in the footer:

feat(auth)!: replace cookie-based refresh with rotating tokens

BREAKING CHANGE: Existing refresh tokens are invalidated.
Clients must re-authenticate after this update.

Branch Naming

<type>/<short-description>

Examples:

  • feat/recipe-search-filters
  • fix/auth-token-refresh-loop
  • docs/add-architecture-diagrams
  • refactor/extract-meal-plan-scoring

Pull Request Standards

PR Title

Same format as commit messages:

feat(recipe): add cuisine-based search filtering

PR Description Template

## What
Brief description of the change.

## Why
Link to issue or explain the motivation.

## How
Key implementation details or architectural decisions.

## Testing
How you verified the change works.

## Screenshots
If UI changes are involved.

Review Checklist

Before requesting review:

  • Code compiles/builds without warnings
  • All existing tests pass
  • New features have tests
  • Documentation updated (if behavior changed)
  • Translations updated (if docs changed)
  • No secrets or credentials in code
  • Breaking changes documented

Code Style by Language

Rust (API)

  • Follow rustfmt defaults
  • Run cargo clippy before committing — no warnings allowed
  • Use thiserror for error types, not string errors
  • Prefer ? over .unwrap() in production code
  • Group imports: std → external crates → internal modules
  • Document public functions with /// doc comments
  • Keep handlers thin — business logic goes in services/

Dart (Flutter / UI)

  • Follow dart format and flutter analyze
  • Use const constructors where possible
  • Riverpod providers in dedicated files (one provider per file)
  • Widget decomposition: max ~150 lines per widget file
  • Name files in snake_case, classes in PascalCase
  • Use final for all local variables that don't change

TypeScript (Web / Docs)

  • Follow project ESLint/Prettier config
  • Prefer const over let, never use var
  • Use TypeScript strict mode — no any unless unavoidable
  • React components: one component per file, PascalCase filenames
  • Use interface for public contracts, type for unions/intersections

TypeScript / React (CUCL)

  • All styles via var(--ck-*) CSS custom properties — no hard-coded hex values
  • Use cn() (clsx + tailwind-merge) for all class composition — never string interpolation
  • Use forwardRef for all components that wrap a native DOM element
  • Every component must have a .test.tsx and a .stories.tsx file
  • Every new component must be added to src/index.ts and exported by name
  • Run bun run format:check before committing — uses Prettier with prettier-plugin-tailwindcss

Python (ETL)

  • Follow PEP 8 (use black formatter)
  • Type hints for all function signatures
  • Docstrings for public functions (Google style)
  • Use logging module, not print()
  • Environment variables via python-dotenv

Environment Management

Required Tools

ToolVersionRepository
Rust1.78+api
PostgreSQL15+api, etl
Flutter3.xUI
Dart3.xUI
Node.js20+web, docs
Bun1.xcucl, docs
Python3.10+etl

Environment Variables

Every repository that requires environment variables includes a .env.example file. Copy it to .env and fill in the values:

cp .env.example .env

Never commit .env files. They are gitignored.

Security Practices

  1. No secrets in code. Use environment variables for all credentials
  2. Hash passwords with Argon2id (API) — never store plaintext
  3. SHA-256 refresh tokens — raw tokens only exist in httpOnly cookies
  4. Verify admin from DB — never trust JWT claims alone for admin access
  5. HMAC-verify webhooks — Stripe webhook payloads are verified with SHA-256 HMAC
  6. Rate limit all endpoints — governor middleware on API, RPS limits on ETL

Dependency Management

  • Rust: Pin major versions in Cargo.toml, use cargo update regularly
  • Flutter: Pin versions in pubspec.yaml, run flutter pub upgrade --major-versions quarterly
  • Node.js: Use lockfiles (bun.lock), review breaking changes before upgrading
  • Python: Pin versions in requirements.txt, test upgrades in a venv

On this page