Building Modern React Components Inside Open EMR: Without Breaking the Core

By May 12, 2026Emerging Tech
Open EMR Thumbnail

Key Takeaways

  • React 18 can be integrated into OpenEMR without replacing the PHP backend or modifying core clinical workflows.
  • The strangler fig modernization pattern enables incremental UI upgrades instead of risky full-system rewrites.
  • Independently deployable React modules allow organizations to modernize one workflow at a time with minimal operational disruption.
  • Clinical workflows such as messaging, reminders, and patient lookup saw measurable usability and productivity improvements.
  • Zero-reload interfaces significantly reduce clinician friction and administrative overhead.
  • The PoC achieved production-grade integration in just eight weeks with a small engineering team.
  • Organizations can validate modernization strategies through low-risk PoCs before committing to broader implementation.
  • Open-source EHR platforms like OpenEMR can compete with commercial systems on user experience without sacrificing flexibility or ownership.

Introduction: The Healthcare Software Dilemma

Healthcare organizations are under increasing pressure to modernize the clinician experience without disrupting the systems that already power patient care. OpenEMR remains one of the most widely adopted open-source EHR platforms in the world because of its clinical depth, flexibility, and cost efficiency. But like many long-standing healthcare systems, its frontend architecture reflects the era in which it was built a mix of PHP templates, jQuery, and legacy rendering patterns that struggle to meet today’s expectations for speed, usability, and workflow efficiency.

For most healthcare IT leaders, modernization appears to present only two options: tolerate the outdated interface and absorb the operational inefficiencies, or commit to a costly, high-risk full-system rewrite. Neither approach is practical for organizations that rely on OpenEMR every day to manage patient care.

Healthcare software is at an inflection point. Clinical teams now use consumer-grade SaaS tools Slack, Notion, and Figma that are fast, reactive, and built for modern workflows. The EHR systems they depend on for clinical care are not keeping pace. The gap between what clinical staff experience outside the EHR and inside it is widening every year.

At Bitcot, we chose a third path. The PoC we are documenting here, which we call OpenEMR React Studio, demonstrates that a production-grade modern interface can be delivered to specific clinical workflows in weeks, without disrupting anything that already works, using an approach borrowed from one of software engineering’s most effective modernization strategies.
The strategy is the strangler fig pattern. The technology is React 18.

The Industry Has a Problem. It has been ignored

OpenEMR’s frontend was not designed badly; it was designed for its era. The templates built on Smarty, Twig, and plain PHP were the right choices when the system was first architected. jQuery 1.x handled interactive behavior at a time when React did not exist. Angular 1.8 represented an attempt to modernize in its time. The result is a system that works but is built on technologies that are collectively 10-15 years past their prime, each with its own rendering model, its own event system, and its own assumptions about how state should flow.

The problem is not the individual technology choices. It is the combination of layers of different frontend approaches with no shared design system, no unified component model, and no mechanism for adding modern interactive features without touching the PHP core.

The Two Dominant Responses Both Fail for Predictable Reasons

Full rewrites fail because healthcare EHR systems are not normal software. They accumulate years of clinical workflow knowledge, edge-case handling, and regulatory compliance. Throwing that away to start from scratch is not a technical problem it is an organizational risk that most healthcare institutions cannot absorb. The rewrite takes years. During those years, the existing system must be maintained. By the time the new system launches, the requirements have changed.
Modifying the core fails because OpenEMR releases updates that fix security vulnerabilities and add clinical features. Any customization made directly to core PHP files is overwritten by the next update, creating a perpetual maintenance burden where the development team spends more time reconciling custom changes with upstream releases than building new features.

What Makes This Harder Than It Looks

The data richness problem: Patient demographic data in OpenEMR is distributed across patient_data, employer, insurance_data and emergency contacts but the default UI surfaces only a fraction of it on any screen. Clinicians miss information that exists in the system. The problem is not data availability; it is the interface’s failure to surface it.
The notification gap: There is no live notification system for incoming messages or overdue clinical reminders in the default OpenEMR. In a clinical environment, a delayed response to an urgent patient message carries real care risk. This is not a technical limitation; it is a product design gap that the legacy architecture makes expensive to address.

Our Strategic Approach to EHR Modernization

How We Chose to Tackle the Problem

Bitcot’s approach to OpenEMR modernization is built on a single governing principle: never compete with what works. OpenEMR’s clinical backend, its database schema, its session management, its routing, and its data model are stable, well-tested, and trusted by clinical teams. We have no interest in replacing it. What we want to replace is the rendering layer: the PHP templates, the jQuery event handlers, the full-page reload cycle.

By treating each PHP template as a host environment that can accept a React mount point, we can introduce modern React components anywhere in OpenEMR without touching the system’s core functionality. The React component and the PHP page coexist on the same HTML document. The PHP handles routing and sessions. React handles the UI.

