Skip to main content

FluidCalc — Clinical Fluid & IV Calculator

iOS app for nurses and clinicians to track fluid balance and perform bedside calculations in real time.

More screenshots

Progress75%
View on GitHub

Overview

FluidCalc is a production iOS app built for critical care and ward nurses who need fast, accurate fluid tracking and clinical calculations at the bedside. It replaces paper tally charts and mental arithmetic with a structured, safety-aware tool that works fully offline.

The app ships on the Apple App Store via TestFlight CI, is installable as a PWA on any device, and is built to clinical safety standards — including weight-relative balance thresholds, anuria alerts, and ARDS grading.


Features

Fluid Balance Tracking

  • Log intake (IV fluids, oral, blood products, TPN) and output (urine, drainage, blood loss, NG aspirate) with timestamps
  • Real-time net balance with colour-coded status: normal / caution / critical
  • Weight-relative thresholds (3 ml/kg, 8 ml/kg) when patient weight is known; flat thresholds (200 ml, 500 ml) as fallback
  • Anuria detection with clinical alert when urine output falls below threshold
  • Up to 4 simultaneous patient slots with instant switching
  • 10-step undo stack per patient
  • Shift PDF export with handoff notes and page numbers
  • CSV export for documentation
  • Virtual list rendering for shifts with 50+ entries (no jank)

19 Clinical Calculators

Grouped by specialty:

CategoryCalculators
Fluid / RenalIV Drip Rate, Urine Output, Maintenance Fluid, Free Water Deficit, Corrected Sodium, FENa, Creatinine Clearance (CG), Osmolality
CardiacMAP, QTc (Bazett)
RespiratoryABG Interpreter (full acid-base disorder classification, compensation adequacy, P/F ratio, ARDS grading)
NutritionHarris-Benedict REE, BSA (DuBois)
PaediatricPaediatric Weight (age-based), Paediatric Dehydration
Burns / TraumaParkland Formula
PharmacologyDrug Dose (weight-based), Medication Infusion Rate, Intraoperative Fluid Planner, Anion Gap

Clinical Safety

  • Division-by-zero guards on all calculations
  • Critical value alerts with aria-live announcements (pH, QTc, MAP, FENa, anion gap)
  • ABG interpreter classifies primary disorder, compensation, and flags life-threatening derangements
  • DOMPurify sanitisation on all free-text inputs
  • Duplicate entry detection

Technical Stack

LayerTechnology
FrameworkNext.js 16 (App Router, static export)
LanguageTypeScript 5 (strict)
UIReact 19, Tailwind CSS 4
StateZustand 5 with localStorage persistence and versioned migrations
Native wrapperCapacitor 8 (iOS)
PDF exportjsPDF (static import, no lazy loading)
Virtualisation@tanstack/react-virtual (entry lists > 50 items)
TestingVitest, @testing-library/react — 131 tests
CI/CDCodemagic (TestFlight), Vercel (web preview)
i18nCustom context with 8 languages, navigator.language detection, regex-cached plural rules

Design System

Built on a custom Precision Instrument design language — dark-first, clinical, and typographically precise:

  • Fonts: Instrument Serif (headings) · DM Sans (body/UI) · Geist Mono (all clinical numbers)
  • Colours: #0F1117 surface · #4FC3F7 primary · #4CAF82 success · #F5A623 warning · #EF5350 critical
  • All numeric outputs use font-variant-numeric: tabular-nums so values never jump width
  • 8px spacing grid · 48px minimum tap targets throughout · iOS safe-area insets on every header and nav bar
  • Light theme support with full CSS variable theming

Architecture Highlights

  • No backend — the entire app is a static export. All state lives in localStorage, serialised with custom Date hydration to survive JSON round-trips.
  • Versioned store migrations — each breaking state shape change increments a version and runs a migration on hydration, so users never lose data across app updates.
  • i18n without a library — a hand-rolled context reads navigator.language, loads JSON message files dynamically, and caches plural-form regex per locale. Supports EN, DE, FR, ES, HI, RO, PT, AR.
  • Shallow selectors everywhere — Zustand useShallow prevents re-renders on unrelated state changes across the entry list, summary, and patient switcher.
  • Static jsPDF import — eagerly imported at module level to avoid a 300ms+ lazy-load stall when a nurse first hits "Export PDF" mid-shift.

Internationalisation

8 languages: English, German, French, Spanish, Hindi, Romanian, Portuguese, Arabic. Locale is detected from the browser, persisted to localStorage, and applied without a flash on mount. All clinical alerts, error messages, and ARIA labels are translated.


Testing

131 unit and integration tests covering:

  • All 19 clinical calculation functions (including edge cases and zero-guards)
  • Store mutations, serialisation, and migration logic
  • Validation helpers (DOMPurify, duplicate detection, time validation)
  • UI quality assertions (tap target sizes, ARIA roles, toast behaviour)