# TorbatYar Frontend — Module Boundaries **Date:** 2026-07-26 **Scope:** Frontend import and ownership rules **Aligns with:** `docs/architecture/module-boundaries.md` (platform-level) --- ## 1. Module Inventory | Module ID | Route prefix | Component root | API client | BFF route | |-----------|--------------|----------------|------------|-----------| | **platform** | `/`, `/login`, `/register`, `/onboarding`, `/dashboard`, `/auth` | `components/` (root), `components/ui/`, `components/auth/` | `lib/api.ts`, `lib/auth.ts`, `lib/identity.ts` | None (direct) | | **admin** | `/admin` | `components/admin/` | `lib/api.ts` | None (direct) | | **accounting** | `/accounting` | `src/modules/accounting/` | `src/modules/accounting/services/accounting-api.ts` | `/api/accounting/*` | | **beauty** | `/beauty` | `modules/beauty/` | `modules/beauty/services/beauty-business-api.ts` | `/api/beauty-business/*` | | **healthcare** | `/healthcare` | `src/modules/healthcare/` | `src/modules/healthcare/services/healthcare-api.ts` | `/api/healthcare/*` | **Not yet in frontend:** delivery (backend exists; UI only via healthcare pharmacy portal), loyalty, communication, sports center, experience. **Partially migrated:** CRM (`modules/crm/`), Hospitality (`modules/hospitality/`). --- ## 2. Shared Layer (Cross-Module) These folders are **owned by the platform** and may be imported by any module: ``` components/ds/ # Design system — MUST remain domain-agnostic components/providers/ # Query, color mode components/AuthGuard.tsx components/AdminAuthGuard.tsx components/ThemeProvider.tsx components/SiteHeader.tsx components/TenantSwitcher.tsx components/RouteProgress.tsx components/AppStoreGrid.tsx components/settings/ # Account settings (platform) hooks/ # All shared hooks lib/utils.ts lib/auth.ts lib/theme.ts lib/apps-catalog.ts styles/globals.css ``` ### Shared layer rules | Rule | Status | |------|--------| | `components/ds/` MUST NOT import from domain modules | ✅ Compliant | | Shared hooks MUST NOT import domain API clients | ✅ Compliant | | Shared hooks MAY import `lib/auth.ts`, `lib/api.ts` (platform) | ✅ By design | | Platform components MUST NOT import domain shells | ✅ Compliant | --- ## 3. Domain Layer Rules Each business module owns: ``` app/{module}/ # Routes and layouts (thin re-exports when migrated) src/modules/{module}/ # Healthcare, Accounting module root modules/{module}/ # Beauty, CRM, Hospitality module root components/{module}/ # Legacy (removed for migrated modules) lib/{module}-api.ts # Deprecated shims → module services hooks/use{Module}*.ts # Deprecated shims → module hooks app/api/{service}/ # BFF proxy ``` ### Allowed import directions ``` ┌─────────────┐ │ shared │ │ ds, hooks │ │ lib/auth │ └──────▲──────┘ │ ┌─────────────────┼─────────────────┐ │ │ │ ┌─────┴─────┐ ┌──────┴──────┐ ┌──────┴──────┐ │ accounting │ │ beauty │ │ healthcare │ └───────────┘ └─────────────┘ └─────────────┘ ✕ ✕ ✕ └──────────────── no cross-imports ──┘ ``` | From → To | platform/shared | accounting | beauty | healthcare | admin | |-----------|:-:|:-:|:-:|:-:|:-:| | **platform** | ✅ | ❌ | ❌ | ❌ | ✅ (shell only) | | **accounting** | ✅ | ✅ | ❌ | ❌ | ❌ | | **beauty** | ✅ | ❌ | ✅ | ❌ | ❌ | | **healthcare** | ✅ | ❌ | ❌ | ✅ | ❌ | | **admin** | ✅ | ❌ | ❌ | ❌ | ✅ | | **ds** | ✅ (internal) | ❌ | ❌ | ❌ | ❌ | **Current compliance:** ✅ Zero cross-domain imports detected. --- ## 4. Route Layer Rules ### What routes MAY contain - `"use client"` directive - Default export (page component or re-export) - Metadata exports (server components only) - Dynamic route param typing - Thin re-exports to `components/{module}/` ### What routes MUST NOT contain - Direct `fetch()` to microservice origins (use BFF or lib API client) - Business validation logic (>20 lines) - Form schemas (belong in components or `lib/schemas/`) - Reusable UI subcomponents (belong in `components/{module}/`) - Cross-module imports ### Current compliance by module | Module | Route thinness | Compliance | |--------|----------------|------------| | Beauty (portals/site) | 2–3 line re-exports | ✅ Excellent | | Healthcare (portals/site) | 2–3 line re-exports | ✅ Excellent | | Beauty `(owner)` CRUD | 44–245 lines inline | ⚠️ Violation | | Accounting | 3–663 lines inline | ❌ Major violation | | Platform/admin | Mixed | ⚠️ Acceptable | --- ## 5. API Boundary Rules ### Client-side API access | API | Access method | Correct | |-----|---------------|---------| | Accounting service | `accountingApi.*` → `/api/accounting/*` | ✅ | | Beauty business service | `beautyBusinessApi.*` → `/api/beauty-business/*` | ✅ | | Healthcare service | `healthcareApi.*` → `/api/healthcare/*` | ✅ | | Core platform | `api.*` → `NEXT_PUBLIC_BACKEND_URL` | ✅ | | Identity/Keycloak | `identity.*` → `NEXT_PUBLIC_IDENTITY_API_URL` | ✅ | ### Forbidden - Importing another module's API client - Calling microservice ports directly from browser (bypassing BFF) - Storing business rules in BFF route handlers (proxies must stay thin) --- ## 6. State & Cache Boundaries ### Query key namespaces Each module owns its query key prefix: ```typescript // Platform ["me"] ["theme", tenantId] // Accounting ["accounting", tenantId, ...] // Beauty ["beauty", tenantId, ...] // Healthcare ["healthcare", tenantId, ...] ``` **Rule:** Modules MUST NOT invalidate another module's query keys. **Current compliance:** ✅ No cross-module cache invalidation detected. --- ## 7. UI Component Boundaries ### Design system (`components/ds/`) - Domain-agnostic primitives only - No module-specific labels, icons, or business types - Used by all modules ### Module design systems | Module | Path | May import | |--------|------|------------| | Beauty | `modules/beauty/design-system/` | `@/components/ds`, `@/lib/utils` | | Healthcare | `src/modules/healthcare/design-system/` | `@/src/shared/ui`, `@/lib/utils` | | Accounting | (uses ds via `@/src/shared/ui`) | `@/src/shared/ui`, `@/lib/utils` | **Rule:** Module DS MUST NOT import from other modules' DS or pages. ### Legacy UI (`components/ui/`) - Platform/marketing surfaces only: homepage, auth, onboarding, dashboard - New module code MUST NOT import from `components/ui/` --- ## 8. Known Boundary Violations ### Structural (not import violations) | Issue | Type | Severity | |-------|------|----------| | Beauty at `modules/` vs Healthcare/Accounting at `src/modules/` | Path inconsistency | Low | | Global `SiteHeader` on public module sites | Layout leak | Medium | | `BeautyBusinessShell` deprecated but present | Dead code | Low | | Healthcare legacy redirect pages duplicate config | Redundancy | Low | | Beauty at `modules/` vs Healthcare at `src/modules/` | Path inconsistency | Low | | Accounting business logic in routes | Responsibility | **Resolved** — 120 thin adapters | ### Naming inconsistencies (boundary clarity) | Issue | Impact | |-------|--------| | healthcare uses `design-system/` (aligned with beauty) | Resolved in migration | | `lib/beauty-business-nav.ts` dead file alongside `lib/beauty-portals.ts` | Stale boundary docs | --- ## 9. Enforcement Recommendations ### ESLint `no-restricted-imports` (proposed) ```javascript // .eslintrc — example rules { "rules": { "no-restricted-imports": ["error", { "patterns": [ { "group": ["@/components/accounting/*"], "message": "Accounting components are not importable outside accounting module." }, { "group": ["@/components/beauty/*"], "message": "Beauty components are not importable outside beauty module." }, { "group": ["@/src/modules/healthcare/*"], "message": "Healthcare components are not importable outside healthcare module." }, { "group": ["@/components/healthcare/*"], "message": "Legacy healthcare path — use @/src/modules/healthcare/*." } ] }] } } ``` Apply overrides for files inside each module's `app/` and `components/` trees. ### CI checks (proposed) 1. **Import graph script** — fail on cross-domain edges 2. **Route size lint** — warn if `app/**/page.tsx` > 100 lines 3. **API client size** — warn if any `lib/*-api.ts` > 500 lines --- ## 10. Adding a New Module Checklist - [ ] Create isolated `app/{module}/`, `components/{module}/`, `lib/{module}-api.ts` - [ ] Add BFF at `app/api/{service}/[...path]/route.ts` - [ ] Register in `lib/apps-catalog.ts` - [ ] Add env vars to `next.config.mjs` - [ ] Use `components/ds/` exclusively (not `components/ui/`) - [ ] Define query key prefix `["{module}", tenantId]` - [ ] Add ESLint override allowing self-imports only - [ ] Document in this file --- ## Related Documents - [frontend-architecture-audit.md](./frontend-architecture-audit.md) - [import-report.md](./import-report.md) - [dependency-report.md](./dependency-report.md) - Platform: `docs/architecture/module-boundaries.md`