Skip to content
← Back to projects

Needle

An offline GPS speedometer for iPhone. No account, no network, no analytics — the app has no networking code in it at all.

swift react-native expo ios coremotion

A GPS speedometer for iPhone that works entirely on your device. Live speed on a clean dial, trip recording, a 0–60 timer with a personal best, a live g-meter, and a night HUD mode that draws red on black to protect your dark adaptation.

Nothing leaves the phone. There is no account, no analytics, no advertising, and no networking code anywhere in the app. The App Store privacy label reads “Data Not Collected” because that is literally true rather than a claim.

How the speed reading works

GPS is the speed source, not the accelerometer — deliberately. An accelerometer measures change in velocity, so at constant speed it reads zero; you would have to integrate to get speed, and integrated bias error grows without bound, roughly 1–3 mph of drift per minute. iOS’s coords.speed comes primarily from Doppler shift on the GNSS carrier and stays accurate to about ±0.1 m/s even when position accuracy is only ±10 m.

The accelerometer does the two things it is genuinely good at: filling the gaps between once-a-second GPS fixes so the needle moves smoothly, and driving the g-meter. Dead reckoning is hard-clamped to ±3 m/s and abandoned entirely after two seconds without a fix, so integration error can never accumulate past a single GPS cycle.

Working out which way the car is pointing needs no calibration step from the user. Gravity gives “down”, user acceleration is projected onto the horizontal plane, and a decaying covariance accumulator yields the principal axis — which is the direction of travel, because braking and accelerating both act along the car’s long axis. The forward/reverse ambiguity that leaves is resolved by correlating against GPS speed changes.

The practical consequence: the 0–60 timer is good to roughly ±0.2 s. It is not drag-strip accurate, and the app says so.

Built twice, on purpose

Needle exists as both an Expo/React Native app and a native SwiftUI port, sharing every algorithm and constant, in order to measure what the platform choice actually costs. The native build is 27× smaller (1.0 MB against 27 MB), uses about 57 MB less memory, and takes 28% less code to say the same thing — but the most visible difference turned out to be neither: SwiftUI picks up each year’s iOS design language for free, while the React Native build inherits it whenever its navigation library ships support.

Support

Email john.k.fay@gmail.com and you will get a reply from a person.

My speed reads 0 or the dial does not move. Needle needs location access. Check Settings → Needle → Location is set to While Using the App. GPS also needs a view of the sky — speed is often unavailable in a tunnel, a car park, or with the phone under a seat.

How accurate is it? Speed comes from GPS Doppler, accurate to roughly ±0.1 m/s once you have a fix — generally better than a car’s own speedometer, which most manufacturers bias to read slightly high. The 0–60 timer is good to about ±0.2 s.

The g-meter shows nothing. It needs motion access: Settings → Needle → Motion & Fitness.

Does it work without a signal? Yes. GPS is a satellite receiver and needs no data connection, and Needle has no networking code at all. It works the same in aeroplane mode.

Will it drain my battery? Continuous high-accuracy GPS does use power, which is why Needle only reads location while it is on screen and never in the background. Recording a trip also holds the screen awake by default; you can turn that off in Settings.

Where are my trips stored? On your device only. Deleting the app deletes them. See the privacy policy.