Inspiration

Trip planners stop helping the moment the itinerary is generated, but a real trip keeps changing: a museum runs long, it rains, someone is tired by 3 pm. We wanted a planner that starts from how you travel and then stays useful once the day stops going to plan. That idea (first called TripFlow) became Tralupo, an iOS-first adaptive trip planner that is now live on the App Store.

What it does

  • A profile that knows how you travel. A short questionnaire covers your interests, pace, walking tolerance, food and dietary needs (halal, kosher, nut-free), accessibility (step-free, low walking, rest spots) and anything else you type in free text. The next trip starts from what the last one learned.
  • An itinerary for every day, not a list of landmarks. A five-step wizard (where, when, who, style, notes) produces an hour-by-hour plan. Each stop has a one-line reason, so you always know why it's there.
  • Adaptive replanning. Lock the stops you care about, report that the day changed ("+2 h", say), and Tralupo reworks the rest. A review diff shows what was kept safe and what changed before you apply the new version of the plan.
  • Quick edits. Swap any stop for a ready alternative without rebuilding the day, or make manual edits, which never use up your replan allowance.
  • Vibe Food. Find nearby food spots tailored to what you feel like eating, right where you're standing.
  • Destination photos with photo credits, and your active trip stays readable offline.
  • Fair monetization with RevenueCat. Your first trip is free. After that, choose Premium ($9.99/month, up to 20 trips every rolling 30 days) or a Single Trip ($4.99 consumable that unlocks one trip completely). Paid trips can add a Trip Refill (5 more day replans and 15 more stop replacements, up to 3 per trip). Restore purchases is available on the paywall and in the Profile tab.
  • Sign in with Apple, Google or email, and one-tap permanent account deletion.

How we built it

  • Mobile: React Native + Expo (development builds with expo-dev-client, not Expo Go) and TypeScript.
  • API: NestJS hosted on Railway. It owns all domain logic and database access; the app talks to Supabase only for authentication.
  • Data: Supabase Postgres, with the schema owned by Drizzle and reviewed migrations.
  • Contracts: a shared packages/contracts package of Zod schemas, so the app and the API agree on every request and response.
  • AI: Google Gemini behind a multi-step planning pipeline that runs server-side as a resumable job. You can leave the app during generation and pick up the same job when you come back.
  • RevenueCat: the SDK handles offerings, purchases and restore, keyed to the Supabase user ID. The API is the source of truth for access: an idempotent reconcile(userId) calls RevenueCat's subscriber API from the webhook, after a purchase or restore, and during trip creation. POST /trips returns 402 payment_required when nothing covers the trip, and the app opens the paywall and then continues generating automatically once the purchase completes.
  • Delivery: GitHub Actions CI with impact-based check selection, separate release identities for the API and the mobile app, and EAS builds going through TestFlight to the App Store.

Challenges we ran into

  • Keeping the store listing honest. Our first paywall sold replans and locks before they existed, which is an App Review Guideline 2.3.1 risk. We narrowed the copy to what shipped and restored it only in the same change that made replans and locks reachable in the app.
  • A purchase that granted nothing. The same RevenueCat package maps to different product IDs on the Apple store and on RevenueCat's Test Store, so a sandbox tester bought a trip credit and received nothing. We fixed this by making product IDs an append-only allow-list on the server.
  • Test keys crash release builds. A RevenueCat Test Store key makes the SDK shut down a Release build at launch, so we added release-config checks to make sure production builds carry the Apple key.
  • Shipping a new offering without breaking installed apps. Already-installed clients read the current offering, so new products go into a separate named offering that only new binaries use.
  • Provider terms. The Gemini API terms led us to an 18+ rating, and we shipped 1.0 without live web grounding until we could present it the way Google's terms require.

Accomplishments that we're proud of

  • We shipped a real app to the App Store during Shipaton, with working RevenueCat purchases and restore.
  • The replan flow keeps locked stops safe and explains exactly what moved.
  • The privacy declarations are derived from the actual schema, including an honest Sensitive Info declaration for accessibility and dietary data.

What we learned

  • The hard part of travel AI isn't generating a plan. It's changing one without taking control away from the traveler.
  • Entitlements belong on the server, and product IDs are data rather than constants.
  • App Store review, TestFlight and public release are three separate milestones, and each needs its own planning.

What's next for Tralupo

  • A model-assisted "add a stop".
  • More adaptive in-trip interactions beyond the core replan flow.
  • An annual plan, which is already built but held back for now.
  • Android.

Built With

Share this project:

Updates

Submission history