Simple Miles
A workday has more than two stops.
A native iOS mileage tracker designed around driving sessions, temporary pauses, and local trip history.
- Platform
- Mobile App
- Scope
- Full-stack
- Team
- Solo
- Status
- Complete
- Started
- Jul 12, 2025
Project context
Modern mileage tracking tools were largely designed around simple point-to-point travel, but gig workers rarely operate that way.
Drivers routinely move between multiple stops, pause for deliveries, sit in traffic, make route adjustments, and spend hours working without ever truly ending their driving session. These behaviors often result in fragmented trip records, inaccurate reporting, and unclaimed mileage.
The challenge
- Frequent stops fragment mileage records
- A pause does not always end a trip
The approach
- Movement signals drive a trip lifecycle
- Paused sessions can resume before finalization
From intent to interaction
Start driving
Qualifying movement samples begin the tracking process.
Pause and resume
Short stops stay within the session when driving resumes in time.
Review the record
Inspect routes, categorize trips, and explore locally stored summaries.
What it makes possible
Record driving sessions
Track driving sessions without ending at every brief stop.
Review routes
Inspect routes and categorize trips from local history.
Explore driving patterns
Compare mileage and activity using recorded trip data.
How the pieces fit
Native experience
Review active routes, trip history, and analytics.
SwiftUI and MapKitTracking lifecycle
Turn movement into driving and recording states.
Core Location and state managersLocal persistence
Keep trip records and route geometry on device.
SQLiteTreat pauses as part of the journey
Let a paused session resume before finalizing the trip record.
Keep the core local
Store trips locally, with background tracking subject to device limits.
Engineering notebook
Explore the design, data flow, and implementation in more detail.
Native experience
Review active routes, trip history, and analytics.
SwiftUI and MapKitTracking lifecycle
Turn movement into driving and recording states.
Core Location and state managersLocal persistence
Keep trip records and route geometry on device.
SQLiteSimple Miles was built around a simple observation: drivers should not have to manually reconstruct their workday.
Rather than treating every stop as the end of a trip, the application attempts to understand driving sessions as a whole. By identifying natural trip boundaries and combining related movement segments, the system produces a more accurate representation of how people actually drive.
The goal is to reduce administrative overhead while helping users maintain accurate mileage records for business reporting, reimbursement, and tax purposes.
Implementation
Simple Miles uses a SwiftUI and MVVM-style architecture backed by long-lived view models and singleton managers for location, driving state, travel state, recording, settings, and persistence.
The core tracking pipeline flows through LocationManager, DrivingStateManager, TravelStateManager, and RecordingManager. Location samples are evaluated for distance and speed, translated into driving state, mapped into a travel lifecycle, and then persisted as trip segments through a local SQLite storage layer.
Start driving
Begin tracking when movement meets driving rules.
Pause and resume
Keep short stops within a resumable trip session.
Review the record
Review routes and categorize locally stored trips.
Users begin driving as normal while the application operates in the background. Active trips appear on a live map, allowing users to verify that mileage is being recorded without requiring constant interaction.
As trips are completed, driving activity is automatically organized into cohesive sessions that can be reviewed, categorized, and analyzed. Users can inspect routes, review timestamps, compare personal and business mileage, and explore long-term driving patterns through built-in analytics.
Implementation
A driving session begins when Core Location produces qualifying movement samples. The app rejects small movements that may represent GPS drift and large jumps that may represent unreliable data, then uses speed and distance thresholds to determine whether the user is actively driving.
When movement stops, the trip enters a paused state instead of ending immediately. If movement resumes before the pause countdown expires, the trip continues. If the countdown expires, the app finalizes or discards the trip based on configured distance rules before saving the completed record for review and analytics.
Filter location noise
Reject GPS drift and unreliable location jumps.
Store geometry locally
Store trip metadata and route geometry in SQLite.
Account for lifecycle limits
Respect device limits on background trip tracking.
Simple Miles is built around the idea that movement alone does not define a trip.
Accurately identifying trip boundaries requires understanding user behavior rather than simply tracking location updates. The application combines multiple signals from device hardware, motion data, and driving patterns to distinguish temporary interruptions from genuine trip completion.
This approach allows the system to better represent real-world driving behavior, particularly for users whose work involves frequent stops, deliveries, and route changes throughout the day.
Implementation
The app is local-first and does not depend on a remote backend. Trip metadata and encoded route geometry are stored with direct SQLite3 access, while settings and last-known location use UserDefaults.
MapKit powers live and historical route visualization, while SQL aggregation supports category totals, day-of-week distance, start-hour histograms, weekly comparisons, and driving summaries. Background location modes and significant-location monitoring support continued tracking when the app is not actively foregrounded, with known limits around terminated-state reconstruction.
GPS-based driving detection
Use Core Location speed and distance checks to filter drift and unreliable jumps.
Pause-aware trip lifecycle
Hold temporary stops in a paused state until recording resumes or the timer expires.
Local SQLite persistence
Keep trip metadata and compressed routes in local SQLite without a remote account.
Map-based trip review
Render active and historical routes with MapKit polylines, framing, and annotations.
SQL-backed analytics
Calculate totals, category shares, and weekly comparisons from saved trip records.
Automatic mileage tracking
Records driving activity in the background, reducing the need for manual trip logging and mileage calculations.
Intelligent trip reconstruction
Combines related driving segments into cohesive sessions that better reflect real-world driving behavior.
Live trip visibility
Provides real-time maps and trip status information so users can verify mileage is being captured accurately.
Business and personal categorization
Separates different types of driving activity, making it easier to understand vehicle usage and prepare mileage records.
Driving analytics
Surfaces long-term trends including mileage totals, trip duration, busiest days, and driving habits to help users better understand their activity.
Implementation
GPS-based driving detection
Uses Core Location speed and distance samples to infer active driving, filtering small movements as potential GPS drift and rejecting large jumps as unreliable location data.
Pause-aware trip lifecycle
Maps driving state into idle, traveling, and paused states. Temporary stops start a configurable countdown instead of immediately ending the trip.
Local SQLite persistence
Stores trip metadata and compressed route geometry locally using direct SQLite3 access, supporting offline use without a remote account or backend.
Map-based trip review
Uses MapKit polylines, annotations, camera controls, and route framing to display active and historical trips for inspection.
SQL-backed analytics
Calculates mileage totals, category shares, weekday distance, start-hour activity, and weekly comparisons directly from persisted trip records.
Have a related challenge?
Let’s talk about it.
Bring an idea, a workflow to improve, or a technical question. We can work through what comes next.