Find the cheapest fuel that's actually worth the drive.
FuelSmart is an Australian petrol price app with a core differentiator: it calculates net savings after accounting for the fuel your car burns driving to a cheaper station. Most price-finder apps show you the cheapest station — FuelSmart shows you the cheapest station that's actually worth the detour.
| Tool | Version |
|---|---|
| Node.js | 18+ |
| npm | 9+ |
| Expo CLI | npm i -g expo-cli |
| EAS CLI | npm i -g eas-cli |
| Xcode | 15+ (for iOS simulator) |
| Android Studio | Latest (for Android emulator) |
cd fuelsmart-app
npm installCreate a .env file (never commit this):
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your_anon_key_here
EXPO_PUBLIC_GOOGLE_MAPS_API_KEY=your_google_maps_key_here
EXPO_PUBLIC_REVENUECAT_IOS_KEY=appl_xxxxxxxxxxxxxxxxxx
EXPO_PUBLIC_REVENUECAT_ANDROID_KEY=goog_xxxxxxxxxxxxxxxxxxnpx expo startThen press i for iOS Simulator or a for Android Emulator.
fuelsmart-app/
├── app/
│ ├── _layout.tsx # Root layout — auth listener, QueryClient
│ ├── onboarding.tsx # First-run car setup wizard
│ ├── (auth)/
│ │ ├── _layout.tsx # Auth stack (no header)
│ │ ├── login.tsx # Email/password sign in
│ │ └── signup.tsx # Create account + Founders teaser
│ ├── (tabs)/
│ │ ├── _layout.tsx # Bottom tab navigator
│ │ ├── index.tsx # Find Fuel — main station list
│ │ ├── map.tsx # Map view with station pins
│ │ ├── history.tsx # Fill-up log history + stats
│ │ └── profile.tsx # Account, cars, settings
│ ├── station/[id].tsx # Station detail with net savings breakdown
│ ├── add-car.tsx # Add a car profile
│ ├── edit-car/[id].tsx # Edit existing car profile
│ ├── log-fillup.tsx # Record a fill-up with savings tracking
│ ├── alerts.tsx # Price alert management
│ ├── premium.tsx # Paywall — Founders Deal + Monthly
│ ├── fuel-selector.tsx # Default fuel type preference
│ ├── radius-selector.tsx # Search radius preference
│ ├── support.tsx # Help, FAQ, contact
│ └── privacy.tsx # Privacy policy
├── lib/
│ ├── types.ts # All TypeScript interfaces
│ ├── constants.ts # Brand colours, fuel labels
│ ├── supabase.ts # Supabase client + auth/db helpers
│ ├── calculations.ts # Net savings formula (core IP)
│ └── fuelApi.ts # Station fetching + price enrichment
├── store/
│ ├── useUserStore.ts # Zustand: user, cars, preferences
│ └── useStationStore.ts # Zustand: station list, sorting, favourites
└── supabase/
├── migrations/
│ └── 001_schema.sql # Full PostgreSQL + PostGIS schema
└── functions/
├── stations-nearby/ # Edge Function: spatial station query
├── price-ingestor/ # Edge Function: pulls state gov APIs (30min cron)
└── send-alerts/ # Edge Function: push notifications for price alerts
Net Saving ($) = (Price Diff × Litres to Fill) − (Return Drive × L/100km × Current Price)
Where:
- Price Diff = (Local Price − Cheaper Price) ÷ 100 (in dollars)
- Litres to Fill = Tank Size × 0.75 (assumes ¾ empty)
- Return Drive = drive distance × 2 (there and back) ÷ 100
- L/100km = from the user's car profile
A positive result = worth driving. A negative result = not worth the detour.
- Go to supabase.com → New Project
- Choose Sydney (ap-southeast-2) region for Australian latency
- Copy the project URL and anon key
In the SQL Editor, run:
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pg_cron;In the SQL Editor, paste and run the contents of:
supabase/migrations/001_schema.sql
npx supabase functions deploy stations-nearby
npx supabase functions deploy price-ingestor
npx supabase functions deploy send-alertsSet environment secrets for Edge Functions:
npx supabase secrets set NSW_FUELCHECK_API_KEY=your_key_hereIn Supabase Dashboard → Database → Cron Jobs, create:
- Name: price-ingestor
- Schedule:
*/30 * * * *(every 30 minutes) - Command:
SELECT net.http_post('https://your-project.supabase.co/functions/v1/price-ingestor', '{}', 'application/json')
- Register at: https://api.nsw.gov.au
- Subscribe to the Fuel Price product
- Add
NSW_FUELCHECK_API_KEYto Supabase secrets
- Go to console.cloud.google.com
- Enable Maps SDK for iOS, Maps SDK for Android, Distance Matrix API
- Create an API key restricted to your app's bundle ID
- Add to
.envasEXPO_PUBLIC_GOOGLE_MAPS_API_KEY
- Create account at revenuecat.com
- Create two entitlements:
premium,founder - Create two offerings:
default(monthly $2.99),founder(lifetime $19.99) - Add API keys to
.env
eas login
eas build:configureUpdate eas.json with your Apple Team ID and Android Keystore.
eas build --platform ios --profile productioneas build --platform android --profile productioneas submit --platform ios
eas submit --platform androideas update --branch production --message "Price fix"# Run tests
npm test
# Type check
npx tsc --noEmit
# Lint
npx eslint .| Variable | Required | Description |
|---|---|---|
EXPO_PUBLIC_SUPABASE_URL |
✅ | Your Supabase project URL |
EXPO_PUBLIC_SUPABASE_ANON_KEY |
✅ | Supabase anon key (safe to expose) |
EXPO_PUBLIC_GOOGLE_MAPS_API_KEY |
✅ | Google Maps + Distance Matrix |
EXPO_PUBLIC_REVENUECAT_IOS_KEY |
✅ | RevenueCat iOS public key |
EXPO_PUBLIC_REVENUECAT_ANDROID_KEY |
✅ | RevenueCat Android public key |
# Clear Expo cache
npx expo start --clear
# Check for outdated packages
npx expo-doctor
# Generate new icons
npx expo-asset optimize
# View Supabase logs
npx supabase functions logs price-ingestor- Email: support@fuelsmart.app
- Built with ❤️ in Australia