# 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`
