Inspiration

Every travel app gives you the same list: "Top 10 things to do in Paris." Ranked by reviews, identical for everyone. But taste is cross-domain — the person who loves Bon Iver, A24 films and Japanese vinyl isn't the person who wants a hop-on-hop-off bus tour. We wanted a day planner that starts from who you are, not from what's popular, and works in your city — not just six pre-seeded destinations.

What Drift does

A 60-second conversational interview (6 questions + adaptive follow-ups) about music, film, brands, dining and pace → Drift routes a full day: coffee → museum → record store → dinner → live music. Every stop carries:

  • WHY it fits you — a cross-domain sentence grounded in your answers
  • Real taste-overlap score — computed from Qloo affinity × your tags
  • Photo, address, Google Maps directions — real venues, not lorem
  • Swap dropdown — don't like museum A? Tap museum B; A drops into the list

How we used Qloo

  • /v2/insights — taste affinity + locality resolution (signal.location.query) scores venues against your interview profile
  • /search — per-category venue pools (7 keyword chains with fallbacks), entity chips for every interview question, free-text entity resolution, AND city geocoding (name → lat,lon via destination search)
  • Region anchoring: the Q1 answer becomes a filter.location anchor on every downstream request — answer "Paris" and Q2's chips, searches and the final route all localize to Paris. Works for any city on earth.
  • Probe-discovered constraints (not in docs): filter.location only accepts bare lat,lon (names → 400) and is a hard geo filter — so it's auto-dropped for culture types (artist+coords → 0 rows) and applied only to place/destination searches.

Challenges

  1. Rate limit resilience. One 429 used to cascade: keyword chains kept firing, pools emptied, the itinerary silently fell back to mock venues — photos vanished. Built a process-wide guard: 250ms request spacing, fail-fast cooldown honoring Retry-After, 10-min TTL caches with in-flight dedup on suggest/search. One 429 now costs a 5-second window, not an outage.
  2. Any input, any country. "Jogja", "Kota Bandung", "Indonesia", 印度尼西亚 — a normalization pipeline (alias tables, admin-prefix stripping, ~120-country detection, LLM resolve with heuristic fallback) feeds Qloo a locality it can actually resolve, and empty pools fall back to world venues instead of a 422 blank screen. The route always renders.
  3. Maps handoff on mobile. window.open + a warm Maps app resumed the previous destination — restaurant cards opened the museum. Fixed with same-tab navigation + POI name/address destinations.

Tech

Next.js 16 (App Router, Turbopack) · TypeScript · Tailwind v4 · Qloo Taste Graph API · LLM background enrichment (positive-only WHY pass) · 100 unit tests (qloo/llm/itinerary suites) · process-local guard & caches.

What's next

  • filter.radius tuning for dense cities, trending chips via /v2/trending
  • Save/share routes, multi-day trips
  • Language-aware normalization beyond aliases

Built With

Share this project:

Updates

Submission history