Auto Companion

A local-first vehicle tracker for Android

RoleSole Author
TypeAndroid Application
StackExpo / React Native / SQLite
StatusPrivate · Shipped APK
01Overview

Auto Companion is an Android app for tracking what a vehicle actually costs to run: fuel, servicing, and the documents that expire while you are not looking. I built it for my own bike and car, after noticing that the answer to “what did this cost me last year” lived in a spreadsheet I never opened.

It is local-first, and that was the point rather than a limitation. Every record lives on the device in SQLite. There is no server, no account, and no sign-up screen. A fuel log is the kind of data that has no business leaving the phone, and building it that way removed a whole category of work: no auth, no sync conflicts, and no backend to keep alive for an app with one user.

It ships as an APK built with EAS Build, under the package name com.autocompanion.app. The codebase is 67 tracked files and roughly 3,479 lines of TypeScript, with 14 test files. The repository is private, so there is no link at the foot of this page. What follows is the design, not the source.

02Key Features
Four Tabs, One Question Each
A dashboard for what the vehicle is costing now, a garage listing the vehicles, an insights view for the trends, and settings. Logging fuel, a service or a document each gets its own flow instead of one overloaded form.
Cost and Mileage, Derived
Running costs, fuel mileage and money totals are computed from the logged records rather than typed in. Nothing is a field you have to remember to keep up to date.
Reminders That Fire Locally
Service intervals and document expiry dates schedule local notifications on the device. No push service and no server cron, so nothing has to stay running for a reminder to arrive.
Backup, Not Sync
Google Drive backup is an optional snapshot export to the user's own Drive. It is deliberately not live sync: a local-first app that quietly starts round-tripping through a cloud is no longer local-first.
A Scope That Cannot Over-reach
The OAuth scope requested is drive.file, which grants access only to files the app itself creates, in its own folder. It cannot read the rest of the user's Drive by construction, not by promise.
Ships Without a Secret
No OAuth credentials are baked into the build. Until they are supplied, Settings reports that backup needs setup and the sign-in button is disabled while every other feature works normally.
03Technical Architecture

The data layer is split three ways: a client that owns the connection, a schema module that owns the tables, and one repository per entity. Screens never see SQL. That separation is what makes the app testable without a device, because a repository can be exercised against a throwaway database with no UI involved.

Around it sit four small modules that each own one concern: the Drive integration, notification scheduling, the shared UI components, and a theme. Keeping the Drive code in its own module is why the app can ship with that feature inert. Nothing else imports it, so a missing credential disables one surface instead of breaking the launch path.

The 14 test files aim almost entirely at arithmetic: money, mileage, running costs, the backup plan, export, reminders, scheduling, the schema, and each repository. That is deliberate. A vehicle-cost tracker whose money or mileage maths is wrong is worse than useless, because it reports a confident number that happens to be false. That logic is also pure — records in, a figure out — so it is the cheapest thing in the app to test and the most expensive thing to get wrong. The screens are thin enough that a wrong pixel shows up the moment you open them.

What local-first costs is that a lost device means a lost history. That is precisely what the snapshot export covers, and why it is an action the user takes rather than a background process they have to trust.

04Tech Stack
ExpoBuild & runtime
React NativeApplication UI
TypeScriptWhole codebase
expo-sqliteOn-device store
expo-routerScreen routing
expo-notificationsLocal reminders
expo-auth-sessionDrive OAuth
EAS BuildAPK distribution
JestCost & mileage tests