# Interview: Tripline (Group Travel Itinerary Planner)

**Role:** Intermediate Developer (3–4 yr Android → Web)
**Mockup:** `travel-mockup.html`
**Duration:** ~60 min

---

## Setup (5 min)

Show mockup. Say:

> "This is a group travel planner. A group of travelers builds a day-by-day itinerary together — flights, hotels, activities, meals — with shared budget tracking, voting for group decisions, and an AI trip builder. Build this as a web application. Let's talk through the design."

---

## Part 1: Sub-system Decomposition (15 min)

> **"How do you break this into sub-systems or services? Draw the architecture."**

### What they should surface:

| Sub-system | Key Responsibility |
|------------|-------------------|
| **Trip Service** | CRUD, date range validation, traveler management, roles (organizer/participant/follower) |
| **Itinerary Engine** | Event CRUD, time conflict detection, drag-reorder, day structure, multi-day operations |
| **Budget Engine** | Per-category spending vs target, per-person split calculation, settlement math, overspend detection |
| **Voting Service** | Poll CRUD, vote recording, tally, expiry enforcement, write-in approval |
| **Invite & Access Service** | Share link generation, guest token management, role enforcement on API calls |
| **AI Trip Builder** | Itinerary generation, day refinement, budget rebalancing — thin orchestrator over LLM |
| **Cache & External Data** | Weather cache (6h TTL), place data (geocoding, hours, photos), exchange rate snapshot |
| **Expense Split Engine** | Equal / proportional / custom split math, per-person summary, settlement reconciliation |

### Push deeper:

> **"The budget engine must handle: event cost in JPY, another traveler paid in USD, and the organizer's budget set in total JPY. Where does currency conversion happen — at input time or at display time?"**

Look for: trade-off awareness. At input time = simpler, risk of stale rate. At display time = accurate but every view needs conversion. Good answer uses exchange rate snapshot (locked at trip creation or at expense time) stored in trip metadata, converted at display.

> **"Time conflict detection — two events scheduled at 10am–12pm and 10:30am–11:30am. That's a conflict for a single traveler. But in a group, some travelers might go to one, some to the other. How does the system handle sub-group splits?"**

Look for: event-level traveler assignment (not just trip-level). Each event has optional "who's attending" subset. Conflict detection is per-person: if all assigned travelers overlap → warning. If disjoint subsets → no conflict.

---

## Part 2: Identify System Challenges (12 min)

> **"Pick two sub-systems. What's the hardest technical challenge in each?"**

### Key challenges to surface:

**Challenge: Real-time itinerary sync**
- Traveler A rearranges Day 3 events while Traveler B votes on a poll and Traveler C adds a cost to Day 1. All must see each other's changes without stale data.
- Not a simple CRDT problem — itinerary has ordering (event position matters), not just key-value merge.
- Good answer: WebSocket push for active sessions. Operational transform or last-write-wins on per-event granularity. Avoid full-itinerary locks.

**Challenge: Budget split complexity**
- Dinner costs ¥15,000. Two travelers ate, two didn't. Equal split doesn't work.
- Proportional split: one person had the expensive set menu, others ordered à la carte. How is proportion determined?
- Real solution (over-specified for interview): allow custom dollar amounts per person. UI: "split equally" (default), "split by percentage," or "split by exact amount per person." Manual assignment is the v1 escape hatch.
- Cumulative: adding split logic after trip starts means recalculating all prior expenses. Candidate should flag this as a data migration risk.

**Challenge: AI itinerary quality + feasibility**
- AI suggests "breakfast in Shinjuku, 9am visit Meiji Shrine, 10:30am Harajuku shopping, 12pm lunch in Shibuya" — geographically feasible.
- But AI might also suggest "9am Tsukiji Fish Market, 10am teamLab Borderless, 11am Senso-ji Temple" — impossible, these are across Tokyo, 90+ min travel each.
- How to validate geographic feasibility without building a routing engine?
- Good answer: estimate travel time between consecutive event locations using distance API + average transit speed. Flag unrealistic hops. Not perfect but catches egregious errors.
- Cost estimation inflation: AI suggests "¥15,000/person" for Sushi Saito — but for 4 people with drinks it's more like ¥20,000+. How to communicate uncertainty?

**Challenge: Guest identity without account**
- Traveler invited via link, marks self as guest. Their votes, expense assignments, and event attendance tied to device/browser.
- Device lost → all their data orphaned. New device → no way to reclaim identity. Trip organizer can't reassign.
- Solutions: guest token persisted (cookie + localStorage), re-invite flow with token recovery, or force account creation. Each trades off friction vs data durability.

**Challenge: Exchange rate at settlement time**
- Trip in JPY, expenses in USD (flight), JPY (hotel), EUR (activity).
- At end of trip, settlement needs single currency. What rate?
- Good answer: use trip's base currency (JPY). Convert all expenses at rate at time of recording (stored as conversion metadata per expense). Settlement is in base currency. Disclose the rate used.

