Inspiration
I noticed something about how I use social media — I'd spend 4 minutes watching reels about Vietnam, rewatch the same Bali video twice, click into a creator's profile from a Japan post. Then open Skyscanner and search for... London. Because that's what I thought I wanted.
The destination I actually wanted was already written in my scrolling behaviour. I just couldn't read it.
Roam reads it for you.
What It Does
Roam is a Chrome extension that runs silently while you scroll Instagram and TikTok. It detects travel content, measures your genuine engagement with each destination, and builds an Intent Score — a quantified measure of subconscious travel desire.
No forms. No chatbots. No interaction required. Just scroll normally.
When you open Roam, you see:
- Feed — every travel destination detected with live Skyscanner flight prices
- Intent Score — destinations ranked by how much you actually want to go, backed by real behavioural data
- Saved — your personal wishlist with one-tap Skyscanner booking
How We Built It
Signal Detection
A content script watches the DOM on TikTok and Instagram, extracting captions, hashtags, and location tags. These are sent to Gemma 4 (via Google Gemini API) which determines if the content is travel-related and extracts the destination, country, IATA code, and vibe tags.
Intent Scoring Algorithm
The core of Roam is a weighted behavioural scoring engine — pure mathematics, no AI:
Discrete signals:
| Signal | Points |
|---|---|
| Save / bookmark | +35 |
| Share | +30 |
| Profile click | +30 |
| Rewatch | +25 |
| Like / Hashtag click | +20 |
| Scroll back | +18 |
| Comment open | +15 |
| Sound on | +12 |
| Caption expand | +10 |
| Video pause | +8 |
Non-linear dwell time — attention compounds:
| Time on Post | Points per Second |
|---|---|
| 0 – 5 seconds | 0.5 / sec |
| 5 – 15 seconds | 0.75 / sec |
| 15 – 30 seconds | 1.0 / sec |
| 30+ seconds | 1.5 / sec |
Time decay — recent engagement matters more. Engagement from 3 weeks ago counts less than today. Score halves every 7 days:
score = raw × 0.5^(age / 7days)
Multi-post bonus — seeing the same destination across multiple creators adds +10 per unique post, rewarding cross-creator consistency over a single viral post.
Flight Prices
Live Skyscanner API — every detected destination shows the cheapest available flight from your home airport, with airline, duration, and a direct booking deeplink.
Backend + Database
Express.js backend deployed on Railway proxies all API calls — users install and go, zero configuration required. MongoDB Atlas stores engagement events and intent scores across sessions. Atlas Charts provides a live analytics dashboard showing intent trends in real time.
Natural Language Summary
Gemma 4 synthesises your top scores into a human-readable travel insight — like a travel advisor who watched you scroll.
Challenges We Ran Into
TikTok DOM instability — TikTok's DOM mutates aggressively as you scroll. Reliable caption extraction required careful MutationObserver targeting and aggressive debouncing to avoid duplicate detections and API rate limits.
Gemini rate limits — hit 5 RPM on the free tier early on. Solved with an in-memory post ID cache (never call the API twice for the same post) and a request queue with enforced minimum intervals between calls.
Signal detection without native APIs — detecting saves, shares, and profile clicks required mapping Instagram and TikTok's obfuscated DOM event targets to meaningful engagement actions. No official API — pure DOM observation.
Building solo in 36 hours — every architectural decision had to prioritise demo reliability above all else. A working demo beats a half-finished feature every time.
Accomplishments That We're Proud Of
- A fully working product with live API integrations shipped solo in 36 hours
- A mathematically defensible intent scoring algorithm with full transparency — users see exactly why each destination is ranked
- Zero friction UX — the extension never interrupts your scrolling, never asks you anything, never opens a tab
- Real behavioural signal detection across 11 distinct engagement types without any native platform API access
- A natural language summary that tells you something true about yourself that you didn't already know
What We Learned
Revealed preference is a fundamentally more honest signal than stated preference. People don't know what they want until you show them what they've already chosen.
The best product insights come from watching what people do, not asking what they want. Skyscanner has lagging indicators — search data after decisions are made. Roam captures leading indicators — desire before it becomes a decision.
What's Next for Roam
- iOS and Android app — a native mobile app that replicates the exact passive detection experience of the extension — running silently in the background while you scroll TikTok and Instagram mobile, capturing the same 11 engagement signals, building your Intent Score without any interaction required
- Dynamic Island integration — real-time flight price alerts surfaced on iPhone without opening the app
- Expanded platform support — YouTube Shorts, Pinterest, and Twitter/X travel content detection
- Collaborative wishlists — share your Intent Score profile with travel companions to find destinations you both subconsciously want
- Airline points integration — surface estimated reward points alongside cash prices for frequent flyers
Built With
- api
- express.js
- gemma-4
- mongodb-atlas
- skyscanner
- typescript

Log in or sign up for Devpost to join the conversation.