Overview
High-level overview of the SPA (Single Page App) architecture: purpose, dual-mode coexistence, module classification, and core concepts.
SPA Architecture
Unify eight previously independent React module builds into a single React application served from /crelio-dashboard/, eliminating full-page reloads between modules while maintaining backward-compatible single-build deployments.
SPA Architecture
SPA Architecture is the transition of livehealth-frontend from a multi-HTML-entry-point model to a single unified React application called CrelioDashboard. In the legacy model, navigating between staff modules (Registration → Operations → Finance) triggered a complete browser reload: new HTML document, fresh React bootstrap, re-initialization of Redux, i18n, AG Grid, LaunchDarkly, Sentry, and re-fetch of session, settings, department lists, and doctor lists. This created 3-5 second delays on every module switch, destroyed transient state, and caused redundant API calls.
The SPA keeps a single React tree alive across module switches. Module navigation becomes an in-memory hash route change — instant, with no network overhead. Session data, Redux store, sidebar navigation, and all initialized providers are shared across modules.
Both architectures coexist in production. The is_spa_enabled Redis flag (is_spa_enabled_{lab_id}) controls which mode a lab receives. New labs default to SPA; existing labs migrate via the support dashboard. Support users always receive the SPA regardless of the lab flag.
Related Jira Tickets
| Ticket | Title | Notes |
|---|---|---|
| EN-5793 | SPA Architecture | Internal engineering initiative to unify staff modules into a single React application |
Prerequisites
| Requirement | Why it matters | Where it is enforced |
|---|---|---|
is_spa_enabled_{lab_id} must be True in Redis | The feature flag determines whether the lab receives SPA or legacy builds | labs/cacheFunction.py |
Lab must be on React v5 builds (reactVersionAccess == 1 or newRegistrationPage == 3) | The SPA only applies to v5 React module builds, not legacy v4 Jinja templates. reactVersionAccess == 1 or newRegistrationPage == 3 indicates v5; anything else is v4. | livehealth_4/decorators/version_decorator.py — mapped_spa_url() |
crelio-dashboard.html build artifact must be deployed to build_assets/CrelioDashboard/build/ | The Django view serves this HTML file | livehealth_4/views.py — CrelioDashboardView |
Login flow must populate is_spa_enabled in the Django session | Frontend and Django templates can check SPA status without additional Redis lookups | logins/utils/session_helpers.py |
Note: If a user logs in via Support Login (
isSupportLogin = True), the system always opens the SPA — regardless of whether the lab hasis_spa_enabledset toTrueor not. This allows support users to debug any lab using the unified SPA view without needing to toggle the feature flag.
What Is It For
Frontend perspective
- Eliminate full-page reloads between staff module switches (Registration, Operations, Finance, etc.).
- Keep a single React tree alive across all module navigations — Redux store, providers, and sidebar remain initialized.
- Enable instant module switching via in-memory hash route changes instead of browser navigation.
- Share session state, settings, department lists, and doctor lists across all modules — fetched once during bootstrap.
- Provide a unified sidebar with a module switcher dropdown and cross-module spotlight search (
Cmd+K). - Maintain code-splitting via
React.lazy()so only the active module's components are loaded.
Backend perspective
- Serve a single HTML template (
crelio-dashboard.html) for all SPA-eligible modules instead of per-module templates. - Control SPA rollout per-lab via the
is_spa_enabled_{lab_id}Redis flag with instant rollback capability. - Map legacy module URLs to SPA hash routes using
SPA_URL_MAPPERso existing bookmarks and redirects continue working. - Maintain backward compatibility — labs with SPA disabled continue receiving per-module HTML builds without any change.
- Support login bypass — support users always receive the SPA for faster debugging regardless of lab flag state.
Module Classification
SPA-Eligible Modules (Clubbable)
These modules share the same staff session context and are unified under the CrelioDashboard SPA build:
| Module | SPA Route | Build Entry (Legacy) |
|---|---|---|
| Registration | /registration/ | src/modules/Registration/index.tsx |
| Accession | /accession/ | src/modules/Accession/index.tsx |
| Operations | /operation/ | src/modules/Operations/index.tsx |
| Finance | /finance/ | src/modules/Finance/index.tsx |
| Admin | /admin/ | src/modules/Admin/index.tsx |
| LabAdmin | /lab-admin/ | src/modules/LabAdmin/index.tsx |
| Inventory | /inventory/ | src/modules/inventory/index.tsx |
| CRM Dashboard | /crm-dashboard/ | src/modules/crmDashboard/index.tsx |
Standalone Modules (Separate Builds)
These modules serve different user roles and require their own isolated sessions:
| Module | URL | Reason for Isolation |
|---|---|---|
| DoctorLogin | /v4/doctor/ | Doctor-specific session, different settings API |
| ReferralLogin | /v4/referral/ | Referral doctor session, subset of features |
| OrganisationLogin | /org-login/ | Organization-specific session and billing context |
| MarketingLogin | /marketing/ | Marketing-only access, no lab operations |
| centerdashboard | /center-dashboard/ | Multi-centre aggregation view, separate data model |
| CRM | /crm/ | Standalone CRM module with its own entry point and build |
Key Features
- Instant module switching — in-memory hash route changes instead of full browser reloads, eliminating 3-5 second delays.
- Shared session and state — session data, Redux store, settings, department lists, and doctor lists initialized once and shared across all modules.
- Unified sidebar and module switcher — single sidebar with a dropdown to switch between modules, dynamically resolving the active module from the URL.
- Spotlight search —
Cmd+K/Ctrl+Kcross-module search integrated into the SPA. - Code-splitting per module —
React.lazy()+Suspenseensures only the active module's components are loaded, keeping the initial bundle size manageable. - Dual-mode coexistence — SPA and legacy single-build deployments coexist in production, controlled per-lab via Redis flag with instant rollback.
- Backward-compatible URL mapping —
SPA_URL_MAPPERtranslates legacy module URLs to SPA hash routes so existing bookmarks, redirects, and login flows continue working. - Support user override — support users always receive the SPA regardless of lab flag, enabling faster debugging with the unified view.