Admin Dashboard Development
Stack
- Vite for dev server and bundling
- React 19 with TypeScript
- shadcn/ui components on Tailwind v4
ra-core— the headless half of react-admin — for resources, list/edit/create/show, data and auth providers@auth0/auth0-spa-jsfor the admin user's own login
Project Structure
apps/admin/
├── public/
│ └── favicon.svg # default bundled favicon
├── src/
│ ├── index.tsx # outer router + branding boot
│ ├── App.tsx # inner react-admin Router
│ ├── TenantsApp.tsx # tenant-management UI
│ ├── AuthCallback.tsx # OAuth callback handler
│ ├── authProvider.ts # auth0-spa-js wrapper for ra-core
│ ├── auth0DataProvider.ts # management API data provider
│ ├── components/ # shadcn-based UI components
│ ├── layout/ # app layout shell
│ ├── resources/ # one folder per ra-core resource
│ ├── utils/
│ │ └── runtimeConfig.ts # env + window config + applyBranding()
│ └── styles/globals.css
├── index.html
├── vite.config.ts
└── package.jsonDual-router model
The admin runs two routers stacked, both BrowserRouter:
- Outer router in
src/index.tsx:/→ domain selection (or redirect to/tenantswhenVITE_AUTH0_DOMAINis preconfigured)/auth-callback→ OAuth code exchange/tenants/*→ tenant management UI (TenantsApp)/:tenantId/*→ per-tenant admin (App) mounted withbasename="/:tenantId"
- Inner router in
src/App.tsx: thera-core<Router>with resources scoped to a single tenant.
This is why every per-tenant link is naturally tenant-scoped — the inner router never has to know which tenant it's mounted under.
Configuration
All runtime/build-time configuration flows through src/utils/runtimeConfig.ts. See Installation for the full list.
applyBranding() is called once at boot from src/index.tsx and applies appName (→ document.title) and faviconUrl (→ <link id="app-favicon">). The top-bar logo/wordmark is rendered by src/components/admin/layout.tsx.
Development Workflow
pnpm admin dev # start dev server on :5173
pnpm admin type-check # tsc --noEmit
pnpm admin test # vitest
pnpm admin lint
pnpm admin formatBuilding for Production
pnpm admin buildOutput lands in apps/admin/dist/ and can be served from any static host. The bundle uses base: "./" so it works from any sub-path; pair it with VITE_BASE_PATH (build-time) or basePath on window.__AUTHHERO_ADMIN_CONFIG__ (runtime) when mounting under a path like /admin.
Testing
pnpm admin testTests run in jsdom via Vitest. The test environment presets VITE_AUTH0_API_URL and VITE_AUTH0_DOMAIN to local stubs — see vite.config.ts.