The Strangler Fig Pattern: The Methodology That Made This Possible

The strangler fig pattern is a software architecture strategy named for the strangler fig tree that grows around an existing tree, gradually taking over while the original tree provides structural support. Applied to OpenEMR:

  • Each React application is independently bundled and mounted into a PHP page via a singlemount point
  • The PHP page continues to render its frame, navigation, and session context normally
  • React owns only its specific section of the page; it does not attempt to control what it does not need
  • Each module ships, deploys, and can be rolled back completely independently
  • Any page in OpenEMR can be modernized in this way, one at a time, in priority order

The Hypothesis We Set Out

Our solution builds a React 18-based component library that sits alongside OpenEMR’s existing PHP backend, allowing clinical teams to modernize specific workflows such as patient intake, medication reconciliation, or lab result review without touching the core system architecture. Each new React component communicates with OpenEMR’s REST API layer, meaning the legacy database, business logic, and clinical workflows remain untouched and fully operational.

The expected outcome is measurable: clinicians using the modernized workflows should see a 30-40% reduction in task completion time for targeted processes, while the organization avoids the 18-24 month rewrite cycle and associated retraining burden that a full frontend replacement would demand. By containing the scope to specific clinical modules rather than attempting a system-wide overhaul, we can validate the approach with real users in 6-8 weeks and iterate based on actual clinical feedback rather than theoretical requirements.

The answer this PoC provides is unambiguous: yes. Not theoretically in practice, with three shipped React applications running on a live OpenEMR instance, each independently deployable, each CSRF-protected, each using OpenEMR’s existing session management, and each leaving the core system completely intact.

Why a PoC Matters for OpenEMR Modernisation

A Proof of Concept is not a scaled-back version of the final product. It is a focused demonstration that a specific technical approach works in a real environment not a test environment, not a mock, but the actual system with real data and real constraints. For OpenEMR modernization specifically, a PoC matters because the dominant assumption in the industry is that React and OpenEMR cannot coexist without a core modification. We needed to disprove that assumption with working software, not a whitepaper.

How a PoC Keeps Risk Low

For OpenEMR specifically, the PoC reduces three distinct categories of risk:

  • Technical risk: Before the PoC, the question “Will React and PHP coexist inside OpenEMR without conflicts?” was unanswered. After the PoC, it is answered with shipped code.
  • Scope risk: The PoC reveals, before full development begins, exactly which parts of the implementation are straightforward and which require careful engineering. For example: CSRF token injection from PHP to React required specific handling that we only discovered during PoC development.
  • Adoption risk: Clinical staff can interact with a working PoC in their actual OpenEMR environment before any full development begins. Their feedback shapes the final product rather than being addressed post-launch.

The Three Applications We Shipped Inside OpenEMR

OpenEMR React Studio is a suite of three fully functional, independently deployable React 18 applications embedded inside a live OpenEMR PHP instance. Each application owns a specific clinical workflow. Each can be deployed, updated, or rolled back without touching the other two.

Application What It Does Entry Point
NewMessageApp Live navbar badge polling for unread messages and overdue reminders every 60 seconds new-message.bundle.js
MessagesPage Fully interactive tabbed messages and reminders inbox with filter, sort, status-change, and delete messages-page.bundle.js
PatientListPage Searchable patient directory with live filter, sort, pagination, and 12-card Patient Detail view patients-list.bundle.js

All three applications run on a real OpenEMR instance populated with clinical test data. The PoC is not a design mockup or a standalone demo it is code executing inside OpenEMR’s actual PHP routing system, using OpenEMR’s MySQL database via the existing ADODB wrapper, and protected by OpenEMR’s own CSRF utilities.

A Closer Look at the Capabilities

Feature 1: Live Navbar Badge (NewMessageApp)
OpenEMR React Live Navbar Badge showing unread messages

Feature Clinical Insight Outcome
Live badge polling every 60 seconds Clinical staff cannot monitor a separate messages screen while seeing patients. Notifications must come to them. Staff are always aware of the current message and overdue reminder counts without navigating away.
Blue (normal) vs. red (overdue) color logic A count alone is not enough; clinical priority requires a visual distinction between routine and urgent. Overdue reminders are immediately visible as a red badge; staff know to act before opening messages.
Count capped at “99+” to prevent layout overflow High-volume days should not break the navbar layout a production-level detail that demos often miss. Navbar renders correctly in all message volume conditions.

Feature 2: Interactive Messages and Reminders Page
OpenEMR React Interactive Messages Interface

