Last updated: 2026-01-09
Pain Tracker is a local-first, privacy-first PWA for tracking chronic pain and exporting claim-ready reports (with a focus on WorkSafeBC forms).
Data is stored locally by default; sharing happens via user-controlled exports. Core tracking does not require a backend. Optional integrations/features may make network requests when enabled/configured.
The architecture is designed so health data stays local by default and is only shared via explicit, user-controlled actions (e.g., exports):
Key Principles:
- Local-First (Default): Data is stored locally (primarily in the browser's IndexedDB)
- Client-Side Protection: Encryption and security controls are implemented on-device
- User-Controlled: Only YOU decide when to export data for clinical or claims purposes
- No Third-Party Telemetry by Default: No third-party analytics are enabled by default
View detailed comparison with traditional health apps →
- Client: React 18 + TypeScript
- State Management: Zustand (+ Immer)
- Storage: IndexedDB (via Dexie or custom wrapper)
- Packaging: Vite + PWA plugin
- Security: AES-GCM encryption with PBKDF2-derived keys using the Web Crypto API
- Platform: Installable PWA (desktop and mobile)
+------------------------------+
| React UI (Forms, Reports) |
+--------------+---------------+
|
v
+------------------------------+
| Zustand Store (painStore) |
+--------------+---------------+
|
v
+------------------------------+
| IndexedDB (encrypted entries)|
+------------------------------+
export interface PainEntry {
id: string; // UUID
timestamp: Date; // ISO 8601
painLevel: number; // 0–10
location: string[]; // body regions
quality: string[]; // "sharp", "burning", etc.
activities: string[];
medications: string[];
triggers: string[];
emotionalState?: EmotionalMetrics;
notes?: string;
version: number; // schema version
encrypted: boolean;
}export interface EmotionalMetrics {
sentiment: 'positive' | 'neutral' | 'negative' | 'crisis';
keywords: string[];
crisisIndicators: string[];
}Note: The interface supports future ML-based scoring; current implementation uses rule-based heuristics.
The Empathy Intelligence Engine provides context-aware feedback without sending data to the cloud.
- Purpose: Detect crisis patterns, validate user pain, and suggest local interventions.
- Mechanism:
- Local Heuristics: Analyzes recent entry velocity, severity spikes, and emotional keywords.
- Privacy: Differential privacy noise can be applied to aggregated metrics when enabled.
- Crisis Detection: Identifies patterns matching clinical definitions of "flare-up" or "crisis" and triggers local UI adaptions (e.g., simplifying the interface).
interface PainStore {
entries: PainEntry[];
filters: FilterState;
addEntry(entry: PainEntry): void;
updateEntry(id: string, changes: Partial<PainEntry>): void;
deleteEntry(id: string): void;
getFilteredEntries(): PainEntry[];
getAnalytics(): AnalyticsData;
getWCBReport(range: DateRange): WCBReport;
}Implemented using Zustand with Immer:
- Immutable updates.
- Easy testability.
- Simple, flat store — no Redux boilerplate.
Object stores:
painEntries: id, timestamp, painLevel, location*settings: key
All sensitive data is stored encrypted (see below).
Batch operations are used where possible (e.g. bulk add/import).
Single-user app on personal devices.
No server → no remote compromise of a central database.
Main risks:
- Device theft.
- Shoulder-surfing / casual access.
- Browser storage inspection.
- Algorithm: AES-GCM (256-bit).
- Key derivation: PBKDF2-HMAC-SHA256 with configurable iterations.
- Keys derived from user passphrase, never stored in plaintext.
High-level flow:
- User provides passphrase.
- Key is derived via PBKDF2 (with per-user salt).
- Pain entries are serialized and encrypted.
- Ciphertext + IV + salt are stored in IndexedDB.
default-src 'self'frame-ancestors 'none'(no embedding)object-src 'none'- Images/fonts/scripts restricted to self (and minimal required exceptions for dev).
- Service worker pre-caches the app shell.
- Pain entries are stored in IndexedDB and remain available offline.
- The app can be installed to home screen on supported devices.
- Updates:
- New versions are detected and the user is prompted to reload.
Pain Tracker generates a structured summary suitable for manual transcription into WorkSafeBC forms (6/7/8) and a PDF export with:
- Time-bounded pain log.
- Trend summary (average/peak over the selected period).
- Activity limitations snapshot.
- Free-text narrative of pain progression.
Note: Direct, official form replication may require legal review; current implementation focuses on helpful summaries aligned to WorkSafeBC requirements.
- Unit tests: Core utilities (encryption, validation, analytics).
- Integration tests: Store + IndexedDB persistence.
- E2E tests: Critical flows:
- Create/edit/delete pain entry.
- Refresh and verify persistence.
- Generate export.
Testing tools: Vitest + Playwright.
- Emotional metrics with more nuanced scoring.
- Advanced analytics (trigger correlations, flare prediction).
- Optional clinician reports.
- Optional sync / backup mechanisms (user-controlled, privacy-preserving).
This document is a living overview. See the roadmap in README.md or GitHub Issues for current priorities.