3 min read

CarTrack

react tanstack-router tanstack-query zustand dexie tailwindcss vite typescript

Overview 🔗

CarTrack is a local-first web application for tracking vehicle consumption—both electric vehicles (EV battery) and gasoline cars. It logs odometer readings, battery/fuel levels, and charging/refueling events, then calculates consumption rates and predicts range and days until empty.

All data lives in the browser’s IndexedDB. No accounts, no backend, no tracking.

Why I Built This 🔗

I wanted a simple, private way to track my car’s consumption over time without relying on cloud services or car manufacturer apps. Existing solutions don’t support both EV and gasoline vehicles in one place. Building my own gave me full control over the data and the experience.

Key Features 🔗

Dual Vehicle Support 🔗

Track both electric vehicles and gasoline cars in one app. Each vehicle type has tailored consumption metrics—km per % for EVs, km per liter for gasoline. PHEV (plug-in hybrid) is also supported.

Consumption Calculations 🔗

Rolling-window consumption rate with median + outlier detection for accurate, stable readings over time. Later evolved to charge-cycle-based computation—calculating consumption per full charge cycle instead of per reading pair, using median for noise filtering.

Predictions 🔗

Estimated range and days until empty, using a hybrid approach: user-configured daily distance combined with auto-calculated averages from reading history.

Fuel Event Logging 🔗

Log charging sessions or refueling events with cost and amount tracking for cost-per-km trends. Auto-detects event type from vehicle type (EV → charge, Gasoline → refill).

Charts 🔗

Visualize consumption over time, cost per km trends, and charge cost trends with interactive charts.

Data Export & Import 🔗

Full JSON backup or per-vehicle CSV export. Import is idempotent with hash deduplication—no duplicate entries.

Build Notes 🔗

Local-First with Dexie.js 🔗

All data is stored in IndexedDB via Dexie.js. The schema is simple—vehicles, readings, and fuel events—with compound indexes for efficient queries. No server means the app works fully offline and loads instantly. One key learning: use explicit string UUIDs ('id') for Dexie primary keys, not auto-increment ('++id'), to avoid conflicts during import.

Getting Better Over Time 🔗

Consumption accuracy improved significantly—early versions averaged readings naively, now it understands full charge cycles and filters out noise. The app grew from a simple tracker to a proper PWA you can install and use offline, across multiple platforms.