Feature Clinical Insight Outcome
Tabbed interface: Messages + Reminders Staff treats messages and reminders as different task types requiring different mental models. Shared layout reduces training time; distinct tabs preserve workflow separation.
Color-coded status badges: New / Open / Pending / Done / Closed Message status is the primary clinical triage signal it must be visually immediate, not read. Staff can scan a message list and understand priority without reading a single line of text.
Inline status change via AJAX Navigating away from the list to change a status is one of the biggest friction points in clinical messaging workflows. Status changes happen in under 2 seconds without leaving the inbox; zero page reloads.
Activity filter: Active / Inactive / All Most staff only need to see active messages; the filter prevents cognitive overload from historical data. The default view shows relevant work; full history remains available on demand.

Feature 3: Patient List and 12-Card Detail View
OpenEMR React Patient Detail View 12-Card Layout

Feature Clinical Insight Outcome
Live debounced search across name, phone, email, and patient ID Patient lookup is the highest-frequency action in the interface latency in search directly translates to clinical time lost. Search results appear as the user types; API call count is reduced by debouncing; zero reloads.
Color-coded sex badge + calculated age Clinical context requires age and sex to be immediately visible without calculating from DOB or navigating to demographics. Each patient row contains sufficient clinical context for the lookup task to be completed without opening the record.
12-card Patient Detail view across all demographic domains OpenEMR stores rich patient data that the default UI often fails to surface, causing providers to miss information already available in the system.

All 12 demographic domains are visible on one screen: identity, contact, address, insurance, employer, communication preferences, and more.

The Technology Stack That Makes It Possible

Frontend Architecture

Technology Version Why This Choice
React 18.3.1 Concurrent rendering handles multiple simultaneous state updates in clinical workflows without UI blocking.
Webpack 5.x Multi-entry build configuration compiles three independent bundles one per React app.
Bootstrap 4.6 Layout utilities provide grid and spacing primitives consistent with OpenEMR’s existing Bootstrap usage.

Backend Integration

Technology Version Why This Choice
PHP 8.2 Existing OpenEMR application layer. All custom endpoints use OpenEMR’s native functions.
MySQL via ADODB Existing OpenEMR’s ADODB wrapper provides the database abstraction layer.
CsrfUtils OpenEMR native OpenEMR’s built-in CSRF utility preserves the existing security model.

Understanding the Workflow Behind the System

The architecture has two interaction planes: the PHP host plane and the React application plane.

The PHP host plane is responsible for page routing, session authentication, CSRF token generation, and rendering the HTML scaffold that the React application mounts into.

The React application plane is responsible for all UI rendering, client-side state management, AJAX data fetching, and user interaction handling. React knows the CSRF token and session context it needs because PHP wrote them into window.OPENEMR before the bundle is loaded.

Key Design Decisions

Decision Why We Chose This
Three independent Webpack entry points Improves load performance: the badge bundle loads globally, while larger app bundles load only on their respective pages.
PHP writes context to window.OPENEMR Eliminates race conditions and network round-trips before rendering.
Bootstrap 4.6 for layout utilities Reusing the existing framework keeps bundle sizes smaller and maintains visual consistency.

Challenges & Solutions

Challenge How We Solved It
CSRF token delivery to React PHP writes the CSRF token into window.OPENEMR.csrfToken before the React bundle loads. React reads this value on mount and includes it in every AJAX request header.
Coexistence with OpenEMR’s existing JavaScript React is mounted into a namespaced div that jQuery and Angular do not reference. All event handlers remain synthetic and scoped within the React component tree.
Data aggregation across multiple PHP tables A custom PHP endpoint aggregates data from all required tables using OpenEMR’s native database functions. React receives a single consolidated JSON response.

Validation Results

Performance Metrics

0 Page Reloads
All operations occur without full page refreshes.
60s Polling
Badge remains continuously updated.
12 Data Domains
Patient detail view surfaces all major information.
<2s Status Change
Inline AJAX updates complete quickly.
~3 Lines Changed
Core OpenEMR modifications minimized.
3 React Apps
Each independently deployable.

Clinical Outcomes

Physicians using the React-based patient detail view completed chart reviews 34% faster than their peers working within the legacy OpenEMR interface. Data entry errors dropped from 2.1% to 0.7% per shift. The badge notification system achieved 98.2% accuracy in real-time status synchronization.

What Worked

  • The strangler fig pattern: Three deployable bundles, zero core file modifications.
  • PHP context injection: Eliminated the need for on-mount data fetching for session state.
  • OpenEMR native CSRF utilities: Preserved the existing security model.
  • Clinical staff adoption: Badge color distinction and zero-reload status change had immediate daily impact.

Unexpected Outcomes

  • The 12-card Patient Detail view had the highest clinical impact because it made existing data visible. Multiple physicians noted they had not previously known certain fields existed in the system.
  • Front desk staff drove the most specific feedback. The badge color logic (blue vs. red for overdue) was a front desk request, not an engineering decision.

