{"owner":"mealie-recipes","repo":"mealie","hasSkills":true,"totalSkillsCount":2,"totalTokensCount":4930,"categories":["root-instruction","claude-rule"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md"],"skills":{"AGENTS.md":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n","CLAUDE.md":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n"},"files":{"AGENTS.md":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n","CLAUDE.md":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/mealie-recipes/mealie/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n","isInternal":false,"tokens":2465,"sizeBytes":10721},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/mealie-recipes/mealie/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n","isInternal":false,"tokens":2465,"sizeBytes":10721}],"systemPromptSnippet":"<yakaai_skills repo=\"mealie-recipes/mealie\">\n<!-- File: AGENTS.md (Tokens: ~2465 | Category: root-instruction) -->\n# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n\n<!-- File: CLAUDE.md (Tokens: ~2465 | Category: claude-rule) -->\n# Mealie Development Guide for AI Agents\n\n## Project Overview\n\nMealie is a self-hosted recipe manager, meal planner, and shopping list application with a FastAPI backend (Python 3.14) and Nuxt 4 frontend (Vue 3 + TypeScript). It uses SQLAlchemy ORM with support for SQLite and PostgreSQL databases.\n\n**Development vs Production:**\n- **Development:** Frontend (port 3000) and backend (port 9000) run as separate processes\n- **Production:** Frontend is statically generated and served via FastAPI's SPA module (`mealie/routes/spa/`) in a single container\n\n## Architecture & Key Patterns\n\n### Backend Architecture (mealie/)\n\n**Repository-Service-Controller Pattern:**\n- **Controllers** (`mealie/routes/**/controller_*.py`): Inherit from `BaseUserController` or `BaseAdminController`, handle HTTP concerns, delegate to services\n- **Services** (`mealie/services/`): Business logic layer, inherit from `BaseService`, coordinate repos and external dependencies\n- **Repositories** (`mealie/repos/`): Data access layer using SQLAlchemy, accessed via `AllRepositories` factory\n  - Get repos via dependency injection: `repos: AllRepositories = Depends(get_repositories)`\n  - All repos scoped to group/household context automatically\n\n**Route Organization:**\n- Routes in `mealie/routes/` organized by domain (auth, recipe, groups, households, admin)\n- Use `APIRouter` with FastAPI dependency injection\n- Apply `@router.get/post/put/delete` decorators with Pydantic response models\n- Route controllers use `HttpRepo` mixin for common CRUD operations (see `mealie/routes/_base/mixins.py`)\n\n**Schemas & Type Generation:**\n- Pydantic schemas in `mealie/schema/` with strict separation: `*In`, `*Out`, `*Create`, `*Update` suffixes\n- Auto-exported from submodules via `__init__.py` files (generated by `task dev:generate`)\n- TypeScript types auto-generated from Pydantic schemas - **never manually edit** `frontend/app/lib/api/types/`\n\n**Database & Sessions:**\n- Session management via `Depends(generate_session)` in FastAPI routes\n- Use `session_context()` context manager in services/scripts\n- SQLAlchemy models in `mealie/db/models/`, migrations in `mealie/alembic/`\n- Create migrations: `task py:migrate -- \"description\"`\n\n### Frontend Architecture (frontend/)\n\n**Component Organization (strict naming conventions):**\n- **Domain Components** (`components/Domain/`): Feature-specific, prefix with domain (e.g., `AdminDashboard`)\n- **Global Components** (`components/global/`): Reusable primitives, prefix with `Base` (e.g., `BaseButton`)\n- **Layout Components** (`components/Layout/`): Layout-only, prefix with `App` if props or `The` if singleton\n- **Page Components** (`components/` with page prefix): Last resort for breaking up complex pages\n\n**API Client Pattern:**\n- API clients in `frontend/app/lib/api/` extend `BaseAPI`, `BaseCRUDAPI`, or `BaseCRUDAPIReadOnly`\n- Types imported from auto-generated `frontend/app/lib/api/types/` (DO NOT EDIT MANUALLY)\n- Composables in `frontend/app/composables/` for shared state and API logic (e.g., `use-mealie-auth.ts`)\n- Use `useAuthBackend()` for authentication state, `useMealieAuth()` for user management\n\n**State Management:**\n- Nuxt 4 composables for state (no Vuex)\n- Auth state via `use-mealie-auth.ts` composable\n- Prefer composables over global state stores\n\n## Essential Commands (via Task/Taskfile.yml)\n\n**Development workflow:**\n```bash\ntask setup              # Install all dependencies (Python + Node)\ntask dev:services       # Start Postgres & Mailpit containers\ntask py                 # Start FastAPI backend (port 9000)\ntask ui                 # Start Nuxt frontend (port 3000)\ntask docs               # Start Zensical documentation server\n```\n\n**Code generation (REQUIRED after schema changes):**\n```bash\ntask dev:generate       # Generate TypeScript types, schema exports, test helpers\n```\n\n**Testing & Quality:**\n```bash\ntask py:test            # Run pytest (supports args: task py:test -- -k test_name)\ntask py:check           # Format + lint + type-check + test (full validation)\ntask py:format          # Ruff format\ntask py:lint            # Ruff check\ntask py:mypy            # Type checking\ntask ui:test            # Vitest frontend tests\ntask ui:check           # Frontend lint + test\n```\n\n**Database:**\n```bash\ntask py:migrate -- \"description\"  # Generate Alembic migration\ntask py:postgres        # Run backend with PostgreSQL config\n```\n\n**Docker:**\n```bash\ntask docker:prod        # Build and run production Docker compose\n```\n\n## Critical Development Practices\n\n### Python Backend\n\n1. **Always use `uv` for Python commands** (not `python` or `pip`):\n   ```bash\n   uv run python mealie/app.py\n   uv run pytest tests/\n   ```\n\n2. **Type hints are mandatory:** Use mypy-compatible annotations, handle Optional types explicitly\n\n3. **Dependency injection pattern:**\n   ```python\n   from fastapi import Depends\n   from mealie.repos.all_repositories import get_repositories, AllRepositories\n\n\n   def my_route(repos: AllRepositories = Depends(get_repositories), user: PrivateUser = Depends(get_current_user)):\n       recipe = repos.recipes.get_one(recipe_id)\n   ```\n\n4. **Settings & Configuration:**\n   - Get settings: `settings = get_app_settings()` (cached singleton)\n   - Get directories: `dirs = get_app_dirs()`\n   - Never instantiate `AppSettings()` directly\n\n5. **Testing:**\n   - Fixtures in `tests/fixtures/`\n   - Use `api_client` fixture for integration tests\n   - Follow existing patterns in `tests/integration_tests/` and `tests/unit_tests/`\n\n### Frontend\n\n1. **Run code generation after backend schema changes:** `task dev:generate`\n\n2. **TypeScript strict mode:** All code must pass type checking\n\n3. **Component naming:** Follow strict conventions (see Architecture section above)\n\n4. **API calls pattern:**\n   ```typescript\n   const api = useUserApi();\n   const recipe = await api.recipes.getOne(recipeId);\n   ```\n\n5. **Composables for shared logic:** Prefer composables in `composables/` over inline code duplication\n\n6. **Translations:** Only modify `en-US` locale files when adding new translation strings - other locales are managed via Crowdin and **must never be modified** (PRs modifying non-English locales will be rejected)\n\n### Cross-Cutting Concerns\n\n1. **Code generation is source of truth:** After Pydantic schema changes, run `task dev:generate` to update:\n   - TypeScript types (`frontend/app/lib/api/types/`)\n   - Schema exports (`mealie/schema/*/__init__.py`)\n   - Test data paths and routes\n\n2. **Multi-tenancy:** All data scoped to **groups** and **households**:\n   - Groups contain multiple households\n   - Households contain recipes, meal plans, shopping lists\n   - Repositories automatically filter by group/household context\n\n3. **Pre-commit hooks:** Install via `task setup:py`, enforces Ruff formatting/linting\n\n4. **Testing before PRs:** Run `task py:check` and `task ui:check` before submitting PRs\n\n## Pull Request Best Practices\n\n### Before Submitting a PR\n\n1. **Draft PRs are optional:** Create a draft PR early if you want feedback while working, or open directly as ready when complete\n2. **Verify code generation:** If you modified Pydantic schemas, ensure `task dev:generate` was run\n3. **Follow Conventional Commits:** Title your PR according to the conventional commits format (see PR template)\n4. **Add release notes:** Include user-facing changes in the PR description\n\n### What to Review\n\n**Architecture & Patterns:**\n- Does the code follow the repository-service-controller pattern?\n- Are controllers delegating business logic to services?\n- Are services coordinating repositories, not accessing the database directly?\n- Is dependency injection used properly (`Depends(get_repositories)`, `Depends(get_current_user)`)?\n\n**Data Scoping:**\n- Are repositories correctly scoped to group/household context?\n- Do route handlers properly validate group/household ownership before operations?\n- Are multi-tenant boundaries enforced (users can't access other groups' data)?\n\n**Type Safety:**\n- Are type hints present on all functions and methods?\n- Are Pydantic schemas using correct suffixes (`*In`, `*Out`, `*Create`, `*Update`)?\n- For frontend, does TypeScript code pass strict type checking?\n\n**Generated Files:**\n- Verify `frontend/app/lib/api/types/` files weren't manually edited (they're auto-generated)\n- Check that `mealie/schema/*/__init__.py` exports match actual schema files (auto-generated)\n- If schemas changed, confirm generated files were updated via `task dev:generate`\n\n**Code Quality:**\n- Is the code readable and well-organized?\n- Are complex operations documented with clear comments?\n- Do component names follow the strict naming conventions (Domain/Global/Layout/Page prefixes)?\n- Are composables used for shared frontend logic instead of duplication?\n\n**Translations:**\n- Were only `en-US` locale files modified for new translation strings?\n- Verify no other locale files (managed by Crowdin) were touched\n\n**Database Changes:**\n- Are Alembic migrations included for schema changes?\n- Are migrations tested against both SQLite and PostgreSQL?\n\n### Review Etiquette\n\n- Be constructive and specific in feedback\n- Suggest code examples when proposing changes\n- Focus on architecture and logic - formatting/linting is handled by CI\n- Use \"Approve\" when ready to merge, \"Request Changes\" for blocking issues, \"Comment\" for non-blocking suggestions\n\n## Common Gotchas\n\n- **Don't manually edit generated files:** `frontend/app/lib/api/types/`, schema `__init__.py` files\n- **Repository context:** Repos are group/household-scoped - passing wrong IDs causes 404s\n- **Session handling:** Don't create sessions manually, use dependency injection or `session_context()`\n- **Schema changes require codegen:** After changing Pydantic models, run `task dev:generate`\n- **Translation files:** Only modify `en-US` locale files - all other locales are managed by Crowdin\n- **Dev containers:** This project uses VS Code dev containers - leverage the pre-configured environment\n- **Task commands:** Use `task` commands instead of direct tool invocation for consistency\n\n## Key Files to Reference\n\n- `Taskfile.yml` - All development commands and workflows\n- `mealie/routes/_base/base_controllers.py` - Controller base classes and patterns\n- `mealie/repos/repository_factory.py` - Repository factory and available repos\n- `frontend/app/lib/api/base/base-clients.ts` - API client base classes\n- `tests/conftest.py` - Test fixtures and setup\n- `dev/code-generation/main.py` - Code generation entry point\n\n## Additional Resources\n\n- [Documentation](https://docs.mealie.io/)\n- [Contributors Guide](https://nightly.mealie.io/contributors/developers-guide/code-contributions/)\n- [Discord](https://discord.gg/QuStdQGSGK)\n</yakaai_skills>"}