# Hestia — Systems Deep Dive

> The `apps/hestia/` area: the three client/server applications — a Fastify
> REST + GraphQL API, a Next.js web app, and an Expo/React Native mobile app —
> that make up Hestia, the culinary-intelligence product (recipes, meal
> planning, pantry/shopping, nutrition, cooking sessions, and social).

## What this area is

Hestia is a product surface, not a shared library: the three Nx projects under
`apps/hestia/` are deployable applications that together form one "Culinary
Intelligence Platform." Each `project.json` carries the `scope:hestia` tag, and
they split by `type`/`platform`: `@hestia/api` is `type:app` `layer:service`,
`@hestia/web` is `platform:web`, and `@hestia/mobile` is `platform:mobile`. They
share a common product vocabulary — recipes, ingredients, meal plans, shopping,
pantry, nutrition, cooking sessions, preferences, social, and AI assistance — so
the same domain concepts recur across all three codebases.

The intended runtime relationship is a classic two-tier split: `@hestia/api` is
the backend the two clients talk to, and `@hestia/web` plus `@hestia/mobile` are
the two front-ends. The API factory in `apps/hestia/api/src/app.ts`
(`buildServer()`) registers a full Fastify plugin stack — request context, CORS,
error handling, Swagger/OpenAPI, JWT auth, a PostgreSQL/Drizzle database plugin,
Redis, rate limiting, and a GraphQL plugin — before mounting versioned routes
under `/v1/*` (see `apps/hestia/api/src/routes/index.ts`). The web and mobile
apps are organised around the same domain groupings the API exposes.

One honesty note that runs through the API: the infrastructure plugins are real
(`apps/hestia/api/src/plugins/database.ts` wires `@oshun/database` +
`drizzle-orm/node-postgres` against the `@hestia/core` schema, and Redis/auth/
rate-limit are all registered), but the **domain data lives in in-memory stores,
not the database**. The recipe, ingredient, auth, meal-plan, pantry, and
cooking-session handlers are explicitly backed by module-level `In-Memory Store`
maps (in both `src/routes/*.ts` and `src/graphql/resolvers/*.ts`); the wired
`fastify.db` pool is currently consumed by the health route, not the domain
handlers. The applications are substantial and functional, but the API's
persistence is in-process state rather than Postgres-backed today.

## How it fits the wider system

These are leaf product applications: they consume platform libraries
(`@oshun/database` for instrumented Postgres pooling, `@hestia/core` for the
Drizzle table schema, plus the usual Zod/Fastify/Next/Expo stacks) rather than
being consumed by other domains. The boundary between them is HTTP/GraphQL: the
API offers a versioned REST surface (`/v1/recipes`, `/v1/meal-plans`,
`/v1/cooking`, …) and a GraphQL endpoint, and the two clients are written to
talk to that contract. Within the monorepo they share the `scope:hestia` tag,
which is how Nx affected-graph and lint/test targets group them. Walk the "used
by" / "depends on" edges on each node below to see the concrete imports.

## Entity reference

### @hestia/api

The backend service (`apps/hestia/api`, sourceRoot `src`), a Fastify 5 app
described in its README as the "Hestia Culinary Intelligence API."
`src/app.ts`'s `buildServer()` assembles the instance with an ordered plugin
stack (request-context → CORS → error-handler → Swagger → JWT auth → database →
Redis → rate-limit → GraphQL → routes) and leaves listening to `src/server.ts`.
`src/routes/index.ts` mounts thirteen route groups under `/v1/*` (recipes,
ingredients, meal-plans, shopping, pantry, nutrition, cooking, preferences,
social, ai, auth, plus health probes and `/v1/info`), and `src/graphql/` adds an
SDL schema (`schema.ts`) with full Query/Mutation resolvers, Relay-style cursor
pagination, and field-level permissions. The infrastructure is real —
`src/plugins/database.ts` builds a `@oshun/database` Postgres client and a
Drizzle instance over the `@hestia/core` schema — but the domain handlers and
GraphQL resolvers are honestly backed by `In-Memory Store` maps rather than that
database (the pool is used for health checks), so this is a working API over
in-process state, not yet a persistence-backed one. Tested with Vitest under
`__tests__/` (config, health, routes, security) and
`src/__tests__/graphql.test.ts`.

### @hestia/web

The Next.js (App Router) web client (`apps/hestia/web`, sourceRoot `src`), run
on port 3011 (`next dev -p 3011`). It is an extensive front-end: 64 `page.tsx`
route files (out of ~109 tracked source files) organised into a `(auth)` route
group (login/register) and an `(app)` group whose subtrees mirror the product
domains — `admin/` (analytics, api-keys, audit, config, features, health,
ingredients, moderation, nutrition, users), `community/`, `cooking/`, `learn/`
(courses, lessons, quizzes, certificates, …), `meal-plans/` (auto-plan, budget,
household, nutrition, prep, slots, templates), `nutrition/`, `pantry/`,
`recipes/`, `settings/`, and `shopping/`. `src/app/(app)/layout.tsx` is a client
component composing a `Sidebar` + `Header` shell with a Zustand `useAppStore`
for sidebar state. It ships PWA assets (`public/manifest.json`, `public/sw.js`,
`robots.ts`/`sitemap.ts`), Vitest component tests under `src/__tests__/`, and a
Playwright `e2e/` suite (auth, community, cooking, meal-plans, navigation,
recipes, search, shopping).

### @hestia/mobile

The Expo / React Native mobile client (`apps/hestia/mobile`, sourceRoot `src`),
launched via `expo start` (with `run-android`/`run-ios` targets and an
`eas.json` for native builds). `App.tsx` is the entry point, wrapping the app in
`SafeAreaProvider` + React Query's `QueryClientProvider` and bootstrapping
session restore, app-store initialization, and push notifications in parallel on
mount before rendering `AppNavigator`. Navigation
(`src/navigation/AppNavigator.tsx`) switches between an auth flow and a
bottom-tab main flow (Recipes, Meal Plan, Shopping, Cook, Profile) with
deep-link `linking`. It carries 29 screens across recipes, meal-plan,
shopping/pantry, cooking (session/timer/step-by-step), nutrition, camera
(ingredient identify / recipe scan), iot (smart kitchen), social, settings, and
auth; a typed API layer (`src/api/client.ts` + React Query hooks under
`src/api/hooks/`); Zustand stores (`authStore`, `appStore`); a reusable UI kit
(`src/components/ui/`); a theme (colors/spacing/typography); and an
`OfflineManager` (`src/services/offline/`) that does AsyncStorage-backed,
TTL-and-collection-organised offline caching of recipes, meal plans, shopping
lists, pantry, cooking sessions, nutrition, and preferences. Tested with Jest
under `__tests__/`.
