Monorepo structure¶
Why the Perci Platform lives in a single repository, how it is laid out, and the key decisions behind that layout.
Why a monorepo¶
Four separate repositories were consolidated into one to get:
- Unified CI/CD across frontend and backend.
- Shared code via local path dependencies (no git submodules).
- Atomic cross-cutting changes in a single PR across apps.
- Simpler onboarding: one
git clone, one tooling setup. - Code reuse between the Members and Clinicians apps via shared packages.
- Consistent tooling: standard linting, formatting and testing everywhere.
- AI-agent friendliness: tools can see the whole codebase at once.
History¶
The repo was assembled from four originals, with full git history preserved via
git subtree:
- Backend (Node.js):
perci-platform-backend - Members app (Flutter web):
perci-platform - Clinicians app (Flutter web):
perci-platform-clinicians - Shared Flutter library:
perci-platform-shared
The original repositories are archived (read-only). The branch flow today is develop for
staging and main for production (see Branching & releases).
Structure¶
perci-platform-monorepo/
├─ apps/
│ ├─ perci-platform-members/ # Flutter web app for members
│ ├─ perci-platform-clinicians/ # Flutter web app for clinicians
│ └─ perci-platform-backend/ # Backend (Node.js, TypeScript)
│ ├─ functions/ # Firebase Functions (Express apps)
│ ├─ medplum/bots/ # FHIR automation bots
│ └─ web-professionals/ # React clinician portal (Vite)
├─ packages/
│ ├─ perci-platform-frontend-shared/ # Shared Flutter components & utilities
│ ├─ ff_commons/ # FlutterFlow common utilities
│ └─ ff_theme/ # FlutterFlow theming
├─ .github/workflows/ # CI/CD workflows (path-filtered)
├─ melos.yaml # Melos config (Dart/Flutter only)
├─ pubspec.yaml # Root Melos tooling deps
└─ .fvmrc # Flutter version (FVM)
Key design decisions¶
Three shared packages, not one. The original perci-platform-shared was split into
perci-platform-frontend-shared (app-specific shared code), ff_commons (FlutterFlow
utilities) and ff_theme (FlutterFlow theming) for better modularity and reuse.
Backend kept as an app. apps/perci-platform-backend holds three distinct Node.js
projects: functions/ (Firebase Functions, multiple Express apps), medplum/bots/ (FHIR
automation) and web-professionals/ (React + Vite portal).
Tooling isolation. Melos manages only the Dart/Flutter packages; the Node.js backend uses pnpm independently. Dart and Node tooling are intentionally not unified, which keeps clean boundaries.
Gotchas¶
- Each Flutter app's
pubspec.yamlname:is what Melos scopes on (perci_platform,perci_clinical); use those withmelos exec --scope <name>. - The backend has three separate Node.js projects, each needing its own install; Firebase emulators must be running before backend debugging.
- Run
dart pub getat the root before anymeloscommand, and do not try to manage the Node.js projects with Melos.
For day-to-day setup and commands see Running locally; for CI see GitHub workflows.