Monorepo for the FMS collection of independent, reusable Django apps. Each module under packages/ is a standalone pip-installable library that solves one concern (identity, billing, auditing, etc.); consumer SaaS products pick modules à la carte. There is no central runtime and no cross-module imports.
See docs/specs/2026-04-24-shared-modules-prd.md for the full PRD.
fms-core/
├── packages/ # polyglot: Python (uv) + Node (pnpm)
│ ├── _template/ # Python module template — copy for new fms-<module>
│ ├── _template-node/ # Node lib template — copy for new @fms/<lib>
│ └── (future: ui, shell, i18n, field, api, forms, testing — see frontend spec)
├── verticals/ # Nuxt 4 apps, one per vertical product
│ ├── _template/ # vertical app template — copy for new vertical
│ └── (future: bookkeeping-close, hr-1099, hvac-dispatch, funeral-intake, trucking-ifta, insurance-renewals)
├── examples/
│ └── saas-sampler/ # Django reference consumer composing ≥5 Python modules
├── docs/
│ ├── specs/ # PRDs and ADRs
│ ├── superpowers/ # plans, specs, skill content (process docs)
│ └── playbook/ # Obsidian vault — opportunity research, schema, design system specs
├── .github/workflows/ # CI (Python: ruff/mypy/pytest/import-linter; Node: TBD)
├── pyproject.toml # uv workspace root
├── pnpm-workspace.yaml # pnpm workspace root
├── package.json # private root, pins pnpm via packageManager
├── .npmrc # engine-strict, prefer-workspace-packages
├── importlinter.toml # "no cross-module imports" contract (Python only)
├── .pre-commit-config.yaml # ruff + mypy + import-linter + bare-python guard
└── README.md
Python packages live under packages/<dist-name>/ (PyPI-style fms-<module>) with source at src/fms_<module>/ (importable, underscored). Node packages live under packages/<lib>/ with package.json#name = "@fms/<lib>" and use pnpm, not uv. Vertical Nuxt apps live under verticals/<slug>/ with package.json#name = "@fms/vertical-<slug>". The two workspaces (uv and pnpm) coexist because each selects members by config-file presence — uv reads pyproject.toml (with Node-only directories listed under [tool.uv.workspace].exclude), pnpm reads package.json.
The frontend tech-stack architecture (Nuxt 4, layer precedence, design tokens, clusters, Storybook) is specified in docs/superpowers/specs/2026-04-27-frontend-tech-stack-design.md. The product/strategy vault lives at docs/playbook/ (Obsidian).
- Always
uv run. Never invokepython,python3, orpipdirectly. Useuv run <cmd>anduv add <pkg>. CI fails on bare invocations (PRD §2.1). - No cross-module imports between Python packages. Modules reach shared concepts (tenant, user, contact) through Django settings +
apps.get_model()lazy lookups, the way Django resolvesAUTH_USER_MODEL.import-linterenforces this in CI (PRD §2.2 / §4). - Latest stable, always. Dependencies are unpinned in
pyproject.tomlsouvresolves to the latest stable at install time. Never copy a version number from this repo, the PRD, or stale documentation; verify against PyPI / pypi.org / python.org / nodejs.org at install time (PRD §2.3).
- Always
pnpm --filter <name>. Never invokenode,npx,tsc, ornuxtoutsidepackage.jsonscripts. Run package commands aspnpm --filter @fms/<lib> <script>or vertical commands aspnpm --filter @fms/vertical-<slug> <script>. - Layer precedence drives override location. The Nuxt layer order (lowest → highest priority) is
@fms/ui → @fms/i18n → @fms/shell → @fms/field → <vertical>. Vertical-specific overrides live in the vertical's own layer atverticals/<slug>/— never in shared packages. See docs/superpowers/specs/2026-04-27-frontend-tech-stack-design.md §"Layer precedence". - Latest stable, always. Use unpinned
^ranges inpackage.jsonand letpnpmresolve to current latest within the major. Never copy version numbers from documentation; verify against npmjs.com at install time. Pin onlypackageManager(in rootpackage.json) andengines(Node + pnpm major versions).
Initial setup (run once):
# Python side
uv sync --all-packages --all-extras --dev
uv run pre-commit install
# Node side
corepack enable
pnpm installDay-to-day commands:
# Python
uv run pytest # tests across the Python workspace
uv run ruff check . && uv run ruff format --check . # lint + format check
uv run mypy packages examples # type-check
uv run lint-imports --config importlinter.toml # cross-module-import contract
uv run pre-commit run --all-files # all pre-commit hooks
# Node
pnpm -r typecheck # type-check across the Node workspace
pnpm --filter @fms/vertical-<slug> dev # boot a vertical Nuxt app
pnpm --filter @fms/<lib> build # build a shared Node packagecp -r packages/_template packages/fms-<module>and renamesrc/fms_template/tosrc/fms_<module>/.- Update
name, AppConfig, and namespacedFMS_<MODULE>_*settings per PRD §5. - Append the importable name (
fms_<module>) to both lists in importlinter.toml —root_packagesand the "FMS modules are independent" contract. - Add the workspace source to the root pyproject.toml under
[tool.uv.sources]. - Run
uv sync, thenuv run pytest(per package) anduv run lint-imports --config importlinter.tomlto verify.
cp -r packages/_template-node packages/<lib>and updatepackage.json#nameto@fms/<lib>.- Replace
src/index.tswith the package's real public exports. - Append
packages/<lib>to[tool.uv.workspace].excludein root pyproject.toml so uv ignores the Node-only directory. - Run
pnpm installfrom repo root, thenpnpm --filter @fms/<lib> typecheckto verify.
cp -r verticals/_template verticals/<slug>where<slug>matches the roster in docs/superpowers/specs/2026-04-27-frontend-tech-stack-design.md.- Update
package.json#nameto@fms/vertical-<slug>and setruntimeConfig.public.fms.clusterinnuxt.config.ts. - (After Plan 2 lands) wire the
extends:chain innuxt.config.tsto@fms/uietc. - Run
pnpm install, thenpnpm --filter @fms/vertical-<slug> devto verify the app boots.
| Package | Purpose | Status |
|---|---|---|
packages/_template |
Reference layout for new Python modules | scaffolded |
fms-identity |
Multi-tenancy, orgs, invites, RBAC primitives | planned |
fms-audit |
Append-only change log; WORM-ready | planned |
fms-notifications |
Unified email/SMS/push dispatch | planned |
fms-files |
Pre-signed S3/R2 uploads + PDF generation | planned |
fms-billing |
Stripe subscriptions + usage reporting | planned |
fms-integrations |
OAuth framework + reference QBO provider | planned |
fms-importer |
CSV/Excel import with pydantic validation | planned |
fms-reporting |
Saved queries + PDF/CSV export | planned |
fms-jobs |
Scheduling primitives + recurrence | planned |
fms-contacts |
Tenant-scoped CRM-lite | planned |
fms-forms |
JSON-Schema-driven forms | planned |
fms-messaging |
SMS/email thread history | planned |
fms-payments |
Stripe Invoicing for one-off revenue | planned |
Node (Nuxt 4 layers and shared libs — see frontend spec)
| Package | Purpose | Status |
|---|---|---|
packages/_template-node |
Reference layout for new Node libs | scaffolded |
@fms/ui |
Design tokens (incl. clusters), Reka primitives, Storybook | planned |
@fms/shell |
Nav shell, auth (Nitro BFF), tenant resolver, dashboard | planned |
@fms/i18n |
Label aliasing, vertical-namespaced messages | planned |
@fms/field |
PWA layer, offline queue, mobile primitives | planned |
@fms/api |
Generated OpenAPI types + typed client | planned |
@fms/forms |
JSON-Schema-driven form renderer (Draft 2020-12) | planned |
@fms/testing |
Shared Vitest/Playwright utilities | planned |
Vertical Nuxt 4 apps. Newsroom-style slug encodes vertical + workflow wedge. Cluster determines emotional register (typography, density, voice).
| Slug | Vertical | Workflow wedge | Cluster | Status |
|---|---|---|---|---|
verticals/_template |
— | — | (operational default) | scaffolded |
bookkeeping-close |
Small bookkeeping | QBO close-week AR triage | operational | planned |
hr-1099 |
HR | 1099 contractor classification risk | compliance-anxious | planned |
hvac-dispatch |
HVAC / Plumbing | Field dispatch | blue-collar | planned |
funeral-intake |
Family funeral homes | Multi-portal intake | calm-institutional | planned |
trucking-ifta |
Owner-operator trucking | IFTA filing | blue-collar | planned |
insurance-renewals |
Independent insurance | Policy renewals | compliance-anxious | planned |
| Path | Description |
|---|---|
examples/saas-sampler |
Reference Django project. Will compose ≥5 modules by §10 acceptance. |
This bootstrap satisfies Phase 0 of PRD §7: workspace, CI, importlinter, pre-commit, package template, and consumer skeleton. Phase 1 (fms-identity, fms-audit, fms-notifications, fms-files) is next on the Python side. The frontend foundation (pnpm workspace, vertical/Node templates, vault rename, spec amendment) is complete; Plans 2–8 (per docs/superpowers/plans/2026-04-27-fms-frontend-foundation.md) build the Node packages and verticals.