### Push for opinion:

> **"Between real-time itinerary sync and AI generation quality — which is harder to get right in production?"**

Compare: real-time sync is a known hard problem with established patterns (OT/CRDT, WebSocket, conflict resolution). AI generation is stochastic — quality degrades unpredictably, harder to test, no fixed correctness criteria. Strong candidate picks AI generation as harder to *guarantee* but accepts real-time sync is harder to *build*.

---

## Part 3: Coding Agent / AI Best Practices (10 min)

(Same structure as MealPlan + PetCare. Fresh candidate gets standalone. If same candidate as another round, push deeper: "We talked about coding agent practices before. This trip planner has different risk areas — how does your approach change?")

> **"How do you use AI coding tools to build Tripline? Where do they help, where do they hurt specifically for this kind of app?"**

### New angles from Travel Planner:

**Particularly AI-friendly:**
- Generating poll/voting UI with real-time tally bars (repetitive UI code across states: open/closed/tied/won)
- Budget category CRUD with per-person split computation (algorithmic, deterministic, easy to test)
- Itinerary event form with 6 event types × conditional fields (boilerplate-heavy)
- Calendar component with drag-reorder (well-known pattern, AI gets close, human tweaks)

**Particularly dangerous for AI:**
- Currency conversion logic (timezone-naive + rate-fetching = AI writes two bugs in one function)
- Settlement math (edge cases: no-expense traveler, partial payments, settlement graph cycles)
- Real-time sync state management (AI tends toward polling or naive last-write-wins without conflict resolution)
- Guest token security (AI tends to store in localStorage without expiry, CSP, or rotation)
- Travel time estimation between activities (AI assumes coordinates exist and API returns reasonable times — both fail regularly)

### Watch for:

- Candidate names specific AI failure modes for this domain (currency math, travel time feasibility, guest auth)
- Candidate distinguishes between "AI helps with UI" vs "AI helps with logic" and adjusts review depth accordingly
- Candidate understands that AI-generated structured output (itinerary JSON) needs schema validation before rendering — LLM hallucinates fields

---

## Part 4: Building an AI Feature (15 min)

> **"Design the AI Trip Builder feature. User says: 'Plan 7 days in Tokyo for family of 4, budget ¥650k, love food and culture, one picky teen.' Walk through the UX, model, data flow, error handling."**

### UX Layer:

- **Entry:** "Generate Itinerary" button in trip page → opens AI builder with pre-filled form (destination, dates, travelers, budget taken from trip). User can edit before generating.
- **Form fields:** Trip name (pre-filled), interests (multi-select: food/culture/nature/shopping/adventure/relaxation), pace (relaxed/balanced/dense), dietary restrictions, mobility concerns, must-see items (free-text)
- **Or natural language:** single text input for power users. "7 days Tokyo family teens budget 650k food culture" — parsed by LLM, fields extracted for confirmation before generation.
- **Generation states:**
  1. "Analyzing your trip..." (0–2s)
  2. "Finding places and estimating costs..." (2–6s)
  3. "Structuring your days..." (6–10s)
  4. Results stream in: day cards appear one by one as ready
- **Result view:** Each day as a card with events. Day budget shown. "Accept day" / "Regenerate day" / "Edit" per-day actions. "Accept all" at bottom.
- **Interstitial:** Some events have confidence badge: estimated cost (yellow = ±20%), location verified (green = coordinates confirmed), booking link available (blue)
- **Fallbacks:**
  - API timeout → "I can show partial plan — Days 1–4 are ready, Days 5–7 are still generating"
  - No results → "I couldn't build a plan with those constraints. Try adjusting budget or trip duration."
  - Partial constraints impossible → "¥650k for 7 days in Tokyo is tight. Here's the most budget-friendly plan. Want me to focus on free activities?"
  - Hallucinated venue → user reports "this restaurant closed" → flag event, remove from future suggestions for this trip

### System Architecture:

```
┌─────────────────────────────────────────────────┐
│  User Input → Constraint Validator                │
│  (dates realistic? budget feasible? travelers>0?) │
│       ↓                                           │
│  Itinerary Generator (LLM + structured output)    │
│  Prompt: [trip context + constraints + examples]  │
│  Schema: {days: [{date, events: [{type, title,    │
│    description, location, start_time, end_time,    │
│    cost_estimate, currency, tags}]}]}              │
│       ↓                                           │
│  Post-processing Pipeline:                         │
│  1. Geocode each event location → lat/lng         │
│  2. Fetch open hours (where available)            │
│  3. Travel time check: consecutive events         │
│     distance → estimated transit → feasibility    │
│  4. Budget check: total + per-category vs limits  │
│  5. Mark unverified estimates (low confidence)    │
│       ↓                                           │
│  UI Rendering (stream per-day)                     │
│       ↓                                           │
│  User Accept/Edit/Reject → Finalize events         │
└─────────────────────────────────────────────────┘
```

