Workspace layout
The workspace root is a plain folder, not a Git repository. Each surface is its own nested Git clone, checked out on thedev branch.
package.json only exists to start the API and the web app together:
tools/wait-for-api.sh polls http://127.0.0.1:3031/healthz for up to 90 seconds. tools/ensure-core-api.sh does the same check and, with --start, launches pnpm dev in backend in the background and writes its output to a log file in /tmp.
backend
A pnpm workspace built with Turborepo. Workspace globs areapps/* and packages/*.
@perform/* packages were written for the backend. @repo/* packages were ported from the web repository during the server consolidation and keep their original scope and code style.
tsconfig.base.json maps @perform/* to packages/*/src/index.ts, so the API type-checks against package source. The @repo/* packages are consumed through their built dist output. That difference is the cause of the stale dist problem described in Troubleshooting.
Domain modules follow a five-file pattern: <name>.routes.ts, <name>.controller.ts, <name>.service.ts, <name>.repository.ts and <name>.schema.ts.
frontend
A pnpm workspace built with Turborepo. Workspace globs areapps/*, packages/* and tooling/*. Shared dependency versions live in the catalog block of pnpm-workspace.yaml.
The folders
apps/docs, apps/mail-preview, packages/api, packages/database, packages/ai, packages/mail and packages/storage still exist on disk in some checkouts but contain only a leftover node_modules folder. They have no package.json and are not part of the workspace. The code they held now lives in the backend.apps/saas/tsconfig.json defines the path aliases: @/* for the app root, and @shared/*, @auth/*, @organizations/*, @payments/*, @settings/*, @admin/*, @onboarding/*, @i18n/* and @config for the feature modules.
mobile
A single Expo package managed with pnpm. It has no Turborepo setup.android and ios folders are generated by expo prebuild and are not the source of truth. Native configuration lives in app.json, the config plugins and the local module.
Where the same logic lives twice
Some rules are implemented in more than one repository and must be changed together. Search for the function name in all three repositories before changing one of these:- Form field conditions:
backend/apps/core-api/src/modules/forms/form-conditions.ts,frontend/apps/saas/modules/shared/lib/form-conditions.ts, and the forms feature inmobile/src/features/forms/lib. - MBP portion math:
backend/apps/core-api/src/modules/foods/mbp.ts,frontend/apps/saas/modules/shared/lib/mbp.tsandmobile/src/features/nutrition/lib/mbp.ts. - Workout time estimates:
mobile/src/features/workouts/lib/estimateWorkout.tsand the trainee service in the backend.