Skip to main content
The Reflections monorepo uses pnpm workspaces with Turborepo for build orchestration. The codebase is split into deployable apps and shared packages, with strict rules governing how they depend on each other.

Apps

Apps are the deployable units of the platform. Each app serves a distinct runtime concern.
AppDescriptionPlane
apps/apiHono API server. Handles session bootstrap, server-tool callbacks for the voice provider, webhook receivers, and auth/role derivation.Realtime
apps/workersInngest-powered background pipeline. Runs source ingestion, fact extraction, evaluation, and patch application as durable step functions.Background
apps/webNext.js frontend. Provides the user dashboard, knowledge graph visualization, source management, and session interface.Client
apps/iosNative Swift iOS app. Voice interaction interface with knowledge graph visualization and session management. Built with Xcode, outside the pnpm/turbo pipeline.Client

Packages

Packages contain shared logic consumed by apps through published entrypoints. They never depend on apps.
PackageDescriptionKey consumers
packages/brain-coreRetrieval and reasoning logic. Builds retrieval queries, ranks results, and assembles context for LLM prompts.apps/api
packages/dbDatabase queries with read/write/admin segregation. Exposes three entrypoints: ./queries/read (realtime retrieval), ./queries/write (session mutations), ./queries/admin (worker-only operations).apps/api, apps/workers
packages/schemasShared Zod schemas for API contracts, event payloads, ingestion lifecycle states, and the aspect taxonomy. The cross-layer type contract.All apps and packages
packages/vendorsThird-party API clients for Anthropic (LLM) and OpenAI (embeddings). Isolates vendor SDK dependencies so no other package imports them directly.apps/workers, packages/brain-core
packages/sharedUtilities, environment config (env.ts), structured logger, timing helpers, aspect classification, and scoring formulas.All apps and packages
packages/evalFact evaluation logic. Scores candidate facts for confidence and checks for contradictions with existing knowledge.apps/workers
packages/api-clientTyped HTTP client for the Reflections API. Generated from Zod schemas to maintain type safety across the network boundary.apps/web, apps/ios

Dependency direction

The dependency graph flows in one direction: apps depend on packages, never the reverse.
┌─────────────────────────────────────────────────────┐
│                       Apps                          │
│  api    workers    web    ios                        │
└──────────────────────┬──────────────────────────────┘
                       │ depends on

┌─────────────────────────────────────────────────────┐
│                     Packages                        │
│  brain-core  db  schemas  vendors  shared  eval     │
│  api-client                                         │
└─────────────────────────────────────────────────────┘
Packages must never import from apps/*. This is enforced by the monorepo structure (packages do not list apps as dependencies) and verified by architecture guard scripts in CI.

Import rules within packages

Not all packages can import from each other freely:
  • packages/brain-core cannot import from @reflection/db/queries/admin — this enforces the read-only realtime invariant.
  • packages/vendors is the only package allowed to import directly from @anthropic-ai/sdk and openai. All other packages access vendor APIs through @reflection/vendors.
  • packages/shared has no dependencies on other @reflection/* packages — it sits at the bottom of the dependency graph.
  • packages/schemas depends only on Zod — it defines the cross-layer type contract with no runtime dependencies.

How Turborepo orchestrates builds

Turborepo manages the build pipeline through the turbo.json configuration at the repo root.
Turborepo uses dependsOn declarations in turbo.json to build packages before the apps that consume them. When you run pnpm build, Turborepo:
  1. Builds leaf packages first (packages/schemas, packages/shared).
  2. Builds packages that depend on those (packages/db, packages/vendors, packages/eval, packages/brain-core, packages/api-client).
  3. Builds apps last (apps/api, apps/workers, apps/web).
All packages use tsup for bundling, producing ESM output.
Turborepo caches build outputs based on file hashes. If a package’s source files have not changed, its build step is skipped and the cached output is reused. This makes incremental builds fast — typically only the changed packages and their downstream consumers rebuild.
Key Turborepo tasks and what they run:
  • buildtsup (packages) or framework build (apps). Respects dependency ordering.
  • lint — ESLint across all workspaces in parallel.
  • typechecktsc --noEmit across all workspaces in parallel.
  • test — Vitest across all workspaces in parallel.
The pnpm check command runs format:check, lint, typecheck, test, and build in the correct order as the local CI gate.
The iOS app (apps/ios) is a pure Xcode project and does not participate in the pnpm/Turborepo pipeline. It is built and tested separately via xcodebuild. The contract between iOS and the API is maintained through shared Zod schemas that generate Swift-compatible types.

Enforcement

Import boundaries between packages are enforced at three layers:
  1. ESLintno-restricted-imports rules block deep imports, admin query access from the realtime plane, and direct vendor SDK imports.
  2. Architecture guardsimplicity-guard.mjs runs in CI and catches dynamic imports that bypass ESLint.
  3. File-scan tests — dedicated tests in affected packages verify import restrictions and cannot be disabled with inline comments.
See the boundary matrix for per-plane allowed and forbidden operations.

Further reading

  • ADR-0001 — the original decision record for the monorepo and package boundary design.
  • Two-plane architecture — how the realtime and background planes map to apps.
  • System invariants — the non-negotiable rules that package boundaries enforce.