### Key considerations they should surface:

1. **Structured output:** Must force LLM into JSON schema (tool use). Free-text response can't be parsed reliably for structured itinerary.
2. **Travel time post-processing:** Don't trust LLM's travel time estimates. After generation, geocode event locations, call distance matrix API, calculate realistic transit. Flag impossible hops.
3. **Cost estimation accuracy:** LLM is bad at exact costs. Use per-tag multiplier (Tokyo activity = ¥3k–5k typical, meal = ¥1k–3k). Mark estimates with confidence badge. Allow user override on any event cost.
4. **Diversity heuristic:** Prevent same cuisine 3 meals in a row. Check event-type distribution — "you have 5 museums in 3 days, want less culture density?"
5. **Free time buffer:** AI tends to fill every hour. Enforce minimum 1 free buffer block per day (1–2 hours unstructured).
6. **Context retention:** User rejects Day 3 → regenerate Day 3 while preserving Days 1–2, 4–7. AI needs to know what was accepted and why previous attempt was rejected.
7. **Budget rebalancing link:** If AI overshoots budget on Day 1–3, it should proactively suggest cheaper alternatives for later days before generating them.

### Edge case test:

> **"User says 'surprise me' with no budget, no interests, just destination and dates. How does the system behave?"**

Strong: falls back to defaults (moderate pace, balanced interest mix, no budget cap), generates one recommended plan, but makes the constraints explicit in the output card: "I planned for ¥100k/day, mix of culture and food. Adjust budget or interests to refine." The lack of constraints is flagged, not silently accepted.

> **"AI suggests an itinerary. User accepts all. Later discovers two events are 90 minutes apart, not possible in the scheduled time window. Whose fault?"**

Strong: "The system's fault — the travel time post-processing step should have caught this. I'd add a feasibility check that compares event end + travel time vs next event start. If mismatch, flag with suggested fix: 'start Day 3 activity at 11am instead of 9:30am to allow travel.' Also mark it as a known limitation on the confidence dashboard."

---

## Bonus: UI/UX Critique (if time, 5 min)

> **"Look at the mockup. What would you change?"**

### What to look for:

- **Event density:** 8 events on Day 1 is ambitious — does mockup feel realistic? Strong candidate says "this is too dense for a family trip with teens — they'll be exhausted by Day 3"
- **Budget panel vs itinerary panel:** Budget shows transport overspent but there's no inline action to fix it from that panel. Missing "suggest budget fix" CTA.
- **Guest traveler identity:** Mockup shows travelers Haijun/Sara/Ethan/Jamie but no "guest" indicator — subtle UX miss for non-account users
- **Voting UI placement:** Poll is in budget panel's column — unrelated. A group decisions panel is distinct but shares space with AI assistant. Better: dedicated "Decisions" tab or section.
- **Weather awareness placement:** Weather badge on observatory event is nice but there's no weather summary per day header. Missed opportunity.
- **Mobile navigation:** The day tabs row has 8 items + "add day" — massively overflows on mobile. Need horizontal scroll indicator or vertical day picker alternative.
- **Trip completeness indicator:** "80% planned" in trip header — but no indication of what's missing (which days/slots). Progress is vague.
- **Settlement clarity:** "Remaining ¥466,800" vs "¥130,000 budget left" is confusing — remaining budget vs remaining to spend? Labels need disambiguation.
- **Empty states:** First trip with no itinerary — big empty space. Suggested: "Start with AI Builder or add events manually" prompt with sample trip template.

---

## Scoring Rubric

| Area | Minimum (Hire Signal) | Strong (Accelerate Signal) |
|------|----------------------|---------------------------|
| Decomposition | 4+ sub-systems, mentions itinerary + budget + voting as separate | 7+, explains data flow between Trip ↔ Budget ↔ AI, calls out external data cache layer |
| Challenges | 2+ challenges with plausible approach | Real-time sync with event ordering, currency conversion timing, travel time post-validation, guest identity durability |
| Coding Agent | Has used AI tools, reviews output, knows danger zones | Names domain-specific AI failure modes (currency math, travel time, guest auth), tests AI-generated structured itinerary output |
| AI Feature | End-to-end flow with form → generation → accept/regenerate | Post-processing pipeline (geocode + open hours + travel time), budget rebalancing link, confidence badges, diversity heuristic |
| UI/UX Sense | 2+ improvements with rationale | Spots event density problem, voting placement, mobile overflow, settlement label confusion, missing empty states |

---

## Decision Flow

```
Can they design?     → Part 1 & 2  → ≥4 sub-systems + 2 challenges with depth
Can they build?      → Part 4     → full pipeline with post-processing + feasibility checks
Can they use AI?     → Part 3     → risk taxonomy per domain, schema validation awareness
Can they design UX?  → All parts  → do they surface group dynamics, budget clarity, mobile pain points?

Hire if at least 3/4 "minimum" with 1 "strong."
Strong hire if 3+/4 "strong."
```
