docs/monorepo-structure.md
Monorepo structure
Map of apps, packages, and infra in the studyflash monorepo — what each is for and where boundaries lie.
publishedrajivarchitecturemonorepoonboarding
PH analogue: posthog.com/handbook/engineering/project-structure.
TODO: architecture diagram (Excalidraw). The previous link was stale.
Apps
| App | Stack | Description |
|---|---|---|
portal | Nuxt 3 | Student-facing web app |
core-api | Hono (TS) | API service — auth, subscriptions, orchestration |
learning-api | FastAPI (Py) | AI content generation (flashcards, quizzes, summaries) |
mobile-app | Expo / React Native | Mobile app |
supabase | Supabase | Schemas, migrations, seeds, edge functions |
landing-page | Nuxt 3 | Marketing site |
Other
| App | Description |
|---|---|
mountain-max | Microsite |
subway-max | Microsite |
wrapped | Studyflash Wrapped microsite |
email-previews | Transactional email previews |
marketing-emails-preview | Marketing email previews |
Packages
- types — Shared TypeScript types (incl. generated Supabase DB types)
- common — Shared utilities and constants
- api-client — Shared API client
- tsconfig — Shared TypeScript configs
- devtools — Developer tooling scripts (Deno)
- learning-service — Shared learning service client
Infra
infra/* — one Pulumi stack per concern. Examples:
infra/learning-api— Hetzner VM + preview environments (see preview environment plan)infra/dns— DNS recordsinfra/infisical— secrets manager stackinfra/dokploy,infra/openreplay,infra/turborepo-cache— self-hosted servicesinfra/sentry— explicitly excluded from the workspace
Internal
internal/* — services and surfaces that aren't products:
internal/support-bot— Chatwoot SLA + triage assistantinternal/chatwoot— Chatwoot provider configinternal/docs— this handbook surface (Nuxt 3 + Nuxt Content)
internal/docs is intentionally not in pnpm-workspace.yaml. It runs its own pnpm install --ignore-workspace, so a half-finished docs demo can't break the workspace lockfile or CI pipeline.
Build order
Internal packages/* must be built before type-checking dependent apps:
pnpm turbo build --filter=@studyflash-ai/types \
--filter=@studyflash-ai/common \
--filter=@studyflash-ai/api-client \
--filter=@studyflash-ai/learning-service \
--filter=@studyflash-ai/marketing-emails
(Or pnpm turbo build for everything.)
Quick start
Prerequisites: Node.js, pnpm v10, Deno, Python 3, Docker, Infisical CLI.
pnpm install # install dependencies
pnpm dev # interactive dev launcher
pnpm dev:local # full local dev stack
pnpm build # build all apps
pnpm test # run tests
pnpm lint # lint all packages
Boundaries and rules
TODO. Things to capture:
- What lives in
packages/vs inline in an app. - When a new
app/is justified. core-api↔learning-apiboundary.portal↔mobile-appshared code path (api-client,types).internal/vsapps/— whysupport-botisn't an app.