A modern CGM (Continuous Glucose Monitor) dashboard built with React, TypeScript, and Recharts.
Compact Mobile-First CGM Dashboard
The dashboard is now fully functional and deployed to production on Vercel with all core features implemented. Key improvements include intelligent polling, flicker-free charts, and a mobile-optimized design.
Goal: Rock-solid React + TypeScript + Material-UI foundation
- β Clean React 18+ TypeScript project
- β Material-UI 6+ for components and theming
- β Complete type system (CGM, Chart, Common types)
- β Robust API service layer with retry logic
- β Environment configuration (.env setup)
Goal: Reliable data fetching and state management
- β Custom React hooks for CGM data fetching
- β Intelligent polling - calculates next reading time based on actual data patterns
- β Real-time data updates with optimized intervals
- β Error handling and loading states
- β Data transformation utilities
- β Mock data for development
Goal: Clean, responsive Material-UI components
- β Time range selector (1h, 3h, 6h, 12h, 24h)
- β Current glucose reading display
- β Live mode toggle with countdown timer
- β Mobile-responsive design
- β Alert/notification system
Goal: Stable, flicker-free glucose visualization
CRITICAL LESSONS LEARNED:
β οΈ Recharts axis flickering: Known issue with time-series + live updates- β Solution approaches: Memoization, static sizing, disabled animations
- β Alternative libraries: Chart.js, Victory, D3.js direct
- β Key principle: Minimize re-renders of chart components
Implementation Strategy:
- Start with simplest possible chart (static data, no animations)
- Add aggressive memoization from day 1
- Test with static data first, then live data
- If Recharts fails: Chart.js fallback ready
Goal: Complete dashboard with all features
- β Compact mobile-first design - reduced from 3 cards to 2 cards
- β Responsive layout (mobile + desktop optimized)
- β Real-time glucose monitoring with intelligent polling
- β Color-coded glucose values (red/yellow/green based on thresholds)
- β Current time display with AM/PM format
- β Chart + current reading integration
- β Smart trend arrows using actual API direction data
- β Loading and error states with proper error handling
Goal: Stable production environment
- β Vercel deployment with environment variables configured
- β API authentication working correctly with bearer tokens
- β Chart rendering fixes for production builds (ReferenceArea issues)
- β Performance optimizations and code cleanup
- β TypeScript error resolution for production builds
- React 18+ with TypeScript
- Material-UI 6+ for UI components
- date-fns for time utilities
- Axios for API communication
- Recharts 2+ - React-native charting
- Fallback: Chart.js + react-chartjs-2 (if Recharts fails)
- TypeScript 5+ for type safety
- ESLint + Prettier for code quality
- React Dev Tools for debugging
Create .env file with:
REACT_APP_API_BASE_URL=https://loopy-api-production.up.railway.app
REACT_APP_API_KEY=your_bearer_token_hereNote: Use REACT_APP_API_KEY (not REACT_APP_API_TOKEN) to match Vercel environment variables.
- Base URL: https://loopy-api-production.up.railway.app
- Health Check:
/api/health - Current Reading:
/api/cgm/current - CGM Status:
/api/cgm/status - Historical Data:
/api/cgm/data?hours=24 - CGM Analysis:
/api/cgm/analysis/{period}(period: 24h, week, month)
Current Reading (/api/cgm/current):
{
"current_glucose": 142,
"direction": "Flat",
"trend": 4,
"timestamp": "2025-01-16T10:30:00.000Z",
"minutes_ago": 3.2,
"device": "share2",
"type": "sgv"
}Historical Data (/api/cgm/data?hours=24):
Returns data points and analysis for the specified time period.
The dashboard analyzes historical CGM readings to predict when new data will arrive:
- Pattern Analysis: Calculates median interval between actual readings (typically ~5 minutes)
- Next Reading Prediction: Estimates when the next reading should arrive based on the latest timestamp
- Smart Scheduling: Sets timers to check for new data just after the expected time (+30s buffer)
- Adaptive Updates: Recalculates intervals when new data patterns are detected
- Reduces API calls: Only checks when new data is expected, not on fixed intervals
- Faster updates: Gets new data within 30 seconds of availability instead of waiting up to 5 minutes
- Pattern-aware: Adapts to your specific CGM device's timing patterns
- Battery efficient: Minimizes unnecessary network requests
- Next Check: Countdown to next expected reading
- Expected Time: Calculated next reading time based on patterns
- Interval: Detected average time between readings
- Status: Shows when last update occurred
API β Custom Hooks β Components β UI
Dashboard
βββ CurrentReading (glucose value + trend)
βββ TimeRangeSelector (1h-24h + live mode)
βββ CGMChart (memoized, flicker-resistant)
- Must be flicker-free (top priority)
- Time-series glucose data visualization
- Target range overlay (70-180 mg/dL)
- Responsive design
- Real-time updates without re-animation
- Memoize ALL functions passed to chart components
- Memoize data transformations with useMemo
- Disable animations for live-updating charts
- Use stable keys for chart components
- Test with live timers early in development
- ReferenceArea rendering: Add
key={timeRange}to LineChart to force re-render - TypeScript errors: Ensure consistent interface usage across files
- Environment variables: Use consistent naming (
REACT_APP_API_KEY) - API authentication: Bearer token format must match API expectations
- Glucose thresholds: Configurable in
GLUCOSE_THRESHOLDSconstant- Red: < 55 mg/dL (urgent low) or > 250 mg/dL (really high)
- Yellow: 55-69 mg/dL (low) or 181-250 mg/dL (high)
- Green: 70-180 mg/dL (normal range)
- Chart dots: Color-coded based on glucose value
- Active dots: Preserve original color but enlarge on hover/selection
- React.memo for expensive components
- useCallback for event handlers passed to charts
- Intelligent polling - schedules updates based on actual CGM reading patterns
- Separate timer logic from chart rendering
- Batch state updates when possible
- Touch-friendly controls (44px minimum)
- Responsive breakpoints for different screen sizes
- Simplified layouts on small screens
- Readable font sizes (minimum 14px)
- Start with mock data (no API calls)
- Add static API data (single fetch)
- Enable live updates (timer-based)
- Test chart stability under load
- Mobile responsiveness testing
- Static data renders without flicker
- Live data updates smoothly
- Time range changes work correctly
- Target range displays properly
- Mobile layout is usable
npm start # Development server (http://localhost:3000)
npm build # Production build
npm test # Run tests
npm run lint # Code quality check- β Displays current glucose reading with color coding
- β Shows glucose history chart (flicker-free!)
- β Time range selection works (1h, 3h, 6h, 12h, 24h)
- β Mobile responsive with compact design
- β Connects to live API with authentication
- β Intelligent polling - updates based on actual CGM timing patterns
- β Color-coded glucose alerts (red/yellow/green visual indicators)
- β Target range visualization with green underlay (70-180 mg/dL)
- β Smart trend arrows using API direction data
- β Professional mobile-first styling with Material-UI
- β Real-time countdown showing time until next reading
- β Current time display with AM/PM format
-
Environment Variables Required:
REACT_APP_API_BASE_URL=https://loopy-api-production.up.railway.appREACT_APP_API_KEY=your_bearer_token_here
-
Build Settings:
- Framework Preset: Create React App
- Build Command:
npm run build - Output Directory:
build
- Glucose thresholds:
src/components/CurrentReading.tsx(lines 37-43) - Chart colors:
src/components/SimpleCGMChart.tsx(ColoredDot component) - API configuration:
src/services/api.tsandsrc/services/api/base.ts - Polling logic:
src/hooks/useSmartPolling.ts
π Production-ready CGM dashboard with intelligent polling and mobile-first design! π