Mock Data Service
Development only mock API data for device and integration flows.
Mock Data Service
GlycemicGPT supports many possible device and data connections, including CGMs, pumps, Nightscout variants, cloud sync providers, and live glucose streams. Most developers do not have access to every real device, account, credential, or historical dataset needed to test these flows properly.
Without a reliable mock layer, device specific UI and data handling are hard to develop, hard to review, and easy to regress. The mock data service gives developers a development focused way to simulate supported connections so they can work with realistic device data even when they do not personally own or have access to those devices.
This mock layer must never ingest fake data into production systems. It is a browser side development tool that uses the existing web API contracts and returns fake responses before requests leave the browser.
Enabling Mock Mode
Mock mode is opt in. The first browser request must include this request header:
x-glycemicgpt-mock-api: 1Use a browser header extension such as ModHeader:
- Create a request header named
x-glycemicgpt-mock-api. - Set its value to
1. - Scope it to the local web app, for example
http://localhost:3003/*. - Open or reload
/dashboard.
The middleware treats this header as a development only mock runtime signal. In development, it allows dashboard access without a real session and forwards the same header into the App Router request context. The root layout reads that header, starts the MSW worker, and mounts the mock control panel.
If the header is missing, mock mode does not start. The app follows the normal auth and backend API paths.
Benefits
- Developers can test CGM, pump, Nightscout, Glooko, Tandem, Medtronic, and live stream surfaces without real credentials.
- UI review becomes repeatable because reviewers can select the same simulated device and glucose scenario.
- Error prone integration pages can be developed while the real backend, cloud account, or physical device is unavailable.
- Regression testing is easier because mocked responses use the same
/api/*shapes that production screens already consume. - Fake device data stays out of production databases because the mock layer responds inside the browser.
How It Works
The web app uses Mock Service Worker in development. MSW registers a service worker in the browser and intercepts network requests that match configured handlers. The app still calls the same URLs it normally calls, such as /api/integrations/glucose/history or /api/integrations/pump/status. When mock mode is active, MSW catches those requests and returns generated JSON instead of allowing the browser to send the request to the real backend.
The implementation lives in apps/web/src/mocks:
browser.tsstarts the MSW browser worker.handlers.tsmaps API routes to mock responses.data.tsgenerates realistic glucose, pump, alert, brief, insight, and integration payloads.state.tsstores the selected mock scenario inlocalStorage.DevMockPanel.tsxexposes development controls for selecting device sources and glucose events.
The mock service fails closed for API routes. If the browser requests an /api/* endpoint without a mock handler, the catch all handler returns 501 with a clear missing handler message. That prevents silent success when a new API route has not been modeled yet.
Development Only Boundary
The mock runtime is guarded by NODE_ENV === "development". Production builds do not start MSW, and the production Docker image removes public/mockServiceWorker.js from the runtime image.
The mock service does not write to the real backend. It stores temporary mock state in browser localStorage, for example the selected CGM source, pump source, backfill duration, live stream mode, and selected glucose event.
Basic Flow
When mock mode is active:
- The dashboard asks the normal API client for glucose history.
- The browser sends a request to
/api/integrations/glucose/history?minutes=1440&limit=288. - MSW matches that route in
handlers.ts. - The handler reads the current mock runtime state from
localStorage. data.tsgenerates a CGM history response using the selected scenario.- The dashboard receives a normal
GlucoseHistoryResponseand renders as if it came from the real API.
The dashboard does not need special mock specific code. It only sees the same API contract it already uses.
Example Glucose Reading Mock
The glucose generator creates readings at a five minute cadence. It starts from a repeatable daily glucose pattern, adds source specific sensor bias, then optionally blends the most recent hour toward a selected event target.
For example, an urgent low scenario targets the latest readings toward 48 mg/dL:
type MockGlucoseEvent = "baseline" | "low" | "urgent-low" | "high" | "urgent-high";
function glucoseEventTarget(event: MockGlucoseEvent): number | null {
const targets: Record<MockGlucoseEvent, number | null> = {
baseline: null,
low: 62,
"urgent-low": 48,
high: 215,
"urgent-high": 285,
};
return targets[event];
}
function mockGlucoseValueAtMinutesAgo(
minutesAgo: number,
baselineValue: number,
event: MockGlucoseEvent
): number {
const target = glucoseEventTarget(event);
if (target === null || minutesAgo > 60) {
return baselineValue;
}
const blend = 1 - minutesAgo / 60;
return Math.round(baselineValue * (1 - blend) + target * blend);
}That means old history remains a realistic generated day, while the latest readings can simulate a low, urgent low, high, or urgent high. The alert and live stream mocks then derive their payloads from the same generated readings.
What MSW Gives Us
MSW is useful here because it intercepts requests at the network boundary instead of forcing every component to import mock data directly. This keeps application code honest:
- Components still use the real API client.
- Request URLs, methods, query parameters, and response shapes stay visible.
- Missing API coverage is obvious through the
501guard. - Developers can switch scenarios without changing component code.
This is intentionally different from seeding fake records in a backend database. The mock service is for local development and UI review. It should not become a production data ingestion path.