Move business logic out of App Router into module packages, add boundary validation scripts, and keep all routes as thin re-exports without changing URLs or API behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
TorbatYar Frontend — Import Report
Date: 2026-07-26
Scope: Import patterns, alias usage, violations, and conventions
1. Summary Statistics
| Metric | Value |
|---|---|
Total source files (.ts/.tsx) |
~481 |
| Total import statements | ~811 |
@/ alias imports |
756 (93%) |
Relative imports (./, ../) |
55 (7%) |
Files using @/ alias |
445 / 481 (92%) |
| Files using relative imports | 30 / 481 (6%) |
| Files using both patterns | 25 |
| Cross-domain imports | 0 |
| Circular import chains | 0 |
Verdict: Import conventions are strong and consistently applied.
2. Path Alias Configuration
tsconfig.json
{
"compilerOptions": {
"paths": { "@/*": ["./*"] }
}
}
Single alias @/ maps to frontend/ root. No scoped sub-aliases exist.
Implications
| Aspect | Effect |
|---|---|
| Readability | ✅ Clean absolute-style paths |
| Refactoring | ⚠️ No enforced module scoping via alias |
| Tree-shaking | Neutral — bundler resolves same as relative |
| IDE navigation | ✅ Works well |
| Boundary enforcement | ❌ Cannot restrict by alias alone — needs ESLint |
3. Import Pattern Analysis
Pattern A — Absolute @/ (dominant, 93%)
Used for all cross-folder imports:
// App route → component
export { CustomerWallet as default } from "@/components/beauty/pages/customer";
// Component → design system
import { Button, DataTable, PageHeader } from "@/components/ds";
// Component → API client
import { accountingApi } from "@/lib/accounting-api";
// Component → hook
import { useTenantId } from "@/hooks/useTenantId";
// Layout → guard
import { AuthGuard } from "@/components/AuthGuard";
Pattern B — Relative ./ (local composition, 7%)
Used within co-located modules:
// Page bundle → shared helpers
import { BeautyPageLoader, BeautyPageError } from "./shared";
// DS internal
import { Button } from "./Button";
// Design system barrel
export { BeautyStatusChip } from "./BeautyStatusChip";
export { CardShell } from "./BeautyCards";
// Portal layout → shell (same module)
import { BeautyPortalShell } from "@/components/beauty/BeautyPortalShell";
// Note: even same-module sometimes uses @/ — inconsistent but harmless
Pattern C — Re-export routes (beauty/healthcare)
~175 routes use single-line re-exports:
export { CustomerWallet as default } from "@/components/beauty/pages/customer";
This is the canonical thin-route pattern for the codebase.
4. Import Frequency by Target
Most imported modules
| Target | Approx. imports | Category |
|---|---|---|
@/components/ds |
90+ | Design system |
@/hooks/useTenantId |
67 | Shared hook |
@/lib/utils |
47 | Utilities |
@/lib/accounting-api |
30 | Domain API |
@/lib/beauty-business-api |
28 | Domain API |
@/lib/auth |
15 | Platform auth |
@/lib/healthcare-api |
14 | Domain API |
@/components/AuthGuard |
10+ | Platform guard |
@/hooks/useMe |
7 | Shared hook |
@tanstack/react-query |
70+ | External |
Most imported DS exports
| Export | Typical consumers |
|---|---|
Button |
All modules |
PageHeader |
All modules |
DataTable |
All modules |
LoadingState, ErrorState |
Portal layouts, pages |
Dialog, ConfirmDialog |
CRUD pages |
FormField, MoneyInput |
Accounting, beauty owner |
DatePicker |
Accounting |
5. Domain Import Isolation
Accounting imports
✅ @/components/ds
✅ @/components/accounting/*
✅ @/lib/accounting-api
✅ @/lib/accounting-nav
✅ @/hooks/useTenantId, useMe
✅ @/lib/auth, @/lib/utils
❌ @/components/beauty/* — NOT FOUND
❌ @/components/healthcare/* — NOT FOUND
❌ @/lib/beauty-business-api — NOT FOUND
❌ @/lib/healthcare-api — NOT FOUND
Beauty imports
✅ @/components/ds
✅ @/components/beauty/*
✅ @/lib/beauty-business-api
✅ @/lib/beauty-portals
✅ @/hooks/useTenantId, useMe, useBeautyLookups
❌ @/components/accounting/* — NOT FOUND
❌ @/components/healthcare/* — NOT FOUND
Healthcare imports
✅ @/components/ds
✅ @/components/healthcare/*
✅ @/lib/healthcare-api
✅ @/lib/healthcare-portals
✅ @/hooks/useTenantId, useMe, useHealthcareLookups, useHealthcarePatientContext
❌ @/components/accounting/* — NOT FOUND
❌ @/components/beauty/* — NOT FOUND
Platform imports
✅ @/components/ui — Marketing surfaces
✅ @/components/ds — Some admin/settings
✅ @/lib/api — Core backend
✅ @/lib/auth, @/lib/identity
❌ Domain module components — NOT FOUND
Compliance: 100% — no cross-domain import violations detected.
6. Shared Layer Import Compliance
components/ds/ imports
The design system imports only:
@/lib/utils(cn helper)- Internal relative
./imports - External packages (cva, lucide-react, react)
Does NOT import: any domain module ✅
hooks/ imports
| Hook | Allowed imports | Violations |
|---|---|---|
useMe |
@/lib/api |
None |
useTenantId |
@/hooks/useMe |
None |
useBeautyLookups |
@/lib/beauty-business-api |
None (domain hook) |
useHealthcareLookups |
@/lib/healthcare-api |
None (domain hook) |
useAuth |
@/lib/auth |
None |
Shared hooks (useMe, useTenantId, useAuth) do not import domain APIs. ✅
7. Improper Import Patterns
7.1 Legacy UI in new module code
| Issue | Severity | Details |
|---|---|---|
Module code importing components/ui/ |
🟡 Low | Not found in beauty/healthcare/accounting — compliant |
Platform code importing components/ui/ |
✅ Expected | Login, dashboard, homepage |
7.2 Deep imports bypassing barrels
Some files import directly from DS sub-files instead of barrel:
// Bypasses barrel — found occasionally
import { Button } from "@/components/ds/Button";
// Preferred
import { Button } from "@/components/ds";
Impact: Low — does not break boundaries, reduces barrel effectiveness.
7.3 Same-module @/ vs relative inconsistency
Beauty and healthcare components sometimes use @/components/beauty/... for same-module imports where ./ would suffice.
Impact: None functional; stylistic inconsistency only.
7.4 Server/client boundary
Most app routes are "use client" — no widespread server component data fetching pattern. API clients check typeof window for BFF vs direct URL.
Not a violation but limits RSC benefits.
8. External Package Imports
| Package | Import count | Modules using |
|---|---|---|
react |
All files | Universal |
next/navigation |
~50+ | Client routes (useRouter, redirect) |
next/link |
~30+ | Navigation |
next/image |
~10 | Public sites |
@tanstack/react-query |
~70+ | All modules |
react-hook-form |
~29 | Accounting, beauty owner |
@hookform/resolvers/zod |
~29 | With react-hook-form |
zod |
~35+ | Form schemas |
lucide-react |
~100+ | Icons everywhere |
sonner |
~40+ | Toast via import or AppProviders |
class-variance-authority |
2 | ds/Button, ds/Badge |
dayjs |
~5 | Date formatting |
jalaali-js |
1 | ds/DatePicker |
framer-motion |
~3 | Limited animation |
@tanstack/react-table |
0 | Unused |
recharts |
0 | Unused |
9. Import Graph Layers
┌─────────────────────────────────────────────────────────┐
│ app/**/page.tsx │
│ (routes — import components, occasionally inline) │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────┐
│ components/{module}/pages/*.tsx │
│ components/{module}/*Shell.tsx │
│ components/accounting/*.tsx │
└────────────────────────┬────────────────────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
│ components/ds│ │ hooks/ │ │ lib/*-api.ts │
└───────┬──────┘ └───────┬──────┘ └───────┬──────┘
│ │ │
└────────────────┼────────────────┘
│
┌────────▼────────┐
│ lib/auth.ts │
│ lib/utils.ts │
│ lib/api.ts │
└─────────────────┘
No back-edges detected. Graph is a DAG.
10. False-Positive Cross-Module Names
These filenames suggest cross-module coupling but are contained within their domain:
| Route/file | Looks like | Actually imports |
|---|---|---|
beauty/owner/accounting-integration/page.tsx |
Accounting | @/components/beauty/pages/owner |
beauty/owner/crm-integration/page.tsx |
CRM | @/components/beauty/pages/owner |
healthcare/clinic/accounting-integration/page.tsx |
Accounting | @/components/healthcare/pages/clinic |
Integration pages refer to external systems; they do not import other frontend modules.
11. Recommended Import Conventions
For new code
// 1. Design system — always from barrel
import { Button, DataTable } from "@/components/ds";
// 2. Domain code — absolute @/ within module
import { BeautyPortalShell } from "@/components/beauty/BeautyPortalShell";
// 3. Co-located helpers — relative
import { PageLoader } from "./shared";
// 4. Platform utilities
import { cn, formatMoney } from "@/lib/utils";
import { useTenantId } from "@/hooks/useTenantId";
// 5. Domain API — only in own module
import { beautyBusinessApi } from "@/lib/beauty-business-api";
// 6. NEVER cross-module
// import { AccountingShell } from "@/components/accounting/..."; // in beauty
Route files
// Preferred — thin re-export
export { MyPage as default } from "@/components/{module}/pages/{portal}";
// Acceptable — dynamic params wrapper
export { default } from "@/components/{module}/pages/public";
12. Enforcement Plan
| Mechanism | Purpose | Phase |
|---|---|---|
ESLint no-restricted-imports |
Block cross-domain paths | Phase 1 |
ESLint no-restricted-imports |
Block components/ui/ in domain code |
Phase 1 |
| Custom script: import graph | CI validation of DAG | Phase 1 |
Path aliases @accounting/* |
Make boundaries explicit | Phase 2 (optional) |
eslint-plugin-import ordering |
Consistent import sort | Phase 2 (optional) |