Before You Start
Prepare Everything First
Do all of this before opening Antigravity. Going in unprepared means you'll stop mid-session to get keys and lose context.
CRITICAL
Step 1 β Prep Your Figma Code Files
Do this before anything else
β
Find and replace in your Figma HTML files before uploading
Find β Replace with:
Alex Rivera β Andrew
Elena Chen β Carol
Marcus Vogt β Wei2
Sarah Blake β Mayvipah
Julian Fox β Chaaanok
USD β IDR
$ β Rp
July 12 β April 11
July 20 β April 15
2024 β 2026
If you skip this, Antigravity will build with the wrong names and currency throughout. Fix it in the source before uploading β not after.
ACCOUNTS
Step 2 β Create All Accounts
All free tiers β do these in parallel
β
Supabase
Your database + realtime + file storage.supabase.com
Create project named bali-trip, region: Singapore
Google Cloud
Maps + Distance Matrix.console.cloud.google.com
Enable: Maps JS API, Distance Matrix API, Geocoding API
OpenAI
GPT-4o for place data extraction.platform.openai.com
Create API key with billing enabled
Open Exchange Rates
Daily IDR/MYR/THB rates.openexchangerates.org
Free plan, no credit card
AviationStack
Flight status tracking.aviationstack.com
Free plan: 100 req/month
KEYS
Step 3 β Collect All Keys Into One File
Save this β you'll paste from it into every session
β
Create a text file called keys.txt and fill these in
SUPABASE_URL=https://YOUR_PROJECT.supabase.co
SUPABASE_ANON_KEY=eyJh...
GOOGLE_MAPS_KEY=AIza...
OPENAI_API_KEY=sk-...
OPEN_EXCHANGE_APP_ID=...
AVIATIONSTACK_KEY=...
# Fill these after running Supabase user seed (Session 1):
ANDREW_ID=
CAROL_ID=
WEI2_ID=
MAYVIPAH_ID=
CHAAANOK_ID=
REFERENCE
Step 4 β Image Reference Map
Paste this at the start of every Antigravity session
β
Your 15 design screens
Image 1
Add Expense form
Image 2
Add Flight form
Image 3
+ Add Menu Modal
Image 4
Add to Itinerary form
Image 5
Add to Wishlist form
Image 6
Edit Itinerary item
Image 7
Flight Status detail
Image 8
Activity Detail view
Image 9
Itinerary Timeline
Image 10
Login / User Select
Image 11
Expenses overview
Image 12
Map view + filters
Image 13
Move to Itinerary picker
Image 14
Wishlist item detail
Image 15
Wishlist list view
Session 1 of 9
Project Setup + Database
Do not build any UI yet. This session creates the project shell, connects Supabase, runs the schema, and seeds the 5 users. Everything else depends on this being correct.
UPLOAD FIRST
What to upload before typing anything
Attach these files to your first message
β
- 1All your Figma HTML/CSS export files (already find-replaced)
- 2All 15 design screenshots (Images 1β15)
- 3Your keys.txt file (Supabase URL + anon key only for now)
Upload all files in the very first message. Antigravity will reference them throughout all sessions without you needing to re-upload.
PROMPT
Session 1 β Full Prompt to Paste
Copy this exactly
β
Paste this as your first message (with files attached)
I am building a shared trip planner web app called "Bali Trip" for 5 travelers. I have attached:
1. My Figma design export files (HTML/CSS) β read these to understand the full design system, component styles, colours, typography, and spacing. Do not build anything yet.
2. Design screenshots (Images 1β15) β reference map is below.
3. My credentials file.
IMAGE REFERENCE MAP:
Image 1 = Add Expense form
Image 2 = Add Flight form
Image 3 = + Add Menu Modal
Image 4 = Add to Itinerary form
Image 5 = Add to Wishlist form
Image 6 = Edit Itinerary item form
Image 7 = Flight Status detail
Image 8 = Activity/Place Detail view
Image 9 = Itinerary Timeline (main view)
Image 10 = Login / User Selection screen
Image 11 = Expenses overview + settlement
Image 12 = Map view with filter bar
Image 13 = Move Wishlist item to Itinerary
Image 14 = Wishlist item detail card
Image 15 = Wishlist list view
TECH STACK: React + Tailwind CSS, Supabase (database + realtime + edge functions).
TRIP CONSTANTS (hardcode these everywhere):
- Trip name: Bali Trip
- Dates: 11 April 2026 to 15 April 2026 (5 days)
- Travelers: Andrew (MYR), Carol (MYR), Wei2 (MYR), Mayvipah (THB), Chaaanok (THB)
- Default travel mode: Car / Driving only. No scooter, no walking options anywhere.
- All prices entered in IDR. Displayed as "Rp 150.000" format.
- No $ signs, no price tier symbols ($$$ etc) anywhere in the app.
SUPABASE CREDENTIALS:
URL: [paste your URL]
Anon Key: [paste your anon key]
YOUR TASK FOR THIS SESSION:
1. Set up the React + Tailwind project connected to Supabase
2. Run this exact SQL schema in Supabase β do not modify any field names:
CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
currency text NOT NULL,
pin_hash text,
created_at timestamptz DEFAULT now()
);
CREATE TABLE fx_rates (
id serial PRIMARY KEY,
base text NOT NULL,
target text NOT NULL,
rate numeric NOT NULL,
fetched_at timestamptz DEFAULT now()
);
CREATE TABLE itinerary_items (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
address text,
opening_hours text,
cost_idr integer,
image_url text,
category text,
status text DEFAULT 'wishlist',
trip_day integer,
start_time time,
duration_mins integer,
sort_order integer,
source_url text,
is_time_block boolean DEFAULT false,
time_block_label text,
is_done boolean DEFAULT false,
added_by uuid REFERENCES users(id),
created_at timestamptz DEFAULT now()
);
CREATE TABLE votes (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
item_id uuid REFERENCES itinerary_items(id) ON DELETE CASCADE,
user_id uuid REFERENCES users(id),
UNIQUE(item_id, user_id)
);
CREATE TABLE activity_attendance (
item_id uuid REFERENCES itinerary_items(id) ON DELETE CASCADE,
user_id uuid REFERENCES users(id),
PRIMARY KEY (item_id, user_id)
);
CREATE TABLE comments (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
item_id uuid REFERENCES itinerary_items(id) ON DELETE CASCADE,
user_id uuid REFERENCES users(id),
text text NOT NULL,
created_at timestamptz DEFAULT now()
);
CREATE TABLE expenses (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
description text,
amount_idr integer NOT NULL,
paid_by uuid REFERENCES users(id),
split_between uuid[] NOT NULL,
category text,
created_at timestamptz DEFAULT now()
);
CREATE TABLE flights (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES users(id),
flight_number text,
airline text,
departure_date date,
departure_time time,
terminal text,
gate text,
data_json jsonb,
last_updated timestamptz DEFAULT now()
);
CREATE TABLE accommodation (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
property_name text,
address text,
checkin_time timestamptz,
checkout_time timestamptz,
host_name text,
host_phone text,
updated_by uuid REFERENCES users(id),
updated_at timestamptz DEFAULT now()
);
ALTER PUBLICATION supabase_realtime ADD TABLE itinerary_items;
ALTER PUBLICATION supabase_realtime ADD TABLE expenses;
ALTER PUBLICATION supabase_realtime ADD TABLE votes;
ALTER PUBLICATION supabase_realtime ADD TABLE activity_attendance;
ALTER PUBLICATION supabase_realtime ADD TABLE comments;
3. Seed the 5 users:
INSERT INTO users (name, currency) VALUES
('Andrew', 'MYR'),
('Carol', 'MYR'),
('Wei2', 'MYR'),
('Mayvipah', 'THB'),
('Chaaanok', 'THB');
4. Show me the 5 user UUIDs from the users table after seeding.
5. Do NOT build any UI components yet.
Confirm when done and show me the UUIDs.
After this session, copy the 5 UUIDs into your keys.txt file before starting Session 2.
Session 2 of 9
Auth + App Shell + Navigation
Build the login screen and the 4-tab navigation shell. No feature tabs need to work yet β just the structure and auth flow.
PROMPT
Session 2 β Full Prompt
Auth screen + app shell
β
Paste this as your Session 2 opening message
Session 1 is complete. The database and schema are set up. Now build Session 2: Auth and App Shell.
USER IDs (from Supabase users table):
Andrew: [paste UUID]
Carol: [paste UUID]
Wei2: [paste UUID]
Mayvipah: [paste UUID]
Chaaanok: [paste UUID]
DESIGN REFERENCE: Image 10 (Login / User Selection screen)
BUILD EXACTLY THIS:
1. LOGIN SCREEN (match Image 10 layout):
- Header: "Ready for Bali?" in large bold type
- Subtext: "Select your profile to continue"
- 5 user avatar cards in a grid: Andrew, Carol, Wei2, Mayvipah, Chaaanok
- Each card has a avatar illustration (use simple initials avatar if no image), name below
- Tapping a card opens a PIN entry overlay
2. PIN ENTRY OVERLAY:
- 4 large dot circles showing PIN progress
- Number pad (1β9, then 0) below
- First visit for this user: "Set your PIN" β ask to enter twice to confirm
- Return visit: "Welcome back, [name]" β verify PIN against stored hash
- Wrong PIN: shake animation on dots, show "Incorrect PIN"
- No lockout, no forgot PIN
- Use bcrypt or SHA-256 to hash the PIN before storing in Supabase users table
3. ON SUCCESSFUL LOGIN:
- Store in React session state (NOT localStorage): user_id, user_name, home_currency
- Navigate to the main app
4. MAIN APP SHELL:
- Bottom navigation bar with 4 tabs: Itinerary (map icon), Wishlist (heart icon), Expenses (wallet icon), Flights (plane icon)
- Match the nav bar style from Image 9 bottom
- Each tab shows an empty placeholder screen for now: "[Tab name] coming soon"
- Active tab highlighted in blue
- App header shows "Bali Trip" + user avatar top right
5. FLOATING + BUTTON:
- Blue circular + button bottom right (above nav bar)
- Tapping it opens the Add Menu Modal (Image 3) with 4 options:
- Add to Wishlist
- Add to Itinerary
- Add Expense
- Add Flight
- These options do nothing yet β just close the modal. They will be wired up in later sessions.
Do not build any tab content yet. Just auth + shell + nav + floating button.
Session 3 of 9
Wishlist Tab
The full wishlist β card list, category filters, add form with GPT place lookup, voting, comments, and the Move to Itinerary flow.
PROMPT
Session 3 β Full Prompt
Complete wishlist tab
β
Paste this as your Session 3 opening message
Auth and shell are working. Now build Session 3: the full Wishlist tab.
DESIGN REFERENCES: Image 15 (list view), Image 14 (item detail), Image 5 (add form), Image 13 (move to itinerary picker)
OPENAI API KEY: [paste key]
SUPABASE URL + KEY: [paste both]
BUILD EXACTLY THIS:
1. WISHLIST LIST VIEW (Image 15):
- "Your saved gems." heading
- 4 category filter pills across top: All Items Β· Stay Β· Food Β· Activities Β· Spa
- Tapping a filter shows only that category
- Cards sorted by vote count desc, then newest first
- Each card shows: full-width image (or placeholder), category badge top-right, name, brief notes preview, vote count
- Floating "+ Add Item" button bottom right β opens Add to Wishlist form
2. ADD TO WISHLIST FORM (Image 5):
- Header image banner: teal gradient with "Capture a new memory" text
- Category selector: 4 icon tiles β Stay (bed icon), Food (fork icon), Activities (hiking icon), Spa (leaf icon). Selected = blue filled tile.
- Fields:
- Location Name (text input, placeholder "e.g., La Favela Bali")
- Address/Link (text input, placeholder "Google Maps link or street address")
- Estimated Price (number input in IDR β shown as "Rp" prefix)
- Notes (textarea, placeholder "Anything special to remember?")
- When user types in Address/Link and taps a "Search" icon button next to the field:
- Call a Supabase Edge Function named "lookup-place"
- Edge Function calls GPT-4o with the input and returns JSON: { name, address, opening_hours, image_url }
- Pre-fill Name, Address, and opening_hours fields with the result
- Set image_url on the card
- If GPT returns null or call fails: show toast "Could not find place β please fill in manually"
- "Add to Wishlist" button at bottom β saves to itinerary_items table with status='wishlist'
- Syncs to all phones instantly via Supabase Realtime
3. WISHLIST ITEM DETAIL (Image 14):
- Full-width image at top with category badge overlay
- Name + price (Rp amount, right-aligned)
- Vote row: "X/5 travelers voted for this" with vote button
- Notes box (grey background)
- 3 buttons at bottom: "Add to Itinerary" (blue), "Edit Wishlist" (outline), "Delete Wishlist" (red text)
4. VOTING RULES:
- Food & Drink and Spa: heart button per person, 1 per item. Shows "3/5 β€οΈ". Green highlight at 3+.
- Activities: 5 name pills (Andrew, Carol, Wei2, Mayvipah, Chaaanok). Each person toggles only their own. Filled = in, outline = out.
- Stay: same as Food hearts, but card shows green border + "β Majority reached" at 3+.
- Only the logged-in user can toggle their own vote/attendance.
5. COMMENTS (π¬ Notes button on each card):
- Opens a slide-up panel
- Shows all comments: author name, text, time ago
- Text input + Post button at bottom
- Append-only (no delete, no edit)
- Real-time sync via Supabase Realtime on comments table
6. MOVE TO ITINERARY (Image 13):
- Opens a modal with place image, place name, "Add [name] to Itinerary" heading
- Date picker: Day 1 (11 Apr) through Day 5 (15 Apr) β shown as "Apr 11, 2026" format
- Time picker: hour:minute AM/PM
- "Confirm & Add to Trip" blue button
- On confirm: updates itinerary_items β set status='confirmed', trip_day, start_time
- Item immediately appears in Itinerary tab
Do not build the Itinerary tab yet. Just make the Move to Itinerary flow complete the database write.
Session 4 of 9
Itinerary Tab β Timeline + Stay
The main itinerary timeline view with travel times between stops, done check-off, conflict alerts, drag to reorder, the Stay sub-tab, and the place detail screen.
PROMPT
Session 4 β Full Prompt
Timeline + Stay sub-tabs
β
Paste this as your Session 4 opening message
Wishlist is working. Now build Session 4: the Itinerary tab with Timeline and Stay sub-tabs.
DESIGN REFERENCES: Image 9 (timeline main view), Image 8 (place detail), Image 4 (add to itinerary form), Image 6 (edit form)
GOOGLE MAPS KEY: [paste key]
SUPABASE URL + KEY: [paste both]
BUILD EXACTLY THIS:
1. ITINERARY TAB STRUCTURE:
- 3 sub-tabs inside Itinerary tab: Timeline Β· Stay Β· Map
- Map sub-tab = placeholder "Coming in next session"
- Default sub-tab = Timeline
2. TIMELINE SUB-TAB (Image 9):
- App header shows "Vacation in Bali", "11 April β 15 April", "5 Travelers"
- Day selector: horizontal scrollable row of day pills β MON 11, TUE 12, WED 13, THU 14, FRI 15
- Active day = blue filled pill
- Default = current date if within trip range, else Day 1
- TIMELINE LAYOUT:
- Vertical timeline with time stamps on the left (e.g. 09:45 AM)
- Category icon circle on the timeline line (coloured by category)
- Item card to the right of the icon showing:
- Name (bold)
- Subtitle / address line
- Thumbnail image (right side of card)
- β
Done button (tap to mark done β grey out card, strikethrough name, move to bottom)
- π¬ comment badge with count
- Done counter at top of day: "2 of 5 done"
- TRAVEL CONNECTOR between consecutive items:
- Row between two cards: π X km β’ Y mins
- Pull from Google Distance Matrix API (driving mode ONLY β no other modes)
- Use address field of each item as origin/destination
- Call once per day load, cache in session state
- If address missing: "Add address to calculate"
- If API fails: "Travel time unavailable"
- CONFLICT ALERT:
- Red β οΈ badge on item card if start_time is before opening hours start OR end time (start + duration) is after opening hours end
- Tapping badge shows tooltip with specific message
- DRAG TO REORDER:
- Long-press to drag items within the same day
- Updates sort_order in database on drop
- Does NOT auto-recalculate times
- TIME BLOCK (lightweight):
- Appears on timeline in lighter grey style
- No image, no voting, no conflict check
- Shows label + time only
- FLOATING + BUTTON on Timeline:
- Opens Add to Itinerary form (Image 4):
- Header banner (teal gradient "Capture a new memory")
- Category selector: Stay Β· Food Β· Activities Β· Spa (icon tiles)
- Location Name field
- Address/Link field (same GPT lookup as wishlist β reuse lookup-place edge function)
- Price field (IDR, Rp prefix)
- Date picker (Day 1β5 = Apr 11β15)
- Time picker
- Notes textarea
- "Add to Itinerary" button (blue)
- "Save to Wishlist" text link below (saves with status='wishlist' instead)
3. PLACE DETAIL SCREEN (Image 8):
- Triggered by tapping any item card on the timeline
- Full-width image at top
- Category badge overlay on image
- Name (large bold)
- Address with map pin icon (tappable β opens Google Maps)
- Date & Time info box + Price info box (side by side)
- Notes section (full text)
- Travel Logistics section:
- "From previous: [previous item name]" β Distance + Travel time
- "To next: [next item name]" β Distance + Travel time
- Both use Google Distance Matrix (driving)
- 2 buttons at bottom: "Edit Item" (outline), "Open Maps" (blue)
4. EDIT ITINERARY ITEM (Image 6):
- Same form layout as Add to Itinerary
- Pre-filled with existing data
- 3 actions at bottom:
- "Save Changes" (blue button)
- "Move to Wishlist" (blue outline, heart icon) β sets status back to 'wishlist'
- "Remove from Itinerary" (red text, trash icon) β deletes the item
5. STAY SUB-TAB:
- Single card for the whole group
- Fields: Property name, Full address, Check-in date + time, Check-out date + time, Host name, Host phone (tapping opens WhatsApp)
- Large "π Copy Address for Grab" button β copies address to clipboard
- Anyone can edit
- If empty: show "Add Accommodation" button
- Save to accommodation table in Supabase
Session 5 of 9
Map Sub-tab
Full-screen Google Map inside the Itinerary tab with category filters, colour-coded pins, tap-to-view place cards, and the distance measure mode.
PROMPT
Session 5 β Full Prompt
Map sub-tab with distance measure
β
Paste this as your Session 5 opening message
Timeline and Stay tabs are working. Now build Session 5: the Map sub-tab inside the Itinerary tab.
DESIGN REFERENCE: Image 12 (map view with filter bar and pin detail)
GOOGLE MAPS KEY: [paste key]
SUPABASE URL + KEY: [paste both]
BUILD EXACTLY THIS:
1. MAP SUB-TAB (Image 12):
- Replace the "Coming soon" placeholder in the Map sub-tab
- Full-screen Google Maps JavaScript API map
- Bali, Indonesia as default centre (lat: -8.4095, lng: 115.1889), zoom 11
2. FILTER BAR (pinned at top of map):
- Pill buttons: All Β· Wishlist Β· Itinerary Β· Stay Β· Food Β· Activities Β· Spa
- Active filter = blue filled pill (default = All)
- Filters can be combined (e.g. Itinerary + Spa)
- Tapping a filter updates which pins are shown on the map
3. PINS:
- Green pin = confirmed itinerary item (status='confirmed')
- Yellow pin = wishlist item (status='wishlist')
- Each pin uses a circular thumbnail image if image_url exists, else a coloured dot with category icon
- All pins matching the active filter are shown simultaneously
4. TAPPING A PIN:
- Opens a bottom sheet sliding up from the bottom
- Bottom sheet shows: image, name, category badge, address, opening hours, cost in "Rp X.XXX"
- Comment count badge
- 2 buttons: "View in Timeline/Wishlist" (jumps to that tab and item) and "π Measure Distance"
5. MEASURE DISTANCE MODE:
- After tapping "π Measure Distance" on a pin:
- Map enters measure mode
- Blue banner at top: "Tap another pin to measure distance"
- User taps any other pin on the map
- App draws a route polyline between the two points
- Result card appears at bottom:
π [Place A] β [Place B]
π X mins β’ Y km β’ Car
- Pulled from Google Distance Matrix API (driving mode ONLY)
- "Clear" button dismisses the result and exits measure mode
6. MY LOCATION:
- β location button at bottom-right of map
- Tapping centres map on browser geolocation position
- Shows blue dot at user's position
- Updates every 30 seconds while map is open
- If permission denied: show toast "Location not available"
7. ZOOM CONTROLS:
- + and β buttons on the right side of the map (Image 12 style)
Session 6 of 9
Expenses Tab
Full expense ledger with IDR input, home currency display, category breakdown, settlement engine, and WhatsApp export.
PROMPT
Session 6 β Full Prompt
Bali-Split ledger + settlement
β
Paste this as your Session 6 opening message
Map is working. Now build Session 6: the full Expenses tab.
DESIGN REFERENCES: Image 11 (expenses overview), Image 1 (Add Expense form)
SUPABASE URL + KEY: [paste both]
CURRENCY RULES β READ CAREFULLY:
- Andrew = MYR, Carol = MYR, Wei2 = MYR
- Mayvipah = THB, Chaaanok = THB
- ALL expenses entered in IDR
- Display each expense in the logged-in user's home currency using rates from fx_rates table
- NEVER call a live currency API on render β always read from fx_rates table
- Cross-currency settlement (Thai person owes Malaysian person): show both "ΰΈΏ 1,450 (β RM 38.20)"
BUILD EXACTLY THIS:
1. EXPENSES OVERVIEW (Image 11):
- Header card (dark blue): "Total Trip Spending" in large text showing total IDR converted to current user's currency
- Two sub-cards: "I OWE" (blue card) and "OTHERS OWE ME" (teal card) β calculated from settlement engine
- FX rate display row: "1 IDR = 0.000285 MYR Β· 0.0023 THB Β· Updated X hours ago" + Refresh button
- Top Categories breakdown: Food, Transport, Stay, Activities, Spa β each with progress bar and total
- Recent Expenses list (grouped by date: TODAY, YESTERDAY, etc.)
- Each expense row: category icon, description, amount in IDR + home currency equivalent, paid by, time
2. ADD EXPENSE FORM (Image 1):
- "New Expense" header with back arrow, "Drafts" text right
- "Total Amount" label
- Large IDR input field β shows "IDR 150.000" as user types (dot-separated thousands)
- Below input: "Approx. [Rp X in home currency]" in small grey text (from fx_rates table)
- Category selector pills (horizontal scroll): Food Β· Transport Β· Stay Β· Activities Β· Spa Β· Other β selected = green filled
- "Split with..." section:
- Toggle: "Split Equally" (default) | "Certain Users"
- In "Split Equally" mode: shows all 5 users with checkbox (all checked), each showing "IDR X share"
- In "Certain Users" mode: uncheck to exclude
- Shows "Sarah, Julian & 2 more" style summary for unchecked users (use actual names)
- Notes field (optional): placeholder "Dinner at the night market..."
- "+ Add Expense" blue button at bottom
- Save to expenses table: amount_idr, paid_by (current user), split_between (array of checked user IDs), category, description
3. SETTLEMENT TAB (sub-tab inside Expenses alongside expense list):
- "Calculate Settlement" button
- Runs minimum-transactions algorithm (NOT just net balances):
1. Calculate net balance per person (total paid β total owed)
2. Separate into creditors (positive) and debtors (negative)
3. Greedily match largest debtor to largest creditor until all zeroed
- Output format:
Mayvipah β Andrew RM 120.50
Chaaanok β Carol RM 88.00
Chaaanok β Wei2 RM 34.00
- MYR for transfers involving Andrew/Carol/Wei2
- THB for transfers involving Mayvipah/Chaaanok
- Cross-currency: show both amounts
- "Export" button generates plain text and copies to clipboard:
Bali Trip Settlement β 15 Apr 2026
Mayvipah pays Andrew RM 120.50
Chaaanok pays Carol RM 88.00
Chaaanok pays Wei2 RM 34.00
Generated by Bali Trip App
4. REALTIME:
- Subscribe to expenses table β new expenses appear instantly on all phones without refresh
Session 7 of 9
Flights Tab
Per-person flight tracking with manual entry and AviationStack status lookup via Edge Function.
PROMPT
Session 7 β Full Prompt
Flight tracker tab
β
Paste this as your Session 7 opening message
Expenses are working. Now build Session 7: the Flights tab.
DESIGN REFERENCES: Image 2 (Add Flight form), Image 7 (Flight Status detail)
AVIATIONSTACK KEY: [paste key]
SUPABASE URL + KEY: [paste both]
BUILD EXACTLY THIS:
1. FLIGHTS TAB MAIN VIEW:
- Header: "Flights" with compass icon top right
- One row per traveler: Andrew, Carol, Wei2, Mayvipah, Chaaanok
- Each row shows:
- User avatar + name
- If no flight saved: "Add flight" prompt (grey, tappable)
- If flight saved: flight number + status badge (On Time green / Delayed yellow / Landed grey / Unknown grey)
- Tapping a row with a saved flight opens the Flight Status detail view
- Tapping "Add flight" opens the Add Flight form
2. ADD FLIGHT FORM (Image 2):
- "Add Flight" header, back arrow, user avatar top right
- FLIGHT NUMBER field (text, e.g. GA-402) with plane icon
- AIRLINE field (text, e.g. Garuda Indonesia) with building icon
- DEPARTURE DATE (date picker, mm/dd/yyyy format)
- DEPARTURE TIME (time picker)
- FLIGHT DETAILS section (labelled "Optional"):
- TERMINAL field
- GATE field
- "Add to Itinerary" blue button β saves flight to flights table and calls the status Edge Function
- Small text below button: "Adding a flight will automatically update your Itinerary and notify you of any schedule changes."
3. SUPABASE EDGE FUNCTION: get-flight-status
- Proxies call to AviationStack API (prevents CORS error in browser)
- AviationStack free plan uses HTTP not HTTPS β the Edge Function handles this server-side
- Input: flight_number
- Output: status, departure airport, arrival airport, departure time, arrival time, terminal, gate, duration
- Saves result to flights.data_json in Supabase
4. FLIGHT STATUS DETAIL (Image 7):
- User avatar + "Voyager" app name top
- "Flight Status" label + status badge (e.g. "β On Time" in green pill)
- Descriptive text: "Your journey to [destination] starts in X days."
- Flight card:
- Flight number (bold, blue, e.g. FLIGHT VY-204)
- Route: [DEP] β [ARR] airport codes
- Departure section: time (large bold), "DEPARTURE" label, airport name, Terminal + Gate tags
- Flight duration (centre, clock icon, e.g. "13H 30M DURATION")
- Arrival section: time (large bold), "+1 DAY" badge if applicable, "ARRIVAL" label, airport name, Terminal/Carousel tags
- Confirmation code, Seat Assignment, Cabin Class, Status β 2x2 grid at bottom of card
- "Manage My Booking" blue button at bottom
5. AUTO-REFRESH:
- Refresh flight status every 10 minutes while Flights tab is open
- Manual refresh button per flight row
- Update flights.data_json and flights.last_updated in Supabase on each refresh
Session 8 + 9 of 9
FX Cron + Final Polish
Two final sessions β FX rate automation and then a full polish pass fixing any visual or functional gaps before launch.
PROMPT
Session 8 β FX Cron Job
Keeps currency rates updated daily
β
Paste this as your Session 8 opening message
Flights are working. Now build Session 8: the FX rate cron job.
OPEN EXCHANGE RATES APP ID: [paste ID]
SUPABASE URL + KEY: [paste both]
BUILD EXACTLY THIS:
1. SUPABASE EDGE FUNCTION: update-fx-rates
- Calls Open Exchange Rates API
URL: https://openexchangerates.org/api/latest.json?app_id=[ID]&base=USD&symbols=IDR,MYR,THB
- Calculate cross rates: IDRβMYR = MYR_rate / IDR_rate, IDRβTHB = THB_rate / IDR_rate
- Upsert into fx_rates table:
- Row 1: base='IDR', target='MYR', rate=[calculated], fetched_at=now()
- Row 2: base='IDR', target='THB', rate=[calculated], fetched_at=now()
- Log success/failure with timestamp
2. SUPABASE CRON JOB:
- Schedule: every day at 00:00 UTC
- Calls the update-fx-rates Edge Function
- Name it: "daily-fx-update"
3. SEED INITIAL RATES (run once now so the app works immediately):
INSERT INTO fx_rates (base, target, rate) VALUES
('IDR', 'MYR', 0.000285),
('IDR', 'THB', 0.0023);
(These are approximate β the cron will overwrite with real rates at midnight)
4. WIRE UP THE REFRESH BUTTON:
- The "Refresh" button in the Expenses tab header calls the update-fx-rates Edge Function on demand
- After the function completes, re-fetch fx_rates from Supabase and update all displayed currency conversions
- Show a loading spinner on the button while running, then "Updated just now" text
PROMPT
Session 9 β Full Polish Pass
Fix everything before sharing with your group
β
Paste this as your Session 9 opening message
FX cron is working. This is the final polish session before launch.
Go through the entire app and fix the following:
1. DESIGN CONSISTENCY:
- Every screen must match the Figma designs I uploaded (Images 1β15)
- Font sizes, spacing, card shadows, border radii, colours must be consistent throughout
- Bottom nav bar style must be identical on every tab
- All prices must show "Rp X.XXX" format (dot as thousands separator) β never "$" or "IDR X,XXX"
- No placeholder "Coming soon" text should remain anywhere
2. MOBILE RESPONSIVENESS:
- Test every screen at 390px wide (iPhone 14 viewport)
- Nothing should overflow horizontally
- All tap targets minimum 44px height
- Bottom nav must not overlap content
3. REALTIME SYNC CHECK:
- Confirm Supabase Realtime subscriptions are active on: itinerary_items, expenses, votes, activity_attendance, comments
- When any user adds/changes data, other users see it within 2 seconds without refresh
4. EDGE CASES TO HANDLE:
- Empty state on Timeline: "No plans yet for Day X β add from Wishlist or use the + button"
- Empty state on Wishlist: "No saved places yet β tap + to add your first"
- Empty state on Expenses: "No expenses yet β tap + to log your first"
- Empty state on Flights: each row shows "Add flight" prompt
- GPT lookup failure: shows manual entry form with toast notification
- AviationStack failure: shows "Flight status unavailable β check airline app"
- No internet: show "You're offline β showing last saved data"
5. NAVIGATION WIRING:
- "View in Timeline/Wishlist" from map opens correct tab + scrolls to correct item
- "Add to Wishlist" from + modal opens Wishlist form
- "Add to Itinerary" from + modal opens Itinerary form
- "Add Expense" from + modal opens Expense form
- "Add Flight" from + modal opens Flight form
- All back arrows navigate correctly
6. FINAL CHECK β run through this full user flow once:
- Login as Andrew β add a place to Wishlist β vote on it β move it to Itinerary Day 2 β check the timeline β mark it Done β add an expense β check settlement β add a flight β view flight status
- Everything should work end to end with no errors in console
Launch
Pre-Launch Checklist
Do this after all 9 sessions are complete. Test on real phones before sharing the link with your group.
CHECKLIST
Test With 2 Real Phones First
You + one friend β before sharing with everyone
β
- Login as Andrew on your phone, login as Carol on a friend's phone simultaneously
- Add a wishlist item on Andrew's phone β confirm it appears on Carol's phone within 2 seconds
- Add an expense on Carol's phone β confirm it appears on Andrew's phone and the IDR converts to MYR correctly
- Move a wishlist item to Itinerary Day 2 β confirm it appears on the timeline on both phones
- Check the settlement engine with at least 3 expenses β verify the maths manually
- Tap the map, confirm all added places appear as pins, tap a pin, confirm the detail card shows correctly
- Use Measure Distance between 2 pins β confirm travel time shows in Car mode
- Add a flight number β confirm status fetches correctly
- Add accommodation address β confirm "Copy for Grab" copies the right text
- Check the app on iOS Safari β "Share β Add to Home Screen" for app-like experience
- Check the app on Android Chrome β menu β "Add to Home Screen"
- Check no console errors in browser DevTools
SHARING
How to Onboard Your 4 Friends
Send this via WhatsApp
β
WhatsApp message to send
Hey everyone! Our Bali trip app is ready π
Link: [your app URL]
1. Open the link on your phone
2. Tap your name
3. Set a 4-digit PIN (you'll use this every time)
4. On iPhone: tap Share β "Add to Home Screen" so it works like an app
5. On Android: tap menu β "Add to Home Screen"
We'll use this to plan the itinerary, split expenses, and track flights. Don't lose your PIN β I can reset it if needed.
API TABLE
Full API Reference
All services used in the app
β
| API | Purpose | Called From |
|---|---|---|
| GPT-4o (OpenAI) | Place name/address/hours/image extraction | Supabase Edge Function: lookup-place |
| Google Maps JS API | Map display + pin rendering | Frontend |
| Google Distance Matrix | Car travel time between locations | Frontend + Edge Function |
| AviationStack | Flight status data | Supabase Edge Function: get-flight-status |
| Open Exchange Rates | Daily IDRβMYR and IDRβTHB rates | Supabase Edge Function: update-fx-rates |
| Browser Geolocation | User's current location on map | Frontend only |
| Supabase Realtime | Live sync across all 5 phones | Frontend subscriptions |