# 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):** ```tsx export { CustomerWallet as default } from "@/modules/beauty/pages/customer"; ``` **Owner CRUD pages (new thin adapters):** ```tsx 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 ```typescript 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 ```bash 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 1. **Remove deprecated shims** after confirming no external consumers of `lib/beauty-*` paths 2. **Move BeautyTablePage** to `modules/beauty/tables/` when table abstraction is extracted 3. **Extract owner forms** into `modules/beauty/forms/` if CRUD forms grow further 4. **Apply same pattern to Healthcare** as next module migration 5. **Delete `BeautyBusinessShell.tsx`** after confirming zero imports --- ## 10. Related Documents - [frontend-architecture.md](./frontend-architecture.md) - [frontend-migration-plan.md](./frontend-migration-plan.md) - [module-boundaries.md](./module-boundaries.md) - [../modules/beauty/README.md](../modules/beauty/README.md)