v3.1

ROMPO β€” Master Product & Architecture Document

Version 3.1 Β· August 2026


Table of Contents

  1. Product Overview
  2. User Personas
  3. Customer Flows
  4. Feature Map
  5. Data Architecture
  6. Frontend Architecture
  7. Backend Architecture
  8. Design System
  9. Internationalization (i18n)
  10. Offline & Caching Strategy
  11. Security & Access Control
  12. Integrations & APIs
  13. Analytics & Metrics
  14. Distribution & Marketing
  15. Known Limitations & Tech Debt
  16. Roadmap Opportunities
  17. Changelog

1. Product Overview

Rompo is a premium, mobile-first family travel planning app designed to coordinate multi-party trips β€” where multiple families, grandparents, or friend groups traveling from different cities converge on a shared destination.

Core Value Proposition

"One trip. Many travelers. Zero chaos."

Rompo solves the #1 pain point of group travel: coordination across different travel parties with different ages, needs, origins, and schedules. Unlike generic itinerary apps, Rompo is built around the concept of Travel Parties β€” independent family units that each have their own flights, origins, and needs, but share a destination, accommodation, and activities.

Key Differentiators

  • Multi-party travel model β€” Not just "one group," but multiple family units merging at a destination
  • Age-aware AI itinerary generation β€” Considers toddler nap times, senior rest breaks, teen-friendly activities
  • Party-colored timeline β€” Visual transport cards show which party is on which leg
  • Collaborative editing β€” Trip owners can invite other users who can edit their own party's legs
  • Share-without-signup β€” Beautiful read-only trip views via tokenized share links with OG metadata
  • Bilingual β€” Full English and Russian support

Target Market

Families planning vacations where multiple households travel together β€” ski trips, beach holidays, destination weddings, reunion trips, multi-generational travel.


2. User Personas

Persona A: "The Organizer" (Primary)

  • Who: Parent (30–50), tech-savvy, plans 2–4 trips/year
  • Need: Coordinate flights, hotels, and activities across 2–4 families
  • Pain: Spreadsheets, WhatsApp chaos, missed details
  • Journey: Creates trip β†’ adds parties β†’ builds transport β†’ generates itinerary β†’ shares with everyone

Persona B: "The Invited Traveler"

  • Who: Grandparent, in-law, or friend invited to a trip
  • Need: See their specific flight info, hotel details, and daily plan
  • Pain: Information overload β€” only wants their relevant details
  • Journey: Receives invite email β†’ logs in β†’ sees their party's trip view β†’ optionally edits own legs

Persona C: "The Viewer" (No Account)

  • Who: Anyone receiving a share link
  • Need: Quick glance at trip details
  • Pain: Doesn't want to install an app or create an account
  • Journey: Clicks shared link β†’ sees beautiful read-only trip overview

3. Customer Flows

Flow 1: First-Time User (Landing β†’ Dashboard)

