Infrastructure

Overview

High-level overview of the SPA (Single Page App) architecture: purpose, dual-mode coexistence, module classification, and core concepts.

👤 Aakash Pawar📅 Updated: Apr 20, 2026📁 SPA Architecture

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.

TicketTitleNotes
EN-5793SPA ArchitectureInternal engineering initiative to unify staff modules into a single React application

Prerequisites

RequirementWhy it mattersWhere it is enforced
is_spa_enabled_{lab_id} must be True in RedisThe feature flag determines whether the lab receives SPA or legacy buildslabs/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.pymapped_spa_url()
crelio-dashboard.html build artifact must be deployed to build_assets/CrelioDashboard/build/The Django view serves this HTML filelivehealth_4/views.pyCrelioDashboardView
Login flow must populate is_spa_enabled in the Django sessionFrontend and Django templates can check SPA status without additional Redis lookupslogins/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 has is_spa_enabled set to True or 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_MAPPER so 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:

ModuleSPA RouteBuild 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:

ModuleURLReason 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 searchCmd+K / Ctrl+K cross-module search integrated into the SPA.
  • Code-splitting per moduleReact.lazy() + Suspense ensures 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 mappingSPA_URL_MAPPER translates 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.

On this page