# NX Monorepo Modularization - Scratchpad --- ## ⚠️ CRITICAL INSTRUCTION FOR CLAUDE ⚠️ **DO NOT CHEAT.** When implementing features: 0. **Work in large chunks before lint/build.** Prefer moving a whole coherent slice (e.g. an entire folder or feature) and fixing imports broadly. Only run lint/tests/build at the end of a large unit of work (or when truly blocked). Constant lint/build cycles are too expensive and slow the migration dramatically. 1. **Actually move/copy the files** - don't just create re-exports from the old location 2. **Update imports in the moved files** - fix relative imports to work in new location 3. **Update consumers** - change imports in files that use the moved code 4. **If you defer work**, add a NEW feature entry to features.json for that deferred work 5. **Only mark "implemented": true** when the actual migration is complete, not just scaffolding If you have the choice between an easy path (re-exports) and the right path (actual migration), **ALWAYS choose the right path**. If you need to defer harder work to later iterations, add explicit new features to track that work - don't just drop it or pretend it's done. ### Temporary Shim Exception (Migration Only) If a “shim” is required to keep work moving (e.g. to avoid editing dozens of call sites immediately), it must be: - treated as temporary and minimal (no long-lived architecture) - tracked explicitly in `features.json` (with a removal task) - removed once the owning package/horizontal slice has the real implementation --- ## Analysis Summary (2026-01-15) ### Current Codebase Metrics - **Total TypeScript/TSX files**: ~2,300+ - **Components**: 777 files across 42 domain directories - **Lib (actions, models, services, utils)**: 685 files - **API Routes**: 510 files - **Interfaces**: 52 files ### Existing Modular Patterns The codebase already uses npm workspaces with this structure: ```json "workspaces": [ "server", "ee/server", "services/workflow-worker", "services/email-service", "shared", "packages/*", "sdk/*" ] ``` ### Existing Packages (15 total) Located in `/packages/`: 1. `product-auth-ee` - Enterprise auth 2. `product-billing` - Billing features 3. `product-chat` - Chat functionality 4. `product-client-portal-domain` - Client portal domain logic 5. `product-email-domains` - Email domain management (consolidated into `@alga-psa/integrations/email`) 6. `product-email-providers` - Email provider integrations (consolidated into `@alga-psa/integrations/email`) 7. `product-email-settings` - Email configuration (consolidated into `@alga-psa/integrations/email`) 8. `product-ext-proxy` - Extension proxy 9. `product-extension-actions` - Extension server actions 10. `product-extension-initialization` - Extension init 11. `product-extensions-pages` - Extension pages 12. `product-extensions` - Core extensions 13. `product-settings-extensions` - Settings extensions 14. `product-workflows` - Workflow engine 15. `ui-kit` - UI component library ### Shared Library Structure `@alga-psa/shared` exports: - `./types` - Type definitions - `./core` - Logger, secret provider - `./db` - Database utilities, admin, connection - `./events/publisher.js` - Event publishing - `./utils/encryption.js` - Encryption utilities - `./workflow` - Workflow core, persistence, streams - `./models/*` - Shared models (client, contact, tag, ticket, user) - `./extensions/*` - Extension domain, installs, types --- ## Identified Feature Domains ### Large Domains (>30 component files) | Domain | Files | Notes | |--------|-------|-------| | billing-dashboard | 120 | Invoices, contracts, payments, credits | | settings | 86 | System configuration | | ui | 81 | Shared UI components | | projects | 50 | Project management, kanban, tasks | | client-portal | 42 | Client-facing portal | | assets | 37 | Asset management | | time-management | 32 | Time tracking, timesheets | | clients | 32 | Client profiles | ### Medium Domains (10-30 files) - surveys (25), workflows (24), user-activities (21) - tickets (19), documents (18), contacts (12) - technician-dispatch (13), auth (12), layout (11) - integrations (11) --- ## Proposed Module Architecture ### Horizontal Slices (Shared Infrastructure) 1. **@alga-psa/core** - Existing shared package, enhance with: - Logger, config, secrets - Event publisher - Encryption utilities 2. **@alga-psa/db** - Database layer - Knex configuration - Tenant context management - Connection pooling - Base model patterns 3. **@alga-psa/types** - Type definitions - All interface files - Shared types across features 4. **@alga-psa/validation** - Validation logic - Zod schemas - Form validation utilities - Business rule validators 5. **@alga-psa/ui** - UI component library - Enhance existing ui-kit - All shared UI components 6. **@alga-psa/auth** - Authentication - Auth strategies - Session management - Permission utilities ### Vertical Slices (Feature Modules) 1. **@alga-psa/billing** - Billing & Contracts - Invoicing - Contracts/contract lines - Payments - Credits - Tax management 2. **@alga-psa/clients** - Client Management - Client profiles - Contacts - Companies - Client relationships 3. **@alga-psa/projects** - Project Management - Projects - Tasks/phases - Kanban boards - Dependencies - Resource allocation 4. **@alga-psa/tickets** - Ticket/Issue Tracking - Support tickets - Categories - SLA management 5. **@alga-psa/scheduling** - Scheduling & Time - Time tracking - Timesheets - Calendar - Technician dispatch - Schedule entries 6. **@alga-psa/workflows** - Workflow Automation - Workflow engine - Triggers - Actions - Automation rules 7. **@alga-psa/documents** - Document Management - Document storage - Templates - Sharing 8. **@alga-psa/assets** - Asset Management - Asset tracking - Categorization - Service history 9. **@alga-psa/surveys** - Surveys - Survey creation - Responses - Analytics 10. **@alga-psa/integrations** - Third-party Integrations - QuickBooks - Email providers - Calendar providers - Webhooks 11. **@alga-psa/client-portal** - Client Portal - Portal UI - Portal-specific features - External access --- ## Key Decisions ### Decision 1: NX vs Enhanced npm Workspaces **Decision**: Use NX **Rationale**: - Existing npm workspaces show modular thinking is established ### Note: Vitest + Workspace Resolution (2026-01-15) Some dev/test setups may not have newly-added `@alga-psa/*` workspace packages linked into `node_modules`. For Vitest runs from the repo root, add explicit Vite/Vitest aliases (in `server/vitest.config.ts`) pointing `@alga-psa/*` imports to `packages/*/src` to keep unit tests runnable without reinstalling dependencies. ### Note: Root tsconfig.json (2026-01-15) Several `packages/*/tsconfig.json` files extend `../../tsconfig.json`. Ensure `tsconfig.json` exists at the repo root and extends `tsconfig.base.json` so those package configs work and editors/tools pick up the shared path aliases. ### Note: DB tenant context (2026-01-15) The `@alga-psa/db` package now owns tenant context via `AsyncLocalStorage` (`runWithTenant`, `getTenantContext`) and exports `createTenantKnex()`. The server-side `server/src/lib/db/index.tsx` continues to handle request/session/header tenant resolution but delegates context storage to `@alga-psa/db`. ### Note: Vitest coverage temp dir (2026-01-15) Vitest v8 coverage writes a temp directory under `server/coverage/.tmp`. Ensure it exists during test runs (created in `server/src/test/setup.ts`) to avoid occasional `ENOENT` errors when running multiple targeted tests. ### Note: Nx project.json coverage (2026-01-15) Many `packages/*` were created without `project.json`, which prevented them from being first-class Nx projects. Added `project.json` files for all new `@alga-psa/*` packages (and `packages/ui-kit`) so `nx graph`, caching, and affected commands can reason about them. - NX adds: computation caching, affected commands, dependency graph visualization - Better for large codebase with 2300+ files - Enables parallel builds and test optimization ### Note: UI package split (2026-01-16) The existing `packages/ui-kit` is used by SDK/extension template consumers and should remain Tailwind-free to avoid breaking external usage. The app/server UI components from `server/src/components/ui` (Tailwind + Radix heavy) were migrated into a new internal package `packages/ui` (`@alga-psa/ui`), and server consumers were updated to import from `@alga-psa/ui`. ### Decision 2: Module Boundaries **Decision**: Feature-based vertical slices over layer-based **Rationale**: - Aligns with existing component organization - Enables independent deployment/testing - Clear ownership boundaries - Reduces cross-team conflicts ### Decision 3: Next.js Routes Location **Decision**: Keep all routes in single `server/` project **Rationale**: - Next.js requirement - App Router needs single entry - Routes become thin shims calling into feature modules - API routes can delegate to feature modules ### Decision 4: Migration Strategy **Decision**: Incremental, bottom-up **Rationale**: - Start with horizontal slices (already partially exist in `shared/`) - Add vertical slices one feature at a time - Maintain backwards compatibility during migration - Can deploy incrementally --- ## Technical Constraints 1. **Next.js App Router**: All routes must remain in single project 2. **CitusDB**: Tenant column requirements affect data layer design 3. **Enterprise Edition**: CE/EE code separation must be maintained 4. **Existing Workspaces**: Must migrate, not break existing package structure --- ## Commands & References ### Useful Commands ```bash # Current workspace structure npm ls --workspaces # Check package dependencies npm -w server ls # Run tests for specific workspace npm -w server test ``` ### Key File Paths - Root package.json: `/package.json` - Server package.json: `/server/package.json` - Shared exports: `/shared/package.json` - Coding standards: `/docs/AI_coding_standards.md` --- ## Open Questions 1. **Billing + Contracts**: Should these be one module or separate? - Current thinking: Combined as `@alga-psa/billing` (they're tightly coupled) 2. **Email modules**: Consolidated into `@alga-psa/integrations/email` (formerly `product-email-domains`, `product-email-providers`, `product-email-settings`). 3. **Extension packages**: 7 extension-related packages - keep as-is or consolidate? 4. **UI components**: Current ui-kit is minimal - expand or keep ui in each feature? - Recommendation: Expand ui-kit as `@alga-psa/ui` for all shared components --- ## Migration Order (Proposed) ### Phase 1: Foundation 1. Initialize NX workspace 2. Migrate `shared/` to `@alga-psa/core`, `@alga-psa/db`, `@alga-psa/types` 3. Create `@alga-psa/validation` from existing validation utilities 4. Expand `ui-kit` to `@alga-psa/ui` ### Phase 2: Infrastructure Features 5. Create `@alga-psa/auth` from auth actions/lib 6. Create `@alga-psa/integrations` (consolidate email packages + integrations) ### Phase 3: Core Business Features 7. Create `@alga-psa/clients` (clients + contacts) 8. Create `@alga-psa/billing` (invoicing + contracts) 9. Create `@alga-psa/projects` 10. Create `@alga-psa/tickets` ### Phase 4: Supporting Features 11. Create `@alga-psa/scheduling` (time + dispatch + calendar) 12. Create `@alga-psa/workflows` 13. Create `@alga-psa/documents` 14. Create `@alga-psa/assets` 15. Create `@alga-psa/surveys` 16. Create `@alga-psa/client-portal` ### Phase 5: Optimization 17. Configure NX caching 18. Set up affected commands for CI 19. Optimize build pipeline --- ## Implementation Notes (2026-01-16) - **@alga-psa/types interface migration**: synced `server/src/interfaces` into `packages/types/src/interfaces`, removed duplicate/stub interface files that caused resolution ambiguity, fixed self-imports inside the types package, and added tests to validate the barrel exports. Inbound email types are exported under `Inbound*` aliases to avoid name collisions with outbound email types. - **NX graph/tests**: `NX_DAEMON=false` avoids the earlier nx command hangs; added an integration test at `tools/nx-tests/nxWorkspace.test.ts` to validate `nx show projects`, `nx graph --file`, and generator dry-run. - **Module boundaries**: added ESLint rule `custom-rules/no-feature-to-feature-imports` to prevent `packages/` vertical packages from importing other vertical packages via `@alga-psa/*` (validated in `tools/nx-tests/moduleBoundaries.test.ts`). `nx lint` is currently too memory-hungry (heap OOM) to use as an enforcement test in this environment. - **npm workspace protocol**: removed `workspace:*` dependency specifiers from `packages/*/package.json` (replaced with `*`) because npm cannot install/update dependencies when `workspace:` protocol is used. - **NX caching + affected**: added `npm run test:nx` (vitest config for `tools/nx-tests`) including a cache verification test (`nxCache.test.ts`) and an affected-project selection test (`nxAffected.test.ts`); added `npm run affected:test` and `npm run affected:build` scripts; updated `.github/workflows/typecheck.yml` to run `nx affected -t build`/`test`. - **@alga-psa/clients vertical slice**: migrated client/contacts actions + components into `packages/clients` and updated the `/msp/clients` + `/msp/contacts` routes to import from `@alga-psa/clients` (and actions from `@alga-psa/clients/actions`); `server npm run build` passes after import rewiring. - **Tax + client type alignment**: resolved an `ITaxRate` export collision by selectively exporting tax interfaces from `@alga-psa/types` (including `ITaxRateDetails` alias). Also aligned client/contacts typing by using `@alga-psa/types` in key action/components and allowing `client.properties` to be nullable where DB can return null. --- ## Implementation Notes (2026-01-18) ### server/src import cleanup (packages) - Verified no remaining `from 'server/src'` or `import('server/src/...')` usages under `packages/**`. ### Documents storage self-containment - Added missing documents storage primitives under `packages/documents/src/`: - `config/storage.ts` (env/secret-driven storage config + validation) - `types/storage.ts` (provider + file store types) - `models/storage.ts` (`FileStoreModel` without `BaseModel`; tenant resolved via `requireTenantId`) - Rewired documents storage imports to stay within `packages/documents/src/**` (avoids importing files outside the package `src/` root). - Removed `@alga-psa/users/actions` dependency from documents storage to avoid pulling incomplete user avatar utilities into core storage logic. ### Business-logic tests added - Scheduling: `packages/scheduling/tests/timePeriodSuggester.test.ts` (run `npm -w packages/scheduling test`) - Documents: `packages/documents/tests/storageConfig.test.ts` (run `npm -w packages/documents test`) - Auth: adjusted `packages/auth/src/lib/exports.test.ts` to validate RBAC behavior via the subpath export `@alga-psa/auth/rbac` (keeps the test focused and avoids pulling Next.js UI modules). ### Known tooling limitation (out of scope here) - `tsc --noEmit` in many packages currently fails with `rootDir`/project-reference issues when TypeScript path aliases pull in other package sources (example: importing `@alga-psa/tenancy/actions` from another package). Unit tests via Vitest are still runnable and used for verification.