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>
7.9 KiB
Beauty Module Migration Report
Date: 2026-07-26
Scope: Migrate Beauty business logic to frontend/modules/beauty
Routes: Unchanged — all URLs remain under /beauty/* via app/beauty/
Executive Summary
The Beauty Business module is the first completed migration from legacy components/beauty/ + scattered lib//hooks/ files into the formal modules/beauty/ package. All 98 route pages and 8 layouts remain in app/beauty/ as thin adapters; business logic now lives in the module.
| Validation | Result |
|---|---|
| Typecheck | ✅ Pass |
| Lint | ✅ Pass (3 pre-existing accounting warnings) |
| Build | ✅ Pass |
| Import validation | ✅ Pass |
| Route validation | ✅ Pass |
| Architecture validation | ✅ Pass |
| Bundle validation | ✅ Pass (196 compiled beauty segments) |
1. What Moved
From → To
| Legacy path | New path | Files |
|---|---|---|
components/beauty/*.tsx |
modules/beauty/components/ |
4 |
components/beauty/pages/*.tsx |
modules/beauty/pages/ |
9 |
components/beauty/design-system/* |
modules/beauty/design-system/ |
6 |
lib/beauty-business-api.ts |
modules/beauty/services/beauty-business-api.ts |
1 |
lib/beauty-portals.ts |
modules/beauty/constants/portals.ts |
1 |
hooks/useBeautyLookups.ts |
modules/beauty/hooks/useBeautyLookups.ts |
1 |
app/beauty/(owner)/**/page.tsx (inline CRUD) |
modules/beauty/features/owner/*.tsx |
18 |
Total module files: 43 (including README, index barrels)
Deleted / emptied
components/beauty/— fully removed (0 files remain)
2. What Stayed in app/beauty/
Per migration rules, only Next.js routing artifacts remain:
| Artifact | Count | Role |
|---|---|---|
page.tsx |
98 | Thin re-exports to @/modules/beauty/* |
layout.tsx |
8 | Portal layouts calling createPortalLayout() |
loading.tsx |
0 | (none existed) |
error.tsx |
0 | (none existed) |
not-found.tsx |
0 | (none existed) |
Layout files (unchanged URLs)
app/beauty/layout.tsx
app/beauty/(owner)/layout.tsx
app/beauty/owner/layout.tsx
app/beauty/admin/layout.tsx
app/beauty/customer/layout.tsx
app/beauty/reception/layout.tsx
app/beauty/staff-portal/layout.tsx
app/beauty/site/layout.tsx
Route adapter pattern
Portal pages (unchanged pattern):
export { CustomerWallet as default } from "@/modules/beauty/pages/customer";
Owner CRUD pages (new thin adapters):
export { default } from "@/modules/beauty/features/owner/organizations";
3. Module Structure
modules/beauty/
├── README.md
├── index.ts # Public barrel
├── components/
│ ├── BeautyPortalShell.tsx
│ ├── PublicBeautyLayout.tsx
│ ├── createPortalLayout.tsx
│ └── BeautyBusinessShell.tsx (@deprecated)
├── pages/
│ ├── admin.tsx, customer.tsx, owner.tsx, reception.tsx
│ ├── staff-portal.tsx, public.tsx, hub.tsx, shared.tsx
│ └── mobile.tsx
├── features/owner/ # 18 CRUD screens
│ ├── organizations.tsx
│ ├── customers.tsx, branches.tsx, appointments.tsx
│ ├── catalog-services.tsx, catalog-categories.tsx
│ ├── staff.tsx, staff-commissions.tsx
│ ├── packages.tsx, packages-memberships.tsx
│ ├── salon-*.tsx, booking-*.tsx
│ ├── marketing-*.tsx, settings.tsx
├── design-system/
│ ├── tokens.ts, BeautyStatusChip.tsx, BeautyCards.tsx
│ ├── BeautyPrimitives.tsx, BeautyTablePage.tsx
│ └── index.ts
├── hooks/
│ └── useBeautyLookups.ts
├── services/
│ └── beauty-business-api.ts # 1,446 lines
├── constants/
│ └── portals.ts
├── types/
│ └── index.ts
├── forms/ # Reserved (README scaffold)
├── tables/ # Reserved — BeautyTablePage in design-system/
├── calendar/ # Reserved
├── charts/ # Reserved
└── utils/ # Reserved
4. Import Migration
New canonical imports
import { beautyBusinessApi } from "@/modules/beauty/services/beauty-business-api";
import { createPortalLayout } from "@/modules/beauty/components/createPortalLayout";
import { useBeautyLookups } from "@/modules/beauty/hooks/useBeautyLookups";
import { BEAUTY_PORTALS } from "@/modules/beauty/constants/portals";
import { CustomerDashboard } from "@/modules/beauty/pages/customer";
Deprecated shims (backward compatible)
| Shim | Re-exports |
|---|---|
lib/beauty-business-api.ts |
@/modules/beauty/services/beauty-business-api |
lib/beauty-portals.ts |
@/modules/beauty/constants/portals |
hooks/useBeautyLookups.ts |
@/modules/beauty/hooks/useBeautyLookups |
119 files updated by scripts/migrate-beauty-imports.mjs. Zero remaining @/components/beauty/* imports in source.
5. URL Preservation
All beauty URLs are unchanged. Examples:
| URL | Route file | Module export |
|---|---|---|
/beauty/hub |
app/beauty/hub/page.tsx |
pages/hub |
/beauty/customer/wallet |
app/beauty/customer/wallet/page.tsx |
pages/customer |
/beauty/organizations |
app/beauty/(owner)/organizations/page.tsx |
features/owner/organizations |
/beauty/site/book |
app/beauty/site/book/page.tsx |
pages/public |
/beauty/admin/analytics |
app/beauty/admin/analytics/page.tsx |
pages/admin |
No next.config.mjs redirect changes. No backend modifications.
6. Tooling Updates
| File | Change |
|---|---|
tsconfig.json |
@/modules/* alias (already present) |
tailwind.config.ts |
Added ./modules/**/*.{ts,tsx} to content |
.eslintrc.json |
Beauty rules apply to modules/beauty/**/* |
scripts/validate-architecture.mjs |
Beauty domain = modules/beauty |
scripts/validate-beauty-imports.mjs |
New |
scripts/validate-beauty-routes.mjs |
New |
scripts/validate-beauty-bundle.mjs |
New |
package.json |
Added validate:beauty* scripts |
components/ds/Button.tsx |
Added loading prop (unblocks build) |
Validation commands
npm run typecheck
npm run lint
npm run validate:beauty-imports
npm run validate:beauty-routes
npm run validate:architecture
npm run build
npm run validate:beauty-bundle
# Or all beauty checks:
npm run validate:beauty
7. Boundaries
| Rule | Status |
|---|---|
| Beauty must not import healthcare/accounting | ✅ Enforced |
| Shared/ds must not import modules/beauty | ✅ Enforced |
| Healthcare/accounting unchanged | ✅ |
| Backend unchanged | ✅ |
| CRM not present | N/A |
8. Not Migrated (by design)
| Item | Reason |
|---|---|
| Healthcare | Explicitly out of scope |
| Accounting | Explicitly out of scope |
shared/ code |
Platform layer — Phase 2 |
components/ds/ |
Shared design system |
lib/beauty-business-nav.ts |
Dead file (0 imports pre-migration) |
| Auth guards, SiteHeader | Platform components |
9. Follow-up Recommendations
- Remove deprecated shims after confirming no external consumers of
lib/beauty-*paths - Move BeautyTablePage to
modules/beauty/tables/when table abstraction is extracted - Extract owner forms into
modules/beauty/forms/if CRUD forms grow further - Apply same pattern to Healthcare as next module migration
- Delete
BeautyBusinessShell.tsxafter confirming zero imports