Landing Page (4-step onboarding carousel)
  β”œβ”€ Page 0: Hero β€” "One trip. Many travelers. Zero chaos."
  β”œβ”€ Page 1: "Tell us who's coming along"
  β”œβ”€ Page 2: "AI plans the perfect day"
  └─ Page 3: "Share with one tap" β†’ [Get Started β€” It's Free]
       └─ Redirects to Base44 auth
            └─ Dashboard (first-time empty state)
                 └─ Onboarding Tour (5 steps)
                      └─ "Create First Trip" CTA

Key metrics to track: Landing β†’ Sign-up conversion, Tour completion rate, Time to first trip creation.

Flow 2: Trip Creation Wizard (7 Steps: Step 0–6)

Step 0: TRIP TYPE β€” What kind of trip?
  β”œβ”€ Two vibrant gradient cards:
  β”‚    β”œβ”€ πŸŽ’ Friends β€” "One group, everyone flies from their own city"
  β”‚    └─ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ Families β€” "Multiple family groups, each flying from different cities"
  β”œβ”€ Selection determines Step 1 variant
  └─ [Card tap β†’]
       ↓
Step 1: WHO'S COMING? (branched by trip type)
  β”‚
  β”œβ”€ [Families mode β†’ Step1Family]
  β”‚    β”œβ”€ Set trip name
  β”‚    β”œβ”€ Add travel parties (name, color, origin city/country)
  β”‚    β”œβ”€ Drag-to-reorder parties
  β”‚    β”œβ”€ Add members per party (name, age category, optional email)
  β”‚    β”œβ”€ Email lookup: checks if user exists in app
  β”‚    └─ [Next β†’]
  β”‚
  └─ [Friends mode β†’ Step2Friends]
       β”œβ”€ Set trip name
       β”œβ”€ Add individual friends (name, origin city, optional email)
       β”œβ”€ Each friend becomes their own single-member party
       └─ [Next β†’]
       ↓
Step 2: WHERE & WHEN
  β”œβ”€ Search destination (Google Places Autocomplete)
  β”œβ”€ Set country (auto-filled from location search)
  β”œβ”€ Pick start & end dates
  β”œβ”€ Shows trip duration + party summary pills
  β”œβ”€ AI travel tip card (fetched on destination change)
  └─ [Next β†’]
       ↓
Step 3: TRAVEL β€” How Is Everyone Getting There?
  β”œβ”€ For each party: add transport legs (flight/train/bus/car/transfer/ferry)
  β”œβ”€ Each leg: from/to locations (with airport search), times, details
  β”œβ”€ Assign parties to shared legs
  β”œβ”€ "Everyone Meets Up" divider when independentβ†’shared transition
  β”œβ”€ AI-suggested transfer times (optional LLM call)
  └─ [Next β†’]
       ↓
Step 4: STAY β€” Where Is Everyone Staying?
  β”œβ”€ Search accommodations via Google Places (or add manually)
  β”œβ”€ Accommodation cards with check-in/out dates/times
  β”œβ”€ Assign parties to accommodations
  β”œβ”€ Fallback to manual entry if Places API unavailable
  └─ [Next β†’]
       ↓
Step 5: PLAN β€” AI Itinerary Generation
  β”œβ”€ Set preferences (budget, pace, activities, accessibility, notes)
  β”œβ”€ AI consent modal (first-time only β€” persisted on user record)
  β”œβ”€ [Generate Itinerary ✨]
  β”‚    β”œβ”€ If trip.trip_pro is false β†’ PaywallModal opens (gates AI generation)
  β”‚    └─ If trip.trip_pro is true β†’ LLM call β†’ structured JSON response
  β”œβ”€ Day-by-day view with activity cards (time, title, description, age tag, icon)
  β”œβ”€ Fine-tune bar: More Rest / More Adventure / Kid-Friendly / Earlier / Later / More Food
  β”œβ”€ Regenerate with adjusted preferences
  └─ [Next β†’] or [Skip for now]
       ↓
Step 6: REVIEW & SAVE
  β”œβ”€ Trip summary header + timeline preview + sharing config
  β”œβ”€ Status selector (draft/planned/active/completed)
  β”œβ”€ [Save & Finish] β†’ creates all entities β†’ redirects to Trip page
  β”œβ”€ Handles both create and edit (cascading cleanup on edit)
  └─ Sends invite emails to members with linked email addresses

Wizard persistence: Auto-saved to localStorage every 2s (debounced) via useWizardPersistence. Expires after 24h. Not restored when editing.

Edit mode: Accessed via ?edit=tripId query param. Loads all existing data into wizard for modification. Cleans up old entities before saving updated ones.

Progress bar: 6-step progress (Step 0 has no progress indicator). Steps are clickable to navigate back to any previously reached step.

Flow 3: Trip Viewing (Trip Page)

Trip Page (/Trip?id=...)
  β”œβ”€ Header: back button, "Trip Details" title, Share + Invite buttons
  β”œβ”€ Offline Banner (when offline, shows cached data)
  β”œβ”€ Trip Header Card: gradient bg, title, destination, dates, countdown, party avatars
  β”œβ”€ Owner Controls: "Allow party editing" toggle
  β”œβ”€ Tab Navigation: Overview | Timeline | Activities | People
  β”‚
  β”œβ”€ [Overview Tab]
  β”‚    β”œβ”€ Travel Parties grid (2-col, color-coded, member count)
  β”‚    β”œβ”€ Trip Stats grid (flights, transfers, nights, activities β€” clickable)
  β”‚    └─ Travelers list (name, age, age category badge)
  β”‚
  β”œβ”€ [Timeline Tab]
  β”‚    β”œβ”€ Grouped by date
  β”‚    β”œβ”€ Independent transport legs (party-specific)
  β”‚    β”œβ”€ "Everyone Meets Up" divider
  β”‚    β”œβ”€ Shared transport legs
  β”‚    └─ Accommodation cards
  β”‚
  β”œβ”€ [Activities Tab]
  β”‚    └─ AI-generated itinerary + activity management
  β”‚
  └─ [People Tab]
       β”œβ”€ Party-grouped member cards with age categories
       β”œβ”€ Add/edit travelers per party
       └─ Convergence view showing party merge points

Flow 4: Collaboration & Invitations

Trip Owner clicks [+ Invite]
  └─ Invite Modal opens
       β”œβ”€ Enter email address
       β”œβ”€ Select party to assign
       β”œβ”€ [Send Invite]
       β”‚    β”œβ”€ Creates InvitedTripUser record (status: pending)
       β”‚    β”œβ”€ Invites user to app via base44.users.inviteUser()
       β”‚    └─ Sends email notification via Core.SendEmail
       └─ Shows list of existing invites with status badges

Invited User receives email β†’ Logs in β†’ Opens Dashboard
  └─ Trip appears in "Shared" tab
       └─ Opens Trip page
            β”œβ”€ Auto-accepts pending invite
            β”œβ”€ Can view full trip
            └─ If "allow_party_editing" is ON β†’ can edit own party's legs

Flow 5: Sharing (No Account Required)

Trip Owner clicks [πŸ”— Share]
  β”œβ”€ Creates/reuses ShareLink entity (unique token)
  β”œβ”€ Generates preview URL: /functions/sharePreview?token=...&lang=...
  β”œβ”€ Uses Web Share API (mobile) or clipboard (desktop)
  └─ Share link flow:
       β”œβ”€ Messenger/social crawlers β†’ GET request β†’ HTML with OG meta tags
       β”‚    └─ og:title, og:description, og:image (Unsplash travel photo)
       └─ Users β†’ auto-redirect to /SharedTrip?token=...&lang=...
            └─ SharedTrip page (no auth required)
                 β”œβ”€ Calls getSharedTrip backend function
                 β”œβ”€ Renders read-only trip view
                 β”œβ”€ Stats, parties, transport cards, accommodations
                 └─ "Plan your own β†’" CTA to Rompo

Flow 6: Dashboard Management

Dashboard
  β”œβ”€ Shows all trips (own + invited)
  β”œβ”€ Filter pills: All | Upcoming | Active | Past
  β”œβ”€ Each TripCard shows:
  β”‚    β”œβ”€ Status gradient header (draft/planned/active/completed)
  β”‚    β”œβ”€ Trip name, destination, dates
  β”‚    β”œβ”€ Progress text (days to go / day X of Y / completed)
  β”‚    └─ Actions: View | Edit | Delete
  β”œβ”€ Pull-to-refresh support
  β”œβ”€ Offline mode with cached data
  └─ Admin view toggle (admin users see all trips)

4. Feature Map

| Feature | Status | Priority | Notes | |---------|--------|----------|-------| | Multi-party trip creation | βœ… Shipped | P0 | Core differentiator | | 7-step creation wizard (0–6) | βœ… Shipped | P0 | Trip type selector + progress bar + auto-save | | Google Places search | βœ… Shipped | P0 | Airports, cities, accommodations | | Transport leg management | βœ… Shipped | P0 | Flight, train, bus, car, ferry, transfer | | Accommodation management | βœ… Shipped | P0 | With party assignment | | AI itinerary generation | βœ… Shipped | P1 | LLM-powered, age-aware | | Fine-tune itinerary | βœ… Shipped | P1 | 6 adjustment presets | | Trip preferences | βœ… Shipped | P1 | Budget, pace, activities, accessibility | | Share via link | βœ… Shipped | P1 | OG tags for social preview | | Collaborative editing | βœ… Shipped | P1 | Invite by email, party assignment | | Offline mode | βœ… Shipped | P2 | localStorage caching | | Pull-to-refresh | βœ… Shipped | P2 | Mobile UX | | Bilingual (EN/RU) | βœ… Shipped | P2 | Full translation coverage | | Dark mode | βœ… Shipped | P2 | System preference + manual toggle, deep navy palette | | Onboarding tour | βœ… Shipped | P2 | Dashboard + Wizard tours | | Admin view | βœ… Shipped | P3 | See all trips (admin role, hidden toggle) | | AI consent & age bucketing | βœ… Shipped | P0 | Privacy-safe AI: age groups only, consent modal | | Sign in with Apple | βœ… Shipped | P0 | Apple login via Base44 auth | | Privacy policy (expanded) | βœ… Shipped | P0 | AI-Generated Content & Third-Party Login sections | | Multi-party analytics | βœ… Shipped | P2 | Event tracking across wizard + sharing | | Design system tokens | βœ… Shipped | P1 | Unified CSS variables across globals.css + index.css | | Trip type selector | βœ… Shipped | P1 | Friends vs Families with vibrant gradient cards | | People tab | βœ… Shipped | P1 | Full people management on Trip page | | Activities tab | βœ… Shipped | P1 | AI itinerary display + activity management | | Public App Store launch | βœ… Shipped | P0 | Live on iOS App Store GB | | Marketing landing page | βœ… Shipped | P0 | /MarketingLanding β€” public-facing homepage | | TestFlight beta retirement | βœ… Shipped | P0 | Signup flow removed; App Store only | | Google Search Console dashboard | βœ… Shipped | P2 | Admin-only, OAuth connector, query analytics | | Trip Pro paywall | βœ… Shipped | P1 | PaywallModal gates AI itinerary in Step 5; trip.trip_pro flag; price_variant A/B/C | | PDF export | πŸ”œ Planned | P2 | Gated behind Trip Pro | | Expense tracking | πŸ”œ Planned | P2 | Entity exists, no UI | | Real-time collaboration | πŸ”œ Planned | P3 | Entity subscriptions available | | Push notifications | πŸ”œ Planned | P3 | β€” |


5. Data Architecture

Entity Relationship Diagram

User (built-in)
  β”‚
  β”œβ”€ creates β†’ Trip
  β”‚              β”œβ”€ has many β†’ TravelParty
  β”‚              β”‚               β”œβ”€ has many β†’ Member
  β”‚              β”‚               └─ assigned via β†’ LegAssignment
  β”‚              β”œβ”€ has many β†’ Leg (transport + accommodation)
  β”‚              β”‚               └─ assigned via β†’ LegAssignment
  β”‚              β”œβ”€ has many β†’ ItineraryItem
  β”‚              β”œβ”€ has many β†’ Activity
  β”‚              β”œβ”€ has many β†’ Expense (entity exists, UI pending)
  β”‚              β”œβ”€ has many β†’ ShareLink
  β”‚              └─ has many β†’ InvitedTripUser
  β”‚
  └─ invited via β†’ InvitedTripUser

Entity Schemas

Trip

| Field | Type | Required | Notes | |-------|------|----------|-------| | title | string | βœ… | Trip name | | destination | string | βœ… | City/region | | destination_country | string | | Country | | destination_lat/lng | number | | Coordinates | | start_date | date | βœ… | Trip start | | end_date | date | βœ… | Trip end | | status | enum | | draft, planned, active, completed | | emoji | string | | Destination emoji | | allow_party_editing | boolean | | Collaboration toggle | | trip_pro | boolean | | Trip Pro unlocked (gates AI itinerary, multi-family >2, PDF export) | | pro_purchased_at | datetime | | UTC timestamp of purchase (used for 7-day refund window) | | pro_stripe_session_id | string | | Stripe Checkout Session ID (cs_...) for idempotency | | requires_pro | boolean | | True when trip has features needing Pro (e.g. β‰₯3 parties); set client-side, does not block save | | price_variant | enum | | A=$9.99, B=$14.99, C=$19.99 β€” assigned via hash(trip_id) % 3 at paywall_viewed |

TravelParty

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | name | string | βœ… | "The Smiths" | | color | string | | Hex color | | origin_city/country | string | | Departure location | | origin_lat/lng | number | | Coordinates | | order | number | | Display order |

Member

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | party_id | string | βœ… | FK to TravelParty | | name | string | βœ… | Member name | | age | number | | Used for AI itinerary | | age_category | enum | | Toddler through Senior | | role | enum | | organizer, traveler, child | | user_id | string | | Linked app user |

Leg (Transport + Accommodation)

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | type | enum | βœ… | flight, train, bus, car, transfer, ferry, accommodation, activity | | title | string | βœ… | Leg name | | date | date | βœ… | Date of leg | | start_time/end_time | string | | HH:MM format | | from_location/to_location | string | | Origin/destination names | | from_code/to_code | string | | Airport/station codes (IATA) | | from_lat/from_lng/to_lat/to_lng | number | | Coordinates | | duration | string | | e.g., "2h 15m" | | details/notes | string | | Additional info | | place_id | string | | Google Places ID | | phone/website/photo_url | string | | Accommodation details | | is_shared | boolean | | Shared across all parties | | order | number | | Sort order |

LegAssignment

| Field | Type | Required | Notes | |-------|------|----------|-------| | leg_id | string | βœ… | FK to Leg | | party_id | string | βœ… | FK to TravelParty |

ItineraryItem

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | day_number | number | βœ… | Day of trip (1-indexed) | | time | string | | HH:MM | | title | string | βœ… | Activity name | | description | string | | Details | | type | enum | | activity, meal, rest, transport | | age_tag | enum | | All Ages, Kids 4+, Teens+, etc. | | icon | string | | Emoji | | duration_minutes | number | | Duration | | order | number | | Sort within day |

ShareLink

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | party_id | string | | Optional: limit to party view | | token | string | βœ… | Unique share token | | is_active | boolean | | Can be deactivated |

InvitedTripUser

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | invited_email | string | βœ… | Email of invitee | | invited_user_id | string | | Set when accepted | | party_id | string | | Assigned party | | status | enum | βœ… | pending, accepted, declined, revoked | | permissions | array | | e.g., ["edit_own_legs"] |

Activity

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | title | string | βœ… | Activity name | | date | date | βœ… | Date | | category | enum | | sightseeing, dining, adventure, etc. | | estimated_cost | number | | Cost estimate |

Expense (Entity exists, UI pending)

| Field | Type | Required | Notes | |-------|------|----------|-------| | trip_id | string | βœ… | FK to Trip | | title | string | βœ… | What for | | amount | number | βœ… | Amount | | paid_by | string | βœ… | Payer | | split_between | array | | Names for splitting | | category | enum | | accommodation, food, transport, etc. |


6. Frontend Architecture

Technology Stack

  • Framework: React 18 (SPA)
  • Routing: react-router-dom v6
  • State Management: React Query (server state) + useState/useEffect (local state)
  • Styling: Inline styles with CSS variables (Rompo Design System)
  • Animations: Framer Motion
  • UI Components: shadcn/ui (Radix primitives + Tailwind)
  • Icons: Emoji-based (no icon library dependency)
  • Fonts: DM Sans (body) + DM Mono (numbers/codes) β€” Google Fonts

Page Structure

| Page | Route | Auth Required | Description | |------|-------|---------------|-------------| | Landing | / | No | Onboarding carousel, auto-redirect if logged in | | Dashboard | /Dashboard | Yes | Trip list, filters, management | | CreateTrip | /CreateTrip | Yes | 7-step wizard (0–6), edit via ?edit=id | | Trip | /Trip?id=... | Yes | Trip detail view with tabs | | Shared | /Shared | Yes | Trips shared with you | | SharedTrip | /SharedTrip?token=... | No | Public read-only trip view | | Profile | /Profile | Yes | Settings, language, dark mode, logout | | MasterDoc | /MasterDoc | Yes | Internal product documentation | | Support | /Support | Yes | Help & FAQ | | SupportTickets | /SupportTickets | Yes | Support ticket management | | Privacy | /Privacy | No | Privacy policy | | MarketingLanding | /MarketingLanding | No | Marketing page | | SearchConsole | /SearchConsole | Admin | Google Search Console analytics dashboard |

Component Organization

components/
β”œβ”€β”€ BottomNav.jsx              β€” Fixed bottom navigation bar
β”œβ”€β”€ TripCard.jsx               β€” Trip card for dashboard
β”œβ”€β”€ TripHeader.jsx             β€” Destination photo / purple gradient trip header
β”œβ”€β”€ TransportLegCard.jsx       β€” Dark navy transport card
β”œβ”€β”€ AccommodationCard.jsx      β€” Dark navy accommodation card
β”œβ”€β”€ ActivityRow.jsx            β€” Activity item with time bar
β”œβ”€β”€ ProgressBar.jsx            β€” 6-step wizard progress (steps 1–6)
β”œβ”€β”€ InviteCollaboratorModal.jsx β€” Email invite modal
β”œβ”€β”€ TripShareSection.jsx       β€” Share link generation
β”œβ”€β”€ PullToRefresh.jsx          β€” Pull-to-refresh wrapper
β”œβ”€β”€ OfflineBanner.jsx          β€” Offline notification
β”œβ”€β”€ AdminViewToggle.jsx        β€” Admin/user view switch
β”œβ”€β”€ MobileSelect.jsx           β€” Custom mobile select
β”œβ”€β”€ DeleteConfirmModal.jsx     β€” Deletion confirmation
β”œβ”€β”€ SearchBottomSheet.jsx      β€” Search overlay
β”œβ”€β”€ PageHeader.jsx             β€” Generic page header
β”œβ”€β”€ DarkModeContext.jsx        β€” Dark mode provider
β”œβ”€β”€ DarkModeToggle.jsx         β€” Toggle button
β”œβ”€β”€ AiConsentModal.jsx         β€” AI data disclosure consent
β”œβ”€β”€ paywall/
β”‚   └── PaywallModal.jsx       β€” Trip Pro upsell modal (shadcn Dialog, feature list, Stripe CTA placeholder)
β”œβ”€β”€ LanguageContext.jsx         β€” i18n provider + translations
β”œβ”€β”€ useScrollRestore.js        β€” Scroll position persistence
β”œβ”€β”€ useTabState.js             β€” Tab state persistence (sessionStorage)
β”œβ”€β”€ useOfflineCache.js         β€” Offline data caching
β”œβ”€β”€ useLocationSearch.js       β€” Location search hook
β”‚
β”œβ”€β”€ wizard/
β”‚   β”œβ”€β”€ Step0TripType.jsx       β€” Friends vs Families selector
β”‚   β”œβ”€β”€ Step1Family.jsx
β”‚   β”œβ”€β”€ Step2Friends.jsx         β€” Friends-mode party setup
β”‚   β”œβ”€β”€ Step2WhereWhen.jsx
β”‚   β”œβ”€β”€ Step3Travel.jsx
β”‚   β”œβ”€β”€ Step4Stay.jsx
β”‚   β”œβ”€β”€ Step5Plan.jsx
β”‚   β”œβ”€β”€ Step6Review.jsx
β”‚   β”œβ”€β”€ TripPreferences.jsx
β”‚   β”œβ”€β”€ WizardHeader.jsx         β€” Step header with back + progress
β”‚   β”œβ”€β”€ WizardButton.jsx         β€” Reusable wizard CTA button
β”‚   β”œβ”€β”€ WizardProgressDots.jsx   β€” Dot-style progress indicator
β”‚   β”œβ”€β”€ useWizardPersistence.js  β€” Auto-save wizard state to localStorage
β”‚   β”œβ”€β”€ PartyModal.jsx           β€” Add/edit party bottom sheet
β”‚   └── ValidationHint.jsx
β”‚
β”œβ”€β”€ utils/
β”‚   └── ageBucketing.js        β€” Age-to-category + demographic summary
β”‚
β”œβ”€β”€ tour/
β”‚   β”œβ”€β”€ TourOverlay.jsx
β”‚   β”œβ”€β”€ DashboardTourSteps.js
β”‚   └── CreateTripTourSteps.js
β”‚
β”œβ”€β”€ landing/
β”‚   β”œβ”€β”€ MountainScene.jsx
β”‚   β”œβ”€β”€ FamilyScene.jsx
β”‚   β”œβ”€β”€ ItineraryScene.jsx
β”‚   └── ShareScene.jsx
β”‚
β”œβ”€β”€ trip/                        β€” Trip page sub-components
β”‚   β”œβ”€β”€ ActivitiesTab.jsx
β”‚   β”œβ”€β”€ PeopleTab.jsx
β”‚   β”œβ”€β”€ AddTravelerModal.jsx
β”‚   β”œβ”€β”€ ConvergenceView.jsx
β”‚   └── PersonCard.jsx
β”‚
β”œβ”€β”€ Shared*                     β€” SharedTrip sub-components
β”‚   β”œβ”€β”€ SharedTripHeader.jsx
β”‚   β”œβ”€β”€ SharedStatsGrid.jsx
β”‚   β”œβ”€β”€ SharedPartyCard.jsx
β”‚   β”œβ”€β”€ SharedTransportCard.jsx
β”‚   β”œβ”€β”€ SharedAccommodationCard.jsx
β”‚   └── SharedActivityRow.jsx
β”‚
└── Timeline*
    └── TimelineAccommodationCard.jsx

State Management Patterns

| Pattern | Where Used | How | |---------|------------|-----| | Server state | Trip data, parties, members, legs | React Query with staleTime: 30-60s | | Local UI state | Modals, active tabs, form fields | useState | | Persisted UI state | Dashboard filter, scroll position | useTabState (sessionStorage) | | Scroll restoration | Dashboard, Shared, Profile | useScrollRestore (in-memory map) | | Offline cache | Trip data, dashboard trips | localStorage via useOfflineCache | | Auth state | Current user | useState + base44.auth.me() | | Language | EN/RU | LanguageContext + localStorage | | Dark mode | Light/Dark | DarkModeContext + localStorage |


7. Backend Architecture

Platform

Built on Base44 β€” a Backend-as-a-Service platform providing:

  • Authentication & user management
  • Entity CRUD with real-time subscriptions
  • File upload & storage
  • Integration SDK (LLM, email, etc.)
  • Backend function hosting (Deno Deploy)

Backend Functions

| Function | Auth | Purpose | Input | Output | |----------|------|---------|-------|--------| | searchLocations | No | Google Places Autocomplete for cities, airports, places | {term, types} | Array of location results | | autocompletePlaces | No | Places autocomplete | {input} | Predictions | | getPlaceDetails | No | Google Place details | {place_id} | Place details with lat/lng | | searchPlaces | No | General places search | {query} | Place results | | getSharedTrip | No* | Fetch trip data by share token | {token} | Full trip + parties + legs + itinerary | | sharePreview | No* | OG meta tags + redirect for share links | GET: ?token=&lang= | HTML with OG tags | | generateSecureToken | Yes | Crypto-secure share token generation | {} | {token} | | getMyInvitedTrips | Yes | Fetch trips user was invited to | {} | {trips: [...]} | | inviteTripUser | Yes | Send trip invitation email | {tripId, email, partyId} | Status | | submitSupportRequest | Yes | Submit support ticket | {name, email, category, message} | {ticket_ref} | | searchConsoleSites | Admin | List verified Google Search Console sites | {} | {sites: [...]} | | searchConsoleQueries | Admin | Fetch top search queries for a site | {siteUrl, days, rowLimit} | {rows: [...]} |

*Uses service role (base44.asServiceRole) since these are public endpoints.

Secrets / Environment Variables

| Secret | Purpose | |--------|---------| | GOOGLE_PLACES_API_KEY | Google Places API for location search |

API Patterns

  • Frontend calls: base44.functions.invoke('functionName', params)
  • Returns Axios response: {data, status, headers}
  • Service role for public endpoints: base44.asServiceRole.entities.*
  • User-scoped calls for authenticated operations: base44.entities.*

8. Design System

Visual Identity

Aesthetic: Inspired by "App in the Air" β€” dark navy boarding-pass-style cards for transport, warm cream backgrounds, card-based layouts, mobile-first.

Typography

| Usage | Font | Weight | Notes | |-------|------|--------|-------| | Body text | DM Sans | 300–700 | All UI text | | Numbers, codes, times | DM Mono | 400–500 | Airport codes, countdown, dates |

Color Palette

Light Mode: | Token | Value | Usage | |-------|-------|-------| | --rompo-bg | #F8F7F4 | Page background (warm cream) | | --rompo-surface | #FFFFFF | Card backgrounds | | --rompo-primary | #410472 | Primary purple | | --rompo-primary-light | #8825F0 | Purple light | | --rompo-accent | #E94560 | Red accent | | --rompo-text | #1A1A2E | Primary text | | --rompo-text-secondary | #6B7280 | Secondary text | | --rompo-border | #E5E7EB | Borders |

Dark Mode: | Token | Value | Usage | |-------|-------|-------| | --rompo-bg | #0F172A | Deep navy background | | --rompo-surface | #1E293B | Card backgrounds | | --rompo-surface-secondary | #1A2332 | Input backgrounds | | --rompo-primary | #A855F7 | Purple primary | | --rompo-primary-light | #C084FC | Purple light | | --rompo-primary-pale | #3B0764 | Dark purple tint | | --rompo-accent | #FB7185 | Pink accent | | --rompo-text | #F1F5F9 | Light text | | --rompo-text-secondary | #94A3B8 | Secondary text | | --rompo-text-muted | #64748B | Muted text | | --rompo-border | #334155 | Borders | | --rompo-border-light | #1E293B | Subtle borders |

Party Colors: Pink (#DB2777), Teal (#0E7490), Coral (#F97316), Green (#10B981), Blue (#3B82F6), Amber (#F59E0B)

Spacing & Radii

| Token | Value | |-------|-------| | Page padding | 20px | | Card radius | 16px | | Large card radius | 20px | | Pill radius | 20px | | Input radius | 12px | | Card padding | 16px 20px | | Card gap | 10px |

Key Component Specs

  • Transport Card: Dark gradient bg, 3px party-color top stripe, DM Mono city codes, red arrow connector, dashed separator
  • Trip Header: Destination photo / purple gradient, 90px decorative circle, 20px bold title, 26px countdown
  • Bottom Nav: Fixed white, 42px center "New Trip" circle, active = purple line icon + bold, inactive = muted
  • Progress Bar: pill stepper: purple filled, mauve upcoming
  • Section Labels: 12px, weight 700, uppercase, 0.8px letter-spacing

9. Internationalization

Implementation

  • Provider: LanguageContext with React Context
  • Storage: localStorage("appLanguage")
  • Languages: English (en), Russian (ru)
  • Translation function: t(key, params) with placeholder support ({minutes}, {partyName})
  • Standalone translator: createTranslator(lang) for non-context pages (SharedTrip)

Coverage

~150 translation keys covering all UI text. All user-facing text goes through the t() function.

Adding a Language

  1. Add translation object in LanguageContext.jsx
  2. Add language button in Dashboard header and Profile settings
  3. Update sharePreview function for OG tag translations

10. Offline & Caching Strategy

Implementation (useOfflineCache.js)

  • Dashboard trips: Cached to localStorage on successful load
  • Individual trip data: Cached when all data (trip, parties, members, legs, itinerary) is loaded
  • Online status: Tracked via useOnlineStatus() hook (browser online/offline events)

Behavior

| State | Dashboard | Trip Page | |-------|-----------|-----------| | Online | Live data from React Query | Live data, cached in background | | Offline | Shows cached trip list | Shows cached trip data | | Returning online | Auto-refreshes (staleTime triggers) | Auto-refreshes |

Limitations

  • No write operations while offline
  • Cache is per-device (localStorage)
  • No conflict resolution for concurrent edits
  • Cache can become stale if not refreshed

11. Security & Access Control

Authentication

  • Handled by Base44 platform (redirectToLogin, auth.me, isAuthenticated)
  • No custom login page β€” uses platform auth flow
  • Sign in with Apple β€” enabled in Base44 dashboard; Hide My Email relay addresses are stored as the user's email
  • Sign in with Google β€” enabled in Base44 dashboard
  • Email/password β€” default login method

Trip Access Model

| Role | View Trip | Edit Trip | Edit Legs | Invite Others | Delete Trip | |------|-----------|-----------|-----------|---------------|-------------| | Owner | βœ… | βœ… | βœ… | βœ… | βœ… | | Invited (accepted) | βœ… | ❌ | Own party only* | ❌ | ❌ | | Share link viewer | Read-only | ❌ | ❌ | ❌ | ❌ | | Not authorized | ❌ | ❌ | ❌ | ❌ | ❌ |

*Only when allow_party_editing is enabled by the owner.

Share Links

  • Tokenized access (random string + timestamp)
  • Can be deactivated (is_active: false)
  • Backend function uses service role to bypass auth for public access
  • No write operations through share links

Row-Level Security (RLS)

  • Applied to 11 entities (v3.1): Activity, Expense, InvitedTripUser, ItineraryItem, Leg, LegAssignment, Member, ShareLink, SupportRequest, TravelParty, Trip
  • Standard rule: read/update/delete restricted to created_by_id === user.id OR user.role === "admin"
  • InvitedTripUser exception: also allows read/update when invited_email === user.email (so invitees can see/accept their own invites)
  • SupportRequest exception: update/delete restricted to admin only (users can create and read their own tickets)
  • Create operations: open (no restriction) β€” users can create records for trips they own
  • BookingImport: stricter RLS β€” all operations restricted to created_by_id only (no admin override)
  • RLS is enforced at the database layer by the Base44 platform, independent of frontend checks

Admin Features

  • Admin users can toggle "Admin View" to see all trips
  • Protected by user.role === "admin" check
  • Admin toggle is hidden behind a triple-tap gesture on the user avatar (not visible in normal UI flow)

12. Integrations & APIs

Google Search Console

  • Used in: SearchConsole admin page
  • Connector: Authorized via Base44 OAuth app connector (google_search_console)
  • Scopes: webmasters.readonly, userinfo.email, openid
  • Functions: searchConsoleSites (list verified properties) + searchConsoleQueries (fetch query analytics)
  • Access: Admin-only (role check in both backend functions)
  • Data shown: Queries, clicks, impressions, CTR, average position; filterable by 7 / 28 / 90 days

Google Places API

| Endpoint | Usage | Backend Function | |----------|-------|-----------------| | Autocomplete | City, airport, and place search | searchLocations | | Place Details | Lat/lng, address, IATA codes | searchLocations (inline) | | Place Autocomplete | Accommodation search | autocompletePlaces | | Place Details | Hotel details, photos | getPlaceDetails |

API Key: Stored as GOOGLE_PLACES_API_KEY secret.

Core.InvokeLLM (AI)

  • Used in: Step 5 (AI itinerary generation)
  • Model: Platform default LLM
  • Input: Structured prompt with destination, traveller age groups (bucketed β€” never exact ages or names), preferences
  • Output: JSON schema response with days β†’ items structure
  • Features used: response_json_schema for structured output
  • Privacy: Age bucketing via ageToCategory() converts exact ages to groups (e.g. "2 adults, 1 child") before sending to AI. User must consent via AiConsentModal before first generation. Consent is persisted on user record (ai_consent_given).

Core.SendEmail

  • Used in: Invitation flow
  • Sends: Trip invitation emails with party assignment details

Core.UploadFile

  • Available but not currently used in main flows

13. Analytics & Metrics

Implemented Events (base44.analytics.track)

| Event | Properties | Location | Business Value | |-------|-----------|----------|----------------| | party_added | party_count | Step1Family | Multi-party adoption | | wizard_step1_completed | party_count, total_members, members_with_email | Step1Family | Funnel: party setup completion | | travel_leg_added | total_legs | Step3Travel | Transport planning engagement | | wizard_step3_completed | total_legs, shared_legs, independent_legs, party_count | Step3Travel | Funnel: transport step + shared vs independent ratio | | wizard_step4_completed | total_accommodations, shared_accommodations, party_count | Step4Stay | Funnel: accommodation step + sharing patterns | | itinerary_generated | days_count, total_items, had_adjustment, party_count | Step5Plan | AI adoption + fine-tune engagement | | collaborator_invited | trip_id, has_party | InviteCollaboratorModal | Collaboration adoption | | share_link_copied | trip_id, share_type (full_trip / party_view) | TripShareSection | Viral coefficient + party-specific sharing |

Recommended Additional Events (Not Yet Implemented)

| Event | Properties | Business Value | |-------|-----------|----------------| | trip_created | party_count, member_count, duration_days | Core conversion | | invite_accepted | β€” | Invite conversion | | shared_trip_viewed | β€” | Share link effectiveness | | language_changed | from, to | i18n usage | | dark_mode_toggled | mode | Preference data | | wizard_draft_saved | step_number | Engagement signal |

Key Funnels

  1. Landing β†’ Sign-up β†’ First Trip: User acquisition
  2. Wizard Step 0β†’1β†’2β†’3β†’4β†’5β†’6: Trip creation completion rate (tracked per step)
  3. Trip Created β†’ Shared: Viral loop (share_link_copied)
  4. Invite Sent β†’ Accepted: Collaboration effectiveness (collaborator_invited)
  5. AI Generation β†’ Fine-tune β†’ Save: AI value perception (itinerary_generated with had_adjustment)
  6. Multi-party engagement: party_added β†’ shared_legs ratio β†’ shared_accommodations ratio

14. Distribution & Marketing

App Store Listing

  • Platform: iOS (Apple App Store)
  • Region: United Kingdom (GB) β€” initial market
  • App Store URL: https://apps.apple.com/gb/app/rompo-travel/id6760403260
  • App ID: id6760403260
  • Status: Live β€” public release as of March 2026

Marketing Site (/MarketingLanding)

The public-facing marketing page at /MarketingLanding is accessible without authentication and serves as the primary acquisition channel.

Sections (top to bottom): | Component | Purpose | |-----------|---------| | MarketingNav | Fixed dark nav with Rompo logo + App Store CTA button | | MarketingHero | Full-height dark section with headline, subtext, floating emojis, boarding pass visual, CTA buttons | | DemoSection | Interactive phone mockup with tabbed Transport / Stays / Itinerary demo | | ProblemSection | Problem/solution framing for group travel pain points | | HowItWorks | 3-step explainer (Add families β†’ Plan together β†’ Share) | | DifferentiatorsGrid | Feature grid highlighting multi-party, AI, sharing, offline | | SharePreviewSection | Share link preview demonstration | | FinalCTA | Purple gradient CTA section with App Store button | | MarketingFooter | Links to Privacy + Support, copyright |

All App Store CTAs point to: https://apps.apple.com/gb/app/rompo-travel/id6760403260

TestFlight (Retired)

  • TestFlight beta program has been fully decommissioned
  • TestflightSignup component renders null (preserved as no-op to avoid import errors)
  • TestflightSignup entity is retained in the database schema but no longer used
  • All "early access" and "claim your spot" copy has been removed from all marketing components

Auth Flow for Marketing Visitors

  • Marketing page is public (no auth required)
  • Authenticated users visiting /MarketingLanding are automatically redirected to /Dashboard
  • A ?preview=1 URL param bypasses the redirect (for internal review)

15. Known Limitations & Tech Debt

Technical Debt

  1. Inline styles everywhere β€” Should migrate to Tailwind utility classes or CSS modules for maintainability
  2. Trip page is ~980 lines β€” Needs breaking into sub-components (OverviewTab, TimelineTab, etc.)
  3. No error boundaries β€” App crashes on unhandled errors
  4. LegAssignment.list() loads all β€” Should filter server-side by trip legs
  5. No pagination β€” Trip lists and member lists load everything
  6. Google Places API calls are not rate-limited β€” Could hit quota with heavy usage
  7. No input validation on backend functions β€” searchLocations trusts all input
  8. ~~Dual CSS files (globals.css + index.css) with divergent tokens~~ β€” Fixed in v1.4

UX Gaps

  1. ~~Activities tab is placeholder~~ β€” Shipped in v1.4
  2. No expense UI despite entity existing
  3. ~~No deep linking for trip tabs~~ β€” Fixed: tab param in URL (?tab=timeline)
  4. No loading states on some delete operations
  5. Wizard doesn't persist across browser refresh (except saved drafts)

Security

  1. ~~Share link tokens are predictable~~ β€” Fixed: uses generateSecureToken backend function
  2. No rate limiting on invite emails
  3. No invite expiration β€” Pending invites live forever

16. Roadmap Opportunities

Near-Term (P1)

  1. ~~Activities Tab~~ β€” βœ… Shipped in v1.4
  2. Expense Tracking β€” Split bills, track spending by category
  3. Real-time Collaboration β€” Use entity subscriptions for live updates
  4. Drag-to-reorder β€” Legs, activities, and itinerary items

Medium-Term (P2)

  1. PDF Export β€” Downloadable trip itinerary as PDF
  2. Maps Integration β€” Leaflet maps showing route, accommodations, activities
  3. Weather Forecast β€” 14-day weather at destination
  4. Budget Dashboard β€” Estimated vs actual spending
  5. Packing Lists β€” Age-aware packing suggestions
  6. Document Storage β€” Upload boarding passes, hotel confirmations

Long-Term (P3)

  1. Native Mobile App β€” React Native or PWA enhancement
  2. Travel Booking Integration β€” Flight/hotel search and booking
  3. Group Chat β€” In-app messaging per trip
  4. Trip Templates β€” Pre-built itineraries for popular destinations
  5. Multi-currency Support β€” Automatic conversion for expenses
  6. Social Features β€” Trip photo sharing, trip diary
  7. Smart Notifications β€” Departure reminders, check-in alerts
  8. API / Zapier Integration β€” Third-party automation

17. Changelog

v3.1 β€” August 2026

Security Hardening & iOS Viewport Optimization

  • Row-Level Security (RLS) applied to 11 entities β€” Activity, Expense, InvitedTripUser, ItineraryItem, Leg, LegAssignment, Member, ShareLink, SupportRequest, TravelParty, and Trip now have owner-or-admin RLS rules on read/update/delete. InvitedTripUser additionally grants read/update to the invited user by email match. SupportRequest restricts update/delete to admin only. Create remains open on all entities (users can create records for trips they own). This prevents cross-user data access at the database layer.
  • iOS safe-area viewport optimization β€” All main page containers (Dashboard, CreateTrip wizard, Landing) now use paddingTop: calc(20px + env(safe-area-inset-top)) to respect the iOS status bar / notch. viewport-fit=cover added to index.html to enable safe-area insets.
  • Text selection enabled β€” Long-form content (paragraphs, headings, lists, articles) now supports user-select: text for copy-paste on mobile, while UI controls remain non-selectable.
  • MobileSelect drawer component β€” Replaced native HTML <select> dropdowns in Step1Family (age category picker) and Step5Plan with touch-friendly bottom-sheet MobileSelect components for better mobile UX.
  • MasterDoc bumped to v3.1.

v3.0 β€” June 2026

Trip Pro Paywall System

  • Trip Pro model β€” Introduced trip.trip_pro boolean flag on the Trip entity. When true, AI itinerary generation, multi-family support (>2 parties), PDF export, and dynamic OG images are unlocked for that trip.
  • PaywallModal β€” New src/components/paywall/PaywallModal.jsx component using shadcn Dialog. Displays 4 feature bullets (AI-powered daily plan, up to 6 families, beautiful share previews, printable PDF), a primary teal gradient CTA button ("Unlock for $14.99"), a "Maybe later" dismiss, and a 7-day money-back guarantee footer.
  • Step5Plan gating β€” "Generate Itinerary ✨" in Step 5 now checks trip.trip_pro before invoking the LLM. If false, PaywallModal opens instead of starting AI generation.
  • Price variants β€” Trip entity now stores price_variant (A=$9.99, B=$14.99, C=$19.99) assigned deterministically via hash(trip_id) % 3 at paywall_viewed for future A/B testing.
  • Additional Trip fields β€” pro_purchased_at (UTC datetime for 7-day refund window), pro_stripe_session_id (Stripe cs_... for idempotency), requires_pro (client-set flag when β‰₯3 parties added).
  • Stripe integration β€” Checkout flow is a stub (toast placeholder); full Stripe webhook backend is the next step.
  • MasterDoc β€” Bumped to v3.0.

v0.9 β€” June 2026

Logo Integration & Collaboration Features Shipped

  • Branding β€” Replaced placeholder airplane emoji (✈️) on splash/loading screens with the new Rompo.Travel circular compass rose logo (blue-to-orange gradient). Updated both PageLoader and auth-state loading screens in App.jsx.
  • Inline Leg Editing β€” Transport leg cards on Timeline tab are now tappable by trip owners and invited editors (when "allow_party_editing" is enabled). Tap any flight/transfer to edit inline with the full TransportLegEditModal.
  • Add Travel Leg Button β€” "Add Travel Leg" dashed button on Timeline tab allows owners and allowed editors to create new transport and accommodation legs mid-trip.
  • Smart Timeline Ordering β€” Independent party legs are automatically sorted before or after shared legs based on start_time. When both types exist on the same day, an "everyone meets up" divider is rendered between them.
  • Trip Header Inline Edit β€” Trip owners can tap the trip header card (gradient teal background) to edit trip title, destination, emoji, and dates via TripHeaderEditModal.
  • Collaboration Refinements β€” Fixed invite expiry validation, auto-accept logic, and permission scoping for party-specific leg editing.
  • Offline Cache β€” Trip data (legs, accommodations, parties, members, itinerary) fully cached to localStorage when offline; Dashboard trip list also cached with last-synced timestamp.
  • Pull-to-Refresh β€” Gesture support on both Dashboard and Trip pages to manually refresh live data when online.
  • Release Notes document β€” First formal release notes published for v0.9, documenting what changed and what to test.
  • MasterDoc β€” Updated changelog entry with v0.9 feature summary.

v2.0 β€” May 2026

Country Field Fix & Backend Reliability

  • Bug fix: country auto-fill in Where & When wizard β€” The "Country" field was not populating correctly when a destination was selected. Root cause: the searchLocations function was extracting country_name by string-parsing the Places Autocomplete description (e.g. splitting on ", "), which is fragile and locale-dependent. Fixed by calling the Google Places Details API for each city result to extract country_name from the authoritative address_components array instead.
  • MasterDoc bumped to v2.0.

v1.9 β€” April 2026

Auto-Save on Step Navigation & UX Cleanup

  • Auto-save on step advance (edit mode) β€” In edit mode (?edit=tripId), the wizard now automatically saves the full trip state to the database every time the user advances to a new step. Previously, data was only persisted when the user reached Step 6 and clicked "Save & Finish", meaning navigating away mid-edit could lose changes.
  • goTo triggers save β€” The goTo(step, dataOverride) function in CreateTrip was updated to call saveTripToDB automatically. Step handlers (handlePeopleDone, handleWhereWhenDone, etc.) now pass their latest state as dataOverride to ensure the most up-to-date data (not a stale closure) is persisted.
  • Auto-saving indicator β€” A subtle "πŸ’Ύ Saving…" label appears below the progress bar during save operations in edit mode, giving the user immediate feedback.
  • "Unsaved changes" dialog removed β€” The BottomNav previously showed a window.confirm() dialog when the user tried to navigate away from an active edit session. With consistent auto-saving now in place, this confirmation is redundant and has been removed for a smoother UX.
  • MasterDoc bumped to v1.9.

v1.8 β€” April 2026

Navigation Stack Fix

  • Root cause β€” After saving an edited trip, CreateTrip navigated to /Trip?id=... without replacing the /CreateTrip entry in the browser history stack. This caused the Back button on the Trip page to return to the wizard editor (instead of Dashboard), and the Trips tab in BottomNav to restore /CreateTrip as the last stack entry.
  • Fix β€” handleComplete in CreateTrip now uses navigate(..., { replace: true }) when in edit mode, replacing /CreateTrip in history so the stack reads /Dashboard β†’ /Trip rather than /Dashboard β†’ /CreateTrip β†’ /Trip.
  • Step 1 back button β€” Both Step1Family and Step2Friends "Back" buttons in edit mode now navigate directly to /Trip?id=... with replace: true (previously called navigate(-1), which could land anywhere in browser history).
  • MasterDoc bumped to v1.8.

v1.7 β€” April 2026

Google Search Console Integration

  • OAuth connector β€” Authorized google_search_console via Base44 app connector (scopes: webmasters.readonly, userinfo.email, openid).
  • searchConsoleSites backend function β€” Admin-only endpoint; fetches list of verified properties via the Google Search Console API using the stored connector access token.
  • searchConsoleQueries backend function β€” Admin-only endpoint; fetches top search queries for a given site URL with configurable date range (7 / 28 / 90 days) and row limit.
  • /SearchConsole page β€” Admin-only analytics dashboard displaying site selector, date range filter, summary metric cards (clicks, impressions, CTR, position), and a ranked query table with per-row performance bars.
  • MasterDoc β€” Updated to v1.7 with new page, backend functions, and connector documented.

v1.6 β€” March 2026

QA Bug Fix Sprint

  • Fix 1 & 2 β€” Wizard Step 1 validation β€” Replaced always-visible ValidationHint on party name in Step1Family with a ValidationHintTouched component that only shows the error after the user has typed and then cleared the party name field. The "Next" button was already correctly gated on tripName.trim() && parties.some(p => p.name.trim()) β€” no origin city, country, or member records required.
  • Fix 3 β€” Clipboard copy fallback β€” Wrapped navigator.clipboard.writeText() in TripShareSection with try/catch and added a textarea + execCommand('copy') fallback for browsers/WebViews where the Clipboard API is restricted (e.g. in-app browsers on iOS).
  • Fix 4 β€” 401 errors β€” Confirmed all data queries on Dashboard are already gated by enabled: !!user. No structural change required; auth state is properly awaited before API calls fire.
  • Fix 5 β€” Dashboard empty state per filter β€” Added per-filter empty state messages ("No upcoming trips", "No active trips", "No past trips") when a filter pill returns zero results, replacing the previously blank area.
  • Fix 6 β€” Dark Mode toggle β€” Confirmed DarkModeToggle is correctly wired to toggleDark from context, has a 48Γ—44px tap target, and uses role="switch" with aria-checked. No change required.
  • MasterDoc version bumped to v1.6.

v1.5 β€” March 2026

Public App Store Launch & Marketing

  • App Store live β€” Rompo is now publicly available on the iOS App Store (UK): https://apps.apple.com/gb/app/rompo-travel/id6760403260
  • TestFlight retired β€” Beta signup flow fully decommissioned. TestflightSignup component renders null; entity retained for data history.
  • All early access copy removed β€” "Claim my spot", "100 spots left", and any beta/TestFlight language scrubbed from all marketing components (MarketingHero, FinalCTA, MarketingNav).
  • All App Store CTAs standardised β€” Every download link across the marketing page (nav, hero, final CTA) points to the production App Store URL.
  • Marketing landing page hardened β€” Auth-redirect logic confirmed: logged-in users auto-redirect to Dashboard; ?preview=1 param bypasses for internal review.
  • New Β§14 Distribution & Marketing added to this document covering App Store listing, marketing site component map, TestFlight retirement, and auth flow for marketing visitors.
  • MasterDoc version bumped to v1.5.

v1.4 β€” March 2026

Design System Unification & UI Polish

  • CSS token sync β€” Unified globals.css and index.css to use identical light-mode (--background: 39 18% 97% / warm cream #F8F7F4) and dark-mode (deep navy #0F172A) HSL tokens. Eliminated token drift between the two files.
  • Dark mode palette enriched β€” Added full set of dark-mode CSS variables: --rompo-surface-secondary, --rompo-primary-pale, --rompo-text-secondary, --rompo-text-muted, --rompo-border, --rompo-border-light, and enhanced party/accent colors for dark contexts.
  • Step0TripType redesigned β€” Trip type selector now uses vibrant full-width gradient cards (teal for Friends, purple for Families) with large icons, decorative circles, and spring bounce animations. Replaced flat button layout.
  • Step1Family fix β€” Resolved duplicate "+" character rendering in the "Add Member" button.
  • People tab shipped β€” New PeopleTab component on Trip page showing party-grouped travelers with add/edit/convergence views.
  • Activities tab shipped β€” ActivitiesTab component rendering AI-generated itinerary with activity management.
  • Trip tab deep linking β€” Tab state now syncs to URL (?tab=timeline) for shareable deep links.
  • Splash screen β€” Loading state uses warm cream background (#F8F7F4) with teal gradient logo, matching the design system.
  • Safari autofill fix β€” Dark-mode autofill inputs now use correct background/text colors via -webkit-autofill overrides.
  • Input focus rings β€” Global purple focus ring (border-color: #410472, box-shadow: 0 0 0 3px rgba(65, 4, 114, 0.12)) applied to all inputs.

v1.3 β€” March 2026

Apple App Store Compliance

  • AI age bucketing β€” New ageToCategory() utility converts exact ages to demographic groups (toddler, child, teen, adult, senior) before sending to LLM. Full names are never sent.
  • AI consent modal β€” AiConsentModal prompts users before first AI itinerary generation. Consent persisted on user record (ai_consent_given). Includes privacy policy link and provider disclosure.
  • Admin toggle hidden β€” Admin view toggle is now behind a triple-tap gesture on the user avatar, satisfying App Store review requirements for production readiness.
  • Sign in with Apple β€” Enabled in Base44 dashboard. Hide My Email relay addresses are supported.
  • Privacy Policy updated β€” Added Β§5 "AI-Generated Content" and Β§6 "Third-Party Login" sections. All subsequent sections renumbered. Table of contents updated.
  • "Beta" label removed from Dashboard header.

v1.2 β€” March 2026

Multi-Party Analytics Tracking

  • Implemented base44.analytics.track() across all multi-party planning touchpoints
  • Step 1 (Family): party_added, wizard_step1_completed (party count, member count, email linkage)
  • Step 3 (Travel): travel_leg_added, wizard_step3_completed (shared vs independent leg ratio)
  • Step 4 (Stay): wizard_step4_completed (shared accommodation patterns)
  • Step 5 (Plan): itinerary_generated (days, items, adjustments, party count)
  • Collaboration: collaborator_invited (trip + party assignment)
  • Sharing: share_link_copied (full trip vs party-specific view)
  • Updated Master Doc to v1.2 with implemented vs recommended event breakdown

v1.1 β€” March 2026

Design System & UI Hardening

  • Fixed all modal/overlay transparency issues β€” modals now use solid opaque backgrounds (#FFFFFF) instead of CSS variable references that could fall through
  • Elevated z-index consistency across all overlay components (SearchBottomSheet, DeleteConfirmModal, AccommodationEditModal, TransportLegEditModal, MobileSelect, InviteCollaboratorModal)
  • Hardcoded backdrop colors to rgba(0,0,0,0.5) for reliable dimming across light and dark modes

Dark Mode

  • Full dark mode support shipped (v1.0 late addition) β€” all CSS variables, card backgrounds, text colors, and borders adapt
  • DarkModeContext provider + DarkModeToggle component added
  • Profile page includes manual dark mode toggle

Collaboration & Sharing

  • Invite Collaborator modal fully functional β€” email input, party assignment, existing invite list with status badges
  • Fixed modal interactivity bugs (z-index, pointer-events, solid backgrounds)
  • "Allow party editing" toggle on Trip page for owners
  • Bug fix: searchLocations now fetches Google Places Details for every city result to extract country_name from address_components instead of string-parsing the autocomplete description β€” ensures the Country field auto-fills correctly when a destination is selected in the Where & When wizard step

MasterDoc

  • Added PDF export (jsPDF) with formatted headings, tables, code blocks, and page footers
  • Fixed text selection (user-select: text) for copy-paste
  • Bumped to v1.1 with this changelog

Trip Cards

  • "View" button now uses teal gradient for better visual affordance
  • "Edit" button uses solid gray fill to distinguish from primary action

v1.0 β€” March 2026 (Initial Release)

  • Multi-party trip creation with 6-step wizard
  • Google Places integration for cities, airports, accommodations
  • Transport & accommodation leg management with party assignment
  • AI-powered itinerary generation (age-aware, preference-based)
  • Share-without-signup via tokenized links with OG meta tags
  • Collaborative editing with email invitations
  • Offline mode with localStorage caching
  • Pull-to-refresh, scroll restoration
  • Bilingual support (English / Russian)
  • Onboarding tour (Dashboard + Wizard)
  • Admin view toggle