-
-
Flights, grouped into trips — the outbound and return under one heading, the destination's flag, and what a delay was owed
-
World — a globe FlyRight draws itself with Skia, lit by the real sun, with every route you've flown on it
-
Updates — friends in the air with progress rings, and postcards from inside their trips to heart or reply to
-
Know what you're owed — a 195-minute delay becomes a 400 EUR verdict under EU261, with the claim one tap away
-
Travel day — terminal, check-in, gate, boarding, seat and booking in fixed places, counting down to the second
-
Travel stats — kilometres flown, days in the air, the longest flight on its own globe, and your top destination
-
Add a flight — find it by number, scan a boarding pass, upload a ticket, or add it yourself for any year
Inspiration
I fly a lot, and the day of a flight is always the same juggling act: one app for the boarding pass, another to see whether the flight is on time, the airline's app for the gate, and a group chat where everyone asks "did you land?". When something goes wrong, a fourth thing appears days later: a web form from a claims company that keeps a third of whatever the airline owes you.
FlyRight started from a simpler idea. The app that is with you for the whole travel day is the one that should keep your people in the loop, and it is the one that already knows what happened when the flight goes wrong.
So FlyRight is a travel buddy first. It tracks the flight and walks you through the day step by step: at the airport, checked in, bags dropped, through security, passport control, on board, in the air, landed. That walk lives on your Lock Screen and in the Dynamic Island as a Live Activity on iPhone, and as a live notification on Android, counting down on its own with the app closed. The people you choose follow the trip live — the plane riding the route, delays as they happen, the moment you land. Nobody has to ask.
And when the flight is three hours late, FlyRight already knows. It says in plain words what the airline owes you under EU261, drafts the claim letter and points you at the airline's own claim channel. It doesn't file for you and it doesn't take a cut.
What it does
FlyRight is live on the App Store and Google Play as FlyRight: Flight Tracker — Travel buddy & delay claims. Since the first Shipaton submission on 12 September it has shipped eighteen releases in nineteen days, 1.0.32 through 1.1.9, and the product changed shape twice in that window: the map became a globe, and the paywall moved.
Keeping flights and keeping up with people is free.
- Your flights, grouped into trips. The Flights tab no longer lists legs; it groups them into destination trips. The outbound and the return sit together under one heading with the destination city, the country's flag faded across it, the dates and the days spent there. Connections stay inside their trip. Past travel reads newest destination first. A friend's travel groups exactly the same way.
- Add a flight in seconds. Type the number, scan the boarding pass, or share the airline's confirmation PDF — or a screenshot of the email — and every leg imports on its own. Lufthansa, Emirates, Etihad, IndiGo, Goibibo and Amadeus-style receipts are read by barcode or on-device OCR. Adding the same flight twice, even from a codeshare pass, updates the trip instead of duplicating it. Five live lookups a day work before you make an account at all, and your guest flights follow you in when you sign up.
- The boarding pass itself. Scanned or imported once, then full-screen at the gate with the brightness up and no signal needed. Seat, sequence and booking reference fill themselves in.
- A journal worth keeping. Notes, a rating, seat and booking reference, private photos, travel stats down to the aircraft type and maker — all free, with no cap on how many flights you keep.
- Your world as a globe. The World tab is a real earth you turn with a finger and pinch down to coastlines, lit by the actual sun: the terminator falls where it falls right now, and a trip's own globe puts the sun where it was at take-off or landing. Routes, airports and a radar beacon on the trip of the day live on it. Share it as a poster, story or square, with a GPU-drawn glow over the corridors you fly most.
- The people, free on both sides. Follow family and friends, approve who follows you, choose an audience per trip. Read, heart and reply to their postcards — the photo or the line someone sent from inside a trip. Pin a friend's trip to your own Lock Screen as a Live Activity and the countdown runs there too. There is no longer any cap on how many people can follow you.
Pro is the day itself. Automatic monitoring of your own flights — gate, terminal, delay, baggage belt, inbound-aircraft warnings, the live position on the globe — your own Live Activity and travel-day alerts, publishing postcards to your people, and preparing a new claim. Your family never pays to watch: following, reading and replying stay free, and whether their Lock Screen lights up depends on the traveller's subscription, not theirs. You pay to broadcast, not to receive.
- Know what you're owed. A pure-TypeScript rules engine maps the disruption to EU261 and returns a plain payout figure with the reason behind it, not legalese. This release corrected two of its own answers: intra-EU flights over 1,500 km cap at €400, and the EU's outermost regions are covered. Saved claims that carried the old amount were repaired in place.
- Claim, don't decode. The wizard drafts the airline correspondence, routes it to where that airline actually takes claims (a table covering 41 airlines) and tracks the deadline. Letters you already have stay readable forever, subscription or not.
- Wide screens. On an iPad in portrait, an Android tablet or an unfolded Fold, flights, friends and claims open beside their details instead of pushing a new screen.
- Ask for it out loud. "Show my next flight", "Show my boarding pass", "Add a flight" through Siri and Shortcuts on iPhone; the Android twin is registered as AppFunctions for Gemini.
How we built it
Expo SDK 57 and React Native with Expo Router, both stores through EAS Build, EAS Hosting for the website and API routes. The journal is Drizzle over SQLite, so it opens instantly and works offline. Convex is the sync backend, Clerk is auth, and the Clerk user id is deliberately the same key RevenueCat uses for app_user_id and Layers uses for identity — one id across auth, sync, entitlements, attribution and push, so an install joins to the revenue it produced.
RevenueCat, and the week we moved the paywall. The catalogue is monthly, yearly and lifetime in one offering, with a 14-day trial on the store subscriptions and RevenueCat Web Billing running the same entitlement on the web in 18 currencies — a free EU261 checker at getflyright.com/check, then Pro bought on the web keyed to the Clerk id so it is already attached when the app is installed.
What changed on 23 September is not the catalogue but the line it sells across. FlyRight used to cap a free account at three followers. That cap taxed the exact loop that grows the app: every person who invited their family hit a wall, and the people on the other side of the wall were the ones who would have installed it. So the cap is gone, journals and following are free, and Pro became the travel day — monitoring, publishing and claim preparation.
The enforcement is server-side, not a client flag. isPro() in Convex guards the provider calls (freeFlightDetails() strips gate, terminal, position and inbound from a free response, and only returns a delay once the flight has actually landed — so a free traveller can still run a manual EU261 check on a past delay), the Live Activity meter, postcard publishing and claim generation. The RevenueCat webhook writes the mirror; a reconcileAccess job stops paid polling and pushes at expiry, and cancels any pending acquisition reminder the moment someone buys.
The offer itself is trip-shaped. There is no paywall on launch and none when you save a flight. One compact "Live updates off · See Pro" row sits on an upcoming trip, opening a short sheet — three things Pro adds, "Family follows free", plans, and a third option we think matters more than either: "Remind me 2 days before this trip." It is an in-app reminder, not a deferred purchase; it starts no billing, sends no push, and is cancelled by a deletion, a reschedule, departure or an actual subscription. The × on the home card writes a permanent, account-scoped, cross-device preference — a dismissal that a reinstall cannot undo, because a promotion that comes back is a promotion that gets the app deleted. Acquisition cards only ever appear on a future, owned flight: never on an empty journal, never on a past trip, never while reading someone else's travel. Signed-out guests can browse real RevenueCat prices, and the chosen plan and flight survive the sign-up.
The globe is ours. react-native-maps is gone. Both MapKit and Google Maps floor zoom-out at roughly a hemisphere — you cannot see a life of flying at once — and the issue asking to lift it is closed "not planned". So the World tab, the trip inset and a person's travel card are a globe drawn in react-native-skia from a runtime shader, with the projection maths in TypeScript and textures generated by a script. src/services/sun.ts computes the subsolar point and the shader mixes real sunlight with a studio light through a daylight uniform. The plane on an active route moves from the provider's last reported position carried forward along its track, and falls back to the timetable when the position is null — which, over an ocean, it usually is.
One WebGPU feature, on purpose. The share poster's route-density glow runs on react-native-webgpu with shaders written as 'use gpu' TypeScript and compiled to WGSL at build time by TypeGPU: two compute passes, an atomicMax peak feeding a CPU auto-exposure gain, a colour ramp packed to RGBA, then a Skia image drawn under the atlas. No adapter means the switch simply isn't there and the poster is the plain atlas. The globe stayed on Skia — this is the one place the GPU earned its 20 MB.
iOS 27, built on this desk. An app linked against the iOS 27 SDK without UIKit scene-lifecycle adoption is refused at launch by iOS 27; we measured it both ways on the same simulator. Expo backported scene support to SDK 57.0.23, so FlyRight adopted it without waiting for SDK 58 — but EAS Build has no Xcode 27 image, so every 1.1.x release since has been an eas build --local IPA off this Mac, submitted through EAS, with Android still building in the cloud.
Measured on real phones, not our desk. Expo Observe reports startup time from every install, and the first thing it taught us was to distrust it: most of our "slow startups" were Google Play's pre-launch test robots and our own emulator builds. FlyRight now stops reporting from Firebase Test Lab devices and emulators, and strips private trip details from screen reports. With clean data we profiled a release build on a Pixel and found the launch spent its time loading code for screens nobody had opened yet. Loading modules on first use, a lazy React Native UIManager and tabs built on first open cut JavaScript bundle load by about 70% for real Android users and 60% on iPhone. The Android p90 is still slower than we want.
OneSignal carries follower pushes, travel-day alerts and the notification that a new version has reached the store, addressed through secret aliases rather than user ids. Layers carries growth analytics and install attribution on the same id as the revenue. Detour makes an invite link survive the install, so someone who taps "follow Maja" in a message lands on that invitation after installing from the store. Flight status is AeroDataBox behind a shared cache and a per-user daily quota; Cloudflare Email Routing and a Worker run the two-way support relay.
Challenges we ran into
We put the paywall on the wrong side of the product. Three followers seemed generous when the feature was new. It took a month of data to see it was charging people for the thing that spreads the app. Undoing it was the largest single commit of the hackathon — 184 files — because "free" had to be true on the server too: every cap, every push string, every gate in a query. The hard part wasn't removing a constant, it was deciding what Pro is for and keeping the app honest about it, down to refusing to market "automatic seat changes" because the provider does not actually expose seat changes.
Live Activities have five sync points. The lock-screen card, the app's own state, the push payload, the widget extension and the backend's content builder must all agree on one shape; any drift and the Lock Screen quietly lies about your flight. Then iOS kills every activity after eight hours, so a long-haul day needs a liveness sweep and a countdown that ticks natively instead of from pushes.
Time zones bit a real user. Manually entered flights stored bare wall-clock times and drifted two and a half hours when the phone changed zone mid-trip. The rule now: print the digits as written, do every calculation on a pinned instant in the airport's own zone.
Our own compensation engine was wrong about two cases. A flight inside the EU over 1,500 km caps at €400, not €600, and the outermost regions — Réunion, the Canaries, the Azores — are EU departures. We found both, fixed the engine, and then went back and corrected the saved claims that had already been told the wrong number. The one part of the app that must never be wrong is the part that says what you're owed, and it was, twice.
The reorder we had to undo. 1.1.0 moved the app to open on a Home feed of other people's travel. TestFlight feedback was immediate and consistent: I open this to see my flight. 1.1.1 put Flights back first, kept the feed as an Updates tab, and never reached the App Store as 1.1.0 at all — we withdrew the review and renamed the version record. Shipping fast is only useful if you can also un-ship.
Grouping legs into trips is not a sort. A return that hasn't been booked yet, a connection that looks like a stay, a flight saved with no real arrival time, a second city in the same country — each one breaks a naive grouping in a different way, and the grouping has to recompute silently every time a flight is added.
Accomplishments that we're proud of
Eighteen releases in nineteen days, one developer, on two stores that both had to accept them. 1.1.9 is live on Google Play and in App Review on iOS, where 1.1.8 is live. 586 people used FlyRight in the last 28 days, 574 of whom arrived inside that window — 795 new users since launch on 1 August.
The globe. Not because a globe is hard, but because the right answer to "the map SDK won't zoom out far enough" turned out to be writing the earth ourselves, with a shader, a sun and a projection — and it shipped in five days.
Moving the paywall mid-hackathon, with a week left, because the data said the free tier was the growth engine and we were charging rent on it.
And the product is honest about the boring half: most flights are fine, so most days FlyRight is just a good travel journal that keeps your people in the loop.
What we learned
Never put a price on the part of your product that spreads it. The follower cap looked like the obvious upgrade trigger and was actually a tax on word of mouth. What people will pay for is the day something is at stake — the gate changing, the delay, the claim — not the right to have their mother watch them land.
The server has to know about Pro. A client-side check is fine for a paywall. The moment an entitlement has a social side — whose family gets live updates — the backend has to be the one saying yes, and "free" has to be true in the query, not just in the UI.
The platform will set your deadlines for you. Adopting the iOS 27 scene lifecycle wasn't a feature; it was the difference between an app that launches and one that doesn't, and it arrived with no cloud builder that could compile it.
What's next for FlyRight
The Samsung Galaxy Store, where a billing-free build variant already runs. Real flown tracks on the trip globe — the FlightAware integration is written and sitting behind an unset key until the licence question is settled. UK261, Canada's APPR and Brazil. And closing the loop from claim drafted to money actually received, which is the only metric that counts.
Links: App Store · Google Play · getflyright.com · Source on GitHub
Built With
- aerodatabox
- clerk
- cloudflare-workers
- convex
- drizzle
- eas
- expo-router
- expo.io
- ios-live-activities
- kotlin
- layers
- ml-kit
- onesignal
- react-native
- react-native-skia
- react-native-webgpu
- revenuecat
- revenuecat-web-billing
- sqlite
- stripe
- swift
- swiftui
- typegpu
- typescript

Log in or sign up for Devpost to join the conversation.