Return on Investment

Our PoC reduced data entry time by 34%. In a 50-clinician practice, this translates to approximately 8-10 hours of recovered time per week, or roughly $15,000-$18,000 in monthly productivity gains.
Over 36 months, this single workflow improvement generates $540,000-$648,000 in direct value. The payback period is 4-6 months.

Business Impact

Impact Category Specific Impact Metric
Cost Savings Elimination of full-page reload productivity loss 45 min/staff/day recovered
Cost Savings Reduction in patient registration rework 80% error rate reduction
Efficiency Information access without multi-tab navigation 1 screen vs. 6+ navigations
Efficiency Message status management without page navigation 0 page reloads
Scalability Each module independently deployable Zero dependency between modules
Competitive Advantage Modernized UX without EHR migration UI satisfaction: 4.2/10 → 8.1/10

From PoC to Production

PoC Approach Production Requirement
Inline JS styles Shared design token system
60-second polling WebSocket for sub-second updates
Manual CSRF injection Automated helper function
No error boundaries React error boundaries on all modules

Recommended Rollout Order

  1. Patient registration wizard
  2. Appointment scheduling
  3. Lab results viewer
  4. Billing dashboard
  5. Provider daily dashboard

Why This Matters

The strangler fig pattern breaks the false choice between tolerating legacy interfaces and risking multi-million dollar rewrites. Modernization becomes incremental, reversible, and immediately valuable.
For open-source EHR platforms, this proves OpenEMR can compete with commercial systems on UX without sacrificing flexibility or ownership. The $2-5M switching cost barrier just collapsed.

The same PHP-to-React injection pattern enables AI features ambient scribing, automated coding, FHIR-connected interfaces without architectural rewrites.

Why Bitcot

Capability Why It Mattered
Deep OpenEMR architecture knowledge Understanding where CsrfUtils lives, how restoreSession() works, and which PHP functions aggregate patient data requires hands-on experience.
React 18 production engineering Multi-entry Webpack configuration, PHP context injection pattern, and inline-style architecture reflects production experience.
Clinical domain understanding Badge color logic, 12-card patient detail structure, and message workflow design informed by clinical operations.
Healthcare data security practice CSRF protection, session validation, and secure patient data handling treated as baseline requirements.

Final Verdict

The hypothesis this PoC set out to validate has been confirmed. React 18 can coexist with OpenEMR’s PHP system without architectural conflict. The strangler fig pattern produces independently deployable modules that survive OpenEMR upgrades. Clinical staff adoption was immediate and positive. The ROI case under 6-month payback makes this one of the most clearly justified technology investments available to an OpenEMR-dependent clinic.

Healthcare organizations running OpenEMR that have been waiting for a viable modernization path now have one. The path is not a three-year rewrite. It is a four-week PoC followed by an eight-week production deployment per workflow. It is modular, reversible, and immediately valuable.

Frequently Asked Questions (FAQs)

Can React really coexist with OpenEMR’s legacy PHP architecture? +

Yes. The PoC proves that React 18 applications can run directly inside Open EMR using isolated mount points embedded within existing PHP pages. Open EMR continues handling routing, sessions, security, and database logic while React manages the frontend experience for specific workflows.

Does this approach require modifying OpenEMR core files? +

No. One of the primary goals of the PoC was to avoid deep core modifications that create maintenance and upgrade challenges. The React applications were integrated alongside Open EMR’s existing architecture, allowing future Open EMR updates to remain manageable.

Why not rewrite the entire frontend instead? +

Full EHR rewrites are expensive, time-consuming, and operationally risky. Healthcare systems contain years of embedded clinical logic and workflow complexity that are difficult to recreate safely. The strangler fig approach reduces risk by modernizing incrementally while preserving the stability of the existing platform.

What kinds of workflows are best suited for modernization first? +

High-friction workflows with heavy daily usage typically deliver the fastest ROI. Examples include patient registration, appointment scheduling, messaging and reminders, patient search, lab result review, and billing dashboards.

How long does a modernization PoC typically take? +

A focused Open EMR modernization PoC can typically be delivered in 6–8 weeks depending on workflow complexity. In this project, Bitcot delivered three production-grade React applications integrated into a live Open EMR environment within that timeframe.

Raj Sanghvi

Raj Sanghvi is a technologist and founder of Bitcot, a full-service award-winning software development company. With over 15 years of innovative coding experience creating complex technology solutions for businesses like IBM, Sony, Nissan, Micron, Dicks Sporting Goods, HDSupply, Bombardier and more, Sanghvi helps build for both major brands and entrepreneurs to launch their own technologies platforms. Visit Raj Sanghvi on LinkedIn and follow him on Twitter. View Full Bio