Real app skeleton
The app repo is a backend/frontend monorepo. Backend follows BCE: routers call features, features use pure core domain and boundary protocols, wiring selects integrations.
The canonical working map for new and returning developers: where the implementation lives, how the current FastAPI/Vue app is wired, what is real, what is mock, and which contracts join backend and frontend while the product is still in staged mock mode.
The app repo is a backend/frontend monorepo. Backend follows BCE: routers call features, features use pure core domain and boundary protocols, wiring selects integrations.
MOCK_MODE=true registers the mock Today and All Details endpoints. They keep the UI testable before the real daily summary builder replaces them.
/meals is already a real async contract backed by stores and jobs. The estimator is fake unless real Anthropic is explicitly enabled.
Source of truth: implementation work happens in emealia-app. This website repo mirrors the onboarding map for humans; story state and acceptance criteria still live in the app repo's planning docs.
emealia-app/backend/app/| Path | Purpose | How to work there |
|---|---|---|
api/ | FastAPI routers and wire models. Examples: meals.py, daily.py, day_context.py, activity_context.py, consents.py. | Keep HTTP concerns here. Convert request/response models at the edge, then call a feature. |
features/ | Use-case orchestration such as log_meal.py, save_meal.py, run_ai_job.py, build_daily_view.py. | Coordinate domain objects and boundary protocols. Do not reach directly into SQLAlchemy or provider SDKs. |
core/ | Pure domain rules: meals, meal estimation, calibration, daily summaries, band states, profiles, consent, usage, backdating. | No FastAPI, no database sessions, no network. This is the easiest layer to unit-test. |
boundaries/ | Protocols/interfaces for persistence, AI, auth, clocks, payments, email, demo sessions, usage metering. | Add a boundary when a feature needs an external capability. Features depend on these protocols, not integrations. |
integrations/ | Concrete adapters: SQLAlchemy stores, fake and Anthropic estimators, database setup, system clock, in-memory demo sessions, mock data stores. | Provider-specific and infrastructure code belongs here. Keep mapping code explicit and testable. |
prompts/ | AI prompt text and prompt builder for meal parsing and estimation. | Keep estimation at AI level, interpretation and display mapping at application level. |
wiring.py | Composition root. Creates settings, admin config, database sessions, stores, estimator, workers, middleware, and routers. | Feature flags and environment-driven choices are wired here, especially mock mode and provider selection. |
settings.py | Typed environment configuration with production/staging validation. | Real providers must fail fast when secrets or explicit safety switches are missing. |
migrations/ | Alembic migrations for the app database. | Schema changes require migration and tests around affected stores/features. |
emealia-app/frontend/src/| Path | Purpose | How to work there |
|---|---|---|
features/ | Screen-owned views and composables: today, all-details, log-meal, meal-detail, history, onboarding, statistics. | Put feature-specific mapping and state next to the screen. Reuse shared components, but avoid premature cross-feature abstraction. |
components/ | Shared UI primitives such as app shell, buttons, icons, sheets, meal rows, nutrient bands, empty states. | Keep them generic and visual. Business wording should usually stay in feature views and locale files. |
api/ | Typed client and generated schema from backend OpenAPI. | Regenerate after backend contract changes. Feature composables should use the typed client, not hand-built fetch calls. |
stores/ | Small Pinia/localStorage stores for locale, favourites, confirmations, onboarding profile, selected nutrients. | Client-side stores are stopgaps when backend ownership is not ready. Name that in comments when it matters. |
locales/ | English and German UI strings. | User-visible copy lives here. AI voice may be italic in UI; ordinary app labels should not be. |
router/ | Named routes and navigation between app screens. | Prefer named routes, carry demo query parameters where mock/demo continuity matters. |
assets/ | Static frontend assets. | Use real/generative bitmap assets for product-like visual surfaces where needed; avoid decorative placeholders. |
| Path | Purpose |
|---|---|
implementation-plan/ | Story plan and status. Do not revive skipped/duplicate stories unless explicitly reopened. |
docs/architecture/ | Architecture notes and JSON contracts such as the daily view shape. |
backend/tests/ | Backend unit, feature, API, integration, and contract tests. |
frontend/src/**/*.spec.ts | Frontend unit/component tests near the code they protect. |
scripts/ | Generation and validation helpers, including API schema/client regeneration. |
Makefile and npm scripts | Local CI shortcuts for backend and frontend verification. |
This is the checklist for "where data is set". Treat it as the first place to look before adding a new config value, local fixture, persisted client state, API field, or database column.
| Path | Owns | Notes |
|---|---|---|
.env.example | Environment contract for local/staging/production. | Includes app env, mock mode, database URL, provider switches, provider secrets, CORS, rate limits, observability placeholders, and the explicit ALLOW_REAL_AI gate. |
backend/app/settings.py | Typed settings and fail-fast validation. | Production/staging must not boot with fake providers, placeholder secrets, unsafe JWT keys, wildcard CORS, or real AI without the explicit safety switch. |
backend/config/admin.toml | Admin product knobs, not secrets. | Currently owns meal input max chars, AI output-quality thresholds, usage caps/trial credits, and service-paused copy. Deploys may override via ADMIN_CONFIG_PATH. |
backend/app/admin_config.py | Typed loader for admin config. | Maps TOML into application types; features read admin values through wiring rather than parsing TOML directly. |
docker-compose.yml | Local infrastructure. | Local Postgres service for backend integration tests and development. |
.github/workflows/*.yml | CI and deploy automation. | Separate backend, frontend, security, Sonar, and deploy workflows. |
.pre-commit-config.yaml | Local hygiene hooks. | Complements CI; do not rely on it as the only validation. |
| Path | Owns | Notes |
|---|---|---|
package.json | Root frontend command proxies. | Runs frontend dev/build/lint/test/API generation and local CI scripts from the monorepo root. |
frontend/package.json | Frontend dependencies and scripts. | Vue, Vite, Pinia, vue-i18n, openapi-fetch, Vitest, Playwright, lint, i18n, token, and API generation commands. |
frontend/vite.config.ts | Vite app and PWA build configuration. | Controls plugins, aliases, dev/build behavior, and how the browser app is bundled. |
frontend/vitest.config.ts, frontend/playwright.config.ts | Frontend unit/component and e2e test config. | Use Vitest for local component/unit coverage; Playwright for browser behavior where workflows require it. |
frontend/tsconfig*.json | TypeScript project boundaries. | Separate app, node/tooling, and test type-check contexts. |
frontend/eslint.config.ts, frontend/.oxlintrc.json | Frontend lint config. | Run via npm run lint; token checks are part of the lint script. |
backend/pyproject.toml | Backend Python tooling. | Owns pytest, ruff, mypy, coverage, dependency/security tooling configuration where present. |
backend/alembic.ini, backend/alembic/env.py | Migration runtime configuration. | Connects Alembic to the app settings and SQLAlchemy metadata. |
scripts/local-ci.sh | Local CI entrypoint. | Runs backend, frontend, e2e, or security check groups from root npm scripts. |
| Path | Owns | Notes |
|---|---|---|
frontend/src/assets/tokens.css | Runtime CSS design tokens. | Primary color, spacing, typography, and theme variables consumed by Vue components. |
frontend/src/design/tokens.ts | TypeScript token mirror. | Use when components or tests need token names/values in TypeScript. |
frontend/scripts/generate-tokens.mjs, check-tokens.mjs | Token generation and drift checks. | Token files should be generated/checked rather than hand-diverging. |
frontend/src/assets/base.css, fonts.css | Global browser styling. | App-wide reset/base styling and font loading. |
frontend/src/App.vue, frontend/src/main.ts | Vue app shell boot. | Mounts Vue, router, Pinia, i18n, and global shell behavior. |
frontend/src/router/index.ts | Screen route registry. | Named routes connect Today, All Details, meal logging/detail, history, onboarding, statistics, demos, and not-found behavior. |
frontend/src/pwa/manifest.ts | PWA manifest data. | Controls installable app metadata; notification/settings stories should keep browser capability prompts connected to user settings. |
| Path | Owns | Current tables / concerns |
|---|---|---|
backend/alembic/versions/ | Schema history. | Migrations establish users, consents, meals, meal metadata/status, full nutrient columns, daily summaries, usage metering, AI jobs, meal memory, daily context, activity context, and portion/products schema. |
backend/app/integrations/models.py | SQLAlchemy ORM rows. | Mapped infrastructure classes. Keep them out of core/; Alembic imports them so metadata is complete. |
users | Identity anchor. | User id, timezone, created/updated timestamps. Other owned data references this row. |
consents | GDPR consent ledger. | Append/revoke model with one active consent per user/type; rows cascade with user erasure. |
usage_accounts, usage_user_days, usage_global_days | AI entitlement and cost guardrails. | Trial credits, subscription status, per-user daily reservations, and global daily reservations. |
meals | Meal drafts/logged meals and nutrient ranges. | Stores raw text, AI/display metadata, status/lifecycle/versioning, products/assumptions, portion size, and macro/micro/detail nutrient ranges with plausibility checks. |
meal_memory | Confirmed meal reuse. | User-scoped canonical text plus confirmed nutrient/product/assumption shape for fast repeat logs. |
ai_jobs | Async estimation queue. | Pending/running/succeeded/failed job state, attempts, next attempt time, and error metadata. |
daily_summaries | Persisted daily nutrition aggregates. | Per-user/day summary ranges and pending count. Rebuilt when meals are saved or changed. |
daily_context_tags, activity_context | Day context inputs. | User/day tags and rough activity turnover ranges. |
| Path | Owns | Notes |
|---|---|---|
backend/scripts/export_openapi.py | Backend OpenAPI export. | Run after API model/route changes so the frontend contract can be regenerated. |
frontend/openapi.json | Checked-in API snapshot. | The input for TypeScript API type generation. |
frontend/src/api/generated/schema.d.ts | Generated TypeScript route/schema types. | Do not edit by hand. Regenerate with npm run api:generate. |
frontend/src/api/client.ts | Typed API client setup. | Feature composables call this client; avoid ad hoc fetch unless there is a deliberate exception. |
| Path | Owns | Notes |
|---|---|---|
frontend/src/i18n.ts | Vue i18n setup. | Supported locales currently en and de; fallback is English. |
frontend/src/locales/en.json, frontend/src/locales/de.json | User-visible frontend copy. | Keep keys aligned; run npm run i18n:check. Do not put hard-coded app copy in components. |
frontend/src/stores/locale.ts | Active UI locale. | Current scaffold switches i18n locale and document.documentElement.lang. Detection/persistence and backend profile ownership are future work. |
backend/config/admin.toml and admin config loader | Operator-controlled market behavior. | Locale/market activation and unit availability should be admin-configured, not embedded in a screen. |
frontend/scripts/check-i18n.mjs | Locale-key verification. | Use before PRs that touch UI copy or locale files. |
| Path | Owns | Current persistence / status |
|---|---|---|
frontend/src/features/demo/demoData.ts | Frontend-only demo fixtures. | Used by ?demo=1. No backend, AI, or storage cost. |
backend/app/integrations/mock/mock_days.py, mock_stores.py | Backend mock daily data. | Used by GET /daily and GET /daily/{day}/details in MOCK_MODE. |
backend/app/integrations/mock/mock_meal_log.py | Legacy in-process mock meal flow. | Accepts/polls/saves mock meal estimates per process. It does not feed real daily summaries. |
backend/app/dev_seed.py, backend/scripts/seed_dev.py | Development seed data. | Creates demo user/data for local and mock-supported development; guarded so it does not become production behavior. |
frontend/src/stores/favourites.ts | Favourite meal ids. | Client-side localStorage stopgap under emealia.favourite-meals until a backend favourite field/endpoint lands. |
frontend/src/stores/mealConfirmations.ts | Confirmed meal UI state. | Client-side localStorage stopgap under emealia.confirmed-meals. |
frontend/src/stores/onboardingProfile.ts | Goals, dietary context, and optional body params. | Client-side localStorage stopgap under emealia.onboarding-profile; body params are erased when consent is revoked. |
frontend/src/stores/todayNutrients.ts | Starred Today nutrients and remembered band catalog. | Client-side localStorage stopgap under emealia.today-nutrients and emealia.today-nutrient-bands; cap is 10. |
The backend is intentionally layered around BCE. Request/response code stays at the edge; domain rules stay pure; adapters are selected in the composition root.
The frontend is feature-first. Screens own their loading/mapping logic; shared components stay visual and reusable.
There are two distinct demo mechanisms. ?demo=1 is frontend-only and uses static fixtures. MOCK_MODE=true is backend mock mode and registers mock endpoints for daily summary surfaces. Meal logging now has both an older mock router in mock mode and the real router; the real route is the contract to extend.
The product promise depends on free text staying natural. The AI estimates; the application validates, maps, formats, and interprets. Portion size comes from user text when present; otherwise the estimator makes an assumption, normally a mid-sized portion.
| Surface | Status | Notes for next work |
|---|---|---|
| Today bands | Mock-backed | GET /daily exists only as a mock route in MOCK_MODE. Frontend already maps the contract and falls back calmly on errors. |
| All Details | Mock-backed | GET /daily/{day}/details returns numeric transparency data from the same mock day variant. |
| Meal logging | Real contract, fake AI default | POST /meals, draft polling, save, re-estimate, suggestions, and memory reuse are backend concepts. Keep extending this path. |
| Meal detail | Real read path plus demo fixtures | GET /meals/{meal_id} reads stored meals. ?demo=1 uses frontend fixture data for comprehension testing. |
| History | Hybrid | Reads logged meals from /meals and daily context/activity endpoints; day-level summary may still derive from mock daily data where no real summary exists. |
| Day and activity context | Backend-backed | /daily/{day}/context and /daily/{day}/activity-context use stores and are wired outside mock-only daily summary. |
| Statistics | Backend groundwork, UI placeholder | Period summary storage/aggregation exists in recent app work; frontend still has a placeholder screen. |
| Locale and units | Scaffolded | Frontend i18n and locale store exist. Backend has admin config and locale/market rules; activation and full formatting should remain config-driven. |
| Auth, payment, email | Boundaries first | Provider switches and fail-fast settings exist. Real provider rollout must stay explicit and environment-gated. |
core/, orchestrate in features/, expose in api/, and bind concrete dependencies in wiring.py.features/ folder, reuse shared components, put text in locale files, and use the generated typed API client.The exact command names may evolve with the app repo, but this is the expected local shape.
# backend
cd /Users/escheck/Projects/emealia-app
docker compose up -d db
cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
alembic upgrade head
MOCK_MODE=true AI_PROVIDER=fake uvicorn app.main:app --reload
# frontend
cd /Users/escheck/Projects/emealia-app/frontend
npm install
npm run dev
Use ?demo=1 on supported frontend routes for static demo data. Use MOCK_MODE=true when the browser should call backend mock endpoints for Today and All Details.