The Stack
InteropNimbus is built with a modern React stack optimized for developer experience and maintainability:
- React 19 + TypeScript — latest React with strict TypeScript for type safety
- Vite 7 — fast builds and HMR during development
- Tailwind CSS v4 — utility-first styling with the new v4 engine
- Zustand — lightweight state management for auth and UI state
- TanStack React Query — server state management with caching, refetching, and background updates
- React Router v7 — client-side routing with lazy-loaded routes
- keycloak-js v26 — official Keycloak JavaScript adapter for SSO
Why This Combination?
React 19 + TypeScript
React 19 brings improvements to Suspense, transitions, and server components. For InteropNimbus, the key benefit is better concurrent rendering for real-time data updates — channel status changes don't block the UI while fetching.
TypeScript is non-negotiable for a healthcare application. The domain has complex types (HL7 segments, FHIR resources, Mirth channel configs), and type safety catches errors at compile time rather than in production.
Zustand Over Redux
Zustand is a fraction of Redux's complexity. InteropNimbus has two stores — auth state and UI preferences. Zustand handles both in under 50 lines of code. No boilerplate, no action creators, no reducers.
TanStack Query for Server State
This is the key architectural decision. All Mirth and FHIR data lives on the server, and TanStack Query handles:
- Automatic caching — don't re-fetch channel status if it was fetched 10 seconds ago
- Background refetching — keep data fresh without user intervention
- Optimistic updates — UI feels instant even on slow connections
- Error/retry handling — built-in retry logic for flaky network connections
Feature-Sliced Design (FSD)
InteropNimbus uses Feature-Sliced Design, an architectural methodology that organizes code by business domain rather than technical concern.
Folder Structure
src/
app/ # App shell: providers, router
domain/<feature>/ # Types, DTOs, mappers (pure logic, no React)
mocks/<feature>/ # Fixture data + mock API per feature
shared/
api/<feature>/ # API service per feature
hooks/<feature>/# React Query hooks per feature
store/<concern>/# Zustand stores
ui/ # Reusable presentational components
config/ # App-wide config (auth, API URLs)
styles/ # Global CSS
entities/<entity>/# Domain-bound reusable components
features/<feature>/# Feature pages + feature-specific components
Why FSD?
The traditional React approach of organizing by file type (/components, /hooks, /utils) breaks down as applications grow. FSD keeps related code together:
- Channel monitoring — types, API calls, hooks, and components all live under the channels feature
- FHIR browsing — same pattern for FHIR resource types, queries, and views
- Auth — Keycloak config, auth store, and auth provider are co-located
Import Rules
Three strict rules keep the architecture clean:
- Always use
@/alias — never relative../imports - Always import from barrel files (
index.ts) - Dependency direction flows inward: features → entities → shared → domain