Frontend layout - Tenantx kernel (React + TypeScript)
The SPA is organized so tenant UI, platform admin, and shared infrastructure are obvious to extend.
Top-level (frontend/src/)
| Area | Path | Role |
|---|---|---|
| App shell & routes | App.tsx | BrowserRouter, lazy pages, protected layout |
| Lazy page map | components/LazyComponents.tsx | React.lazy imports for every page |
| Permission gate | components/PermissionRoute.tsx | Spatie permission name -> route guard |
| Navigation | components/navigation/SmartSidebar.tsx | titleKey + useHasPermission |
| Hooks | hooks/ | Domain subfolders (auth/, core/, ui/, subscription/, permissions/, …); entry points like @/hooks/auth/useAuth, @/hooks/core/useLanguage |
| API client | lib/api/ | ApiClient in client.ts; feature modules (authApi.ts, organizationsApi.ts, etc.) re-exported from client.ts |
| i18n | lib/translations/ | en.ts / ar.ts, merged page splits, types.ts |
| Tenant pages | pages/ | Kernel-only routes (dashboard, settings, org-admin, etc.) |
| Platform admin | platform/ | /platform shell, platformApi, platform hooks |
Import alias
Vite/TS resolve @/ -> src/ (see frontend/tsconfig*.json and frontend/vite.config.ts).
Convention: Prefer @/components/..., @/lib/api/client, @/hooks/... instead of deep relatives.
Inventory
To list files that use the @/ alias (sample of lines):
php scripts/inventory-kernel-structure.php
The JSON output includes frontend_src_ts_counts_by_top_level (.ts/.tsx counts per first segment under frontend/src/) and frontend_alias_imports_sample (large; capped in script). Use ripgrep for exact work:
rg "from ['\"]@/" frontend/src
Physical reorganization (optional)
hooks/ is grouped by domain (auth, core, ui, subscription, …). The map used for the initial hooks split is archived at scripts/frontend-reorg-map.hooks-applied.json; the active scripts/frontend-reorg-map.json defaults to [] so dry-run/apply do not expect old paths. pages/ and components/ stay mostly as before; use the map script to move more files when needed. To move additional files into subfolders (same idea as scripts/reorganize-kernel-models.php on the backend), use a JSON map and the reorganize script:
- Copy
scripts/frontend-reorg-map.example.jsontoscripts/frontend-reorg-map.json(or pass--map=...). - Edit the map: each entry is
{ "from": "hooks/useAuth.tsx", "to": "hooks/auth/useAuth.tsx" }— paths are relative tofrontend/src/(nosrc/prefix). Extension may be omitted (.tsx/.tsresolved). - Dry run — wrapper scripts (repo root) or PHP directly:
- Windows:
powershell -File scripts/frontend-reorg-dry-run.ps1orpwsh -File scripts/frontend-reorg-dry-run.ps1(optional:-Map scripts/my-map.json) - Bash:
./scripts/frontend-reorg-dry-run.sh(optional:MAP=scripts/my-map.json ./scripts/frontend-reorg-dry-run.sh) - PHP:
php scripts/reorganize-kernel-frontend.php --dry-run(optional:--map=scripts/frontend-reorg-map.json)
- Windows:
- Apply — same pattern:
powershell -File scripts/frontend-reorg-apply.ps1,scripts/frontend-reorg-apply.sh, orphp scripts/reorganize-kernel-frontend.php --apply - Verify:
cd frontend && npx tsc --noEmit.
Not handled automatically: import('./foo') dynamic imports, re-exports in index.ts barrels, or relative imports that are not plain from './x' (fix manually if needed). Prefer a worktree or branch for large moves.
Suggested groupings (taxonomy only — add to the map as you prefer):
| Area | Possible subfolders under src/ |
|---|---|
hooks/ | Done: auth/, core/, ui/, subscription/, organization/, permissions/, help-center/, users/, activity/, system/, workspaces/, notifications/, search/, utils/ |
pages/ | Already has settings/, org-admin/, subscription/; top-level route files could move under tenant/, auth/, etc. |
components/ | Already split (settings/, layout/, ui/); further group by feature |
Update components/LazyComponents.tsx and any relative imports in App.tsx (./pages/...) when you move pages — the script rewrites from './…' when resolution matches a map entry; adjust LazyComponents @/ strings if you rename modules.
Backend coupling
HTTP paths and permission names are documented in docs/PERMISSIONS.md and AGENTS.md. API types follow snake_case from Laravel; map in lib/api modules per nazim-api-domain-types skill.
Related
AGENTS.md- canonical architecture and API-module guidancedocs/I18N.md-en/aronly for SPA copy