Wanderboat AI — Explore Nearby Attractions
Purpose
Given an optional destination (city name or "nearby"/no-input → IP-located) and optional vibe filter (outdoors, coffee, late-night, cocktails, etc.), return a ranked list of attractions with name, rating, review count, opening hours, a short AI-generated summary, and (when available) Google-style place metadata. Read-only — never books, never submits a reservation. Wanderboat's homepage redirects to /chat, which is the AI-powered search/discovery surface; this skill drives that surface.
When to Use
- "Show me top attractions in {city}" — generic discovery for any city worldwide.
- "What's good to do nearby?" — IP-geolocated quick-look for the current location.
- Vibe-scoped local discovery: outdoors, coffee, late-night bites, kid-friendly, etc.
- Comparing top attractions between two cities (run twice with different destinations).
- Any flow needing photo-rich attraction cards with embedded user reviews and AI-curated commentary that mainstream Google/Yelp APIs don't surface.
Workflow
Wanderboat is Cloudflare-protected (managed challenge + Turnstile). A bare HTTP fetch of any page below /sitemaps/* or /robots.txt returns the CF challenge HTML — stealth + residential proxy session is mandatory for everything else. The site has no documented public API; the only reliable surface is the JS-rendered /chat interface.
1. Start stealth + residential-proxy session
SID=$(browse cloud sessions create --keep-alive --verified --proxies \
| node -e "let s='';process.stdin.on('data',c=>s+=c).on('end',()=>process.stdout.write(JSON.parse(s).id))")
export BROWSE_SESSION="$SID"
Both --verified and --proxies are required. Without them, the Cloudflare challenge HTML (/cdn-cgi/challenge-platform/) is served instead of the app.
2. Open /chat — the main discovery surface
browse open "https://wanderboat.ai/" --remote # redirects to /chat
browse wait load --remote
browse wait timeout 3000 --remote # Mapbox + Discover panel render progressively
browse snapshot --remote
The chat page has three usable affordances for "explore attractions":
| Affordance | Snapshot ref pattern | Purpose |
|---|---|---|
textbox: Enter your destination (top-left header) | textbox: Enter your destination | Hard-set destination context — placeholder shows your IP-located city (e.g. "Hermiston") |
textbox: input-textarea (center chat box) | textbox: input-textarea | Free-form natural-language query — the canonical surface |
button: Find me a good hike nearby etc. (right-side Discover panel) | button: <prompt-text> <prompt-text> | Pre-baked quick-action seeds, IP-located |
3. Choose the right path
Path A — IP-located "nearby" via quick-action button (fastest, 1 click):
# Snapshot, then click the quick-action whose label matches the vibe.
# Observed quick-actions: "Find me a good hike nearby", "I need a coffee break,
# what's close?", "Take me to the latest events", "I want to get outside today",
# "Find me a cool cocktail spot", "I need places that kids will enjoy".
# Refs are dynamic per snapshot — match by visible label, not by ref number.
browse click "<ref-for-quick-action>" --remote
browse wait timeout 12000 --remote # AI generation takes ~8–12s; the URL flips to /chat/cov_<nanoid>
Path B — Specific city via custom query (most flexible):
# After snapshot of /chat, fill the input-textarea and click send-button.
browse fill "<ref-for-input-textarea>" "Show me top attractions in Paris" --remote
browse wait timeout 1500 --remote
browse click "<ref-for-send-button>" --remote
browse wait timeout 15000 --remote # international cities sometimes take a touch longer
browse fill on input-textarea does NOT auto-press Enter (returns pressedEnter: false) — you must click the send-button (label send-button) separately. The "Search" button next to it (with magnifying-glass icon) triggers the @-mention place-picker instead of submitting; do not click it for free-form queries (see Gotchas).
Path C — Set destination first, then query:
# Use the top-of-page destination textbox to lock context before sending.
browse fill "<ref-for-Enter-your-destination>" "Tokyo" --remote
# Then proceed with Path A or B. The destination textbox persists across queries
# in the same session.
4. Extract attractions from the conversation page
After step 3, URL flips to https://wanderboat.ai/chat/cov_{nanoid} and the layout is:
- Center column: AI commentary paragraph + per-attraction cards in narrative order. Each card has
StaticText: <name>,StaticText: <rating>,StaticText: (<review-count>),StaticText: Open until <time>orClosed, a reviews carousel, an AI summary paragraph mentioning hours and seasonality, and a post-count footer (<N> posts). - Right sidebar
Placespanel — this is the cleanest structured data source. Toggle betweentab: Listandtab: Map. TheListtab exposes onelistitemper attraction with predictable nesting:listitem image: <attraction-name> paragraph → StaticText: <attraction-name> paragraph → StaticText: <rating> (e.g. "4.5") paragraph → StaticText: (<n_reviews>) (e.g. "(248)") StaticText: Open until <HH:MM AM|PM> | Open 24 hours | Closed StaticText: Click for details - Top tabs:
Attractions <N>/Events <N>— switching tabs changes the body content but keeps the same chat URL.
Prefer extracting from the Places sidebar listitems. The center column's text is richer but cards are deeply nested with reviews/videos mixed in, and parsing order is fragile.
To get all results: the sidebar is virtualized — only ~5–6 items render before a Load more boundary. Scroll the sidebar's scrollable, div until the <N> count matches the Attractions <N> tab badge.
5. (Optional) Switch to Map tab for coordinates
browse click "<ref-for-tab: Map>" --remote
browse wait timeout 2000 --remote
browse snapshot --remote
The Map view exposes image: Map marker refs per attraction but does not expose lat/lng in the a11y tree — only DOM-level marker positions. If you need coordinates, click a marker → details panel opens with the address, then geocode externally.
6. Release the session
browse cloud sessions update "$SID" --status REQUEST_RELEASE
Site-Specific Gotchas
- Cloudflare-protected, stealth + proxy mandatory.
browse cloud fetchagainsthttps://wanderboat.ai/(with or without--proxies) returns the_cf_chl_optchallenge HTML. Only--verified --proxiesbrowser sessions clear it.robots.txtandsitemap.xmlare fetchable bare (CDN-cached), but the app HTML is not. /→/chat302 redirect happens on first navigation; don't assume the URL afterbrowse openmatches what you sent. Alwaysbrowse get urlto confirm.- IP-geolocation drives "nearby" defaults. The destination placeholder, the Discover panel cards, and any quick-action labelled "nearby"/"close" use the request's source-IP city, NOT the
Where totextbox's placeholder string. With Browserbase's defaultus-west-2residential proxy, expect Hermiston, OR (a low-population locale — useful for testing but not realistic). To target a specific city, always type the city into the chat textarea (Path B) or set the destination textbox (Path C); do not rely on the proxy IP being where you want. - "Search places" button is a place-picker, not a submit. The button with magnifying-glass icon next to the chat input (label
Search, ref-patternbutton: Search) inserts@into the input and opens a dropdown of nearby Google places (logos + addresses) — it is the@-mentionaffordance, not a query submitter. The actual submit isbutton: send-button(paper-airplane icon). Verified: clickingSearchafter a blank input opened adialogof 10 nearby places (McDonald's, Denny's, etc.) — not what you want for an attractions search. - Quick-action labels are dynamic and personalized. Observed labels in one session:
Find me a good hike nearby,I need a coffee break, what's close?,Take me to the latest events,I want to get outside today,Find me a cool cocktail spot,I need places that kids will enjoy, plus event-specific items like*FREE* Healthy Cooking on a Budget,Babysitting Basics Course (Ages 10-15). Don't pin to a label — match by intent keywords (outside,hike,coffee,cocktail) when matching by string. - Conversations are sticky to the session. Subsequent sends in the same Browserbase session append to the same
/chat/cov_{nanoid}URL — they do NOT create a new conversation. To start a fresh thread,browse open "https://wanderboat.ai/chat" --remoteagain. Multi-query test verified: a Paris query sent after a Hermiston "outside today" quick-action both landed incov_XPPGLGUaWXo86hxkynUxL9with the Paris response appended below. - AI generation delay is variable. Quick-action (cached-prompt) responses: 8–12s. Custom natural-language queries: 10–18s. Cross-region cities (Paris from a US proxy): occasionally up to 20s.
browse wait timeout 15000is a safe default for Path B. - The
Attractions <N>/Events <N>tab badges are the source of truth for result count. The sidebar virtualizes — only the top 5–6 items render until you scroll. Don't assume the visible sidebar list is complete; cross-check against the tab badge. - Map tab exposes markers without names or coordinates in the a11y tree — only the List tab gives you structured attraction data. If you need lat/lng, you'll have to either parse the DOM
data-*attributes viabrowse evalor geocode externally. - Static listicle pages exist but require a slug+nanoid. Sitemaps surface URLs like
https://wanderboat.ai/listicle/{city-slug}/attractions/{nanoid}andhttps://wanderboat.ai/localities/{country}/{slug}/{nanoid}— these are pre-rendered city-attraction pages, indexed for SEO. They're potentially a faster deep-link path if you already know the slug + nanoid for a target city; but there's no documented slug→nanoid lookup endpoint, so for ad-hoc queries the/chatflow is the only practical surface. The sitemap index lists ~5 locality + ~5 listicle shards (locality_1.xmlthroughlocality_5.xml, etc.) — useful for bulk discovery but not for interactive querying. robots.txtdisallows/chat?(with query string),/chat/, and/posts?*— but allows bare/chat. Honor this. Our flow uses/chatand the dynamic/chat/cov_{nanoid}— the latter is what/chat/disallows for crawlers, so don't curl those URLs out-of-band; interact only through the browser session.- No GraphQL/REST endpoints observed in the page snapshot to bypass the UI. A network trace would reveal the backend (
/api/...) but per browse.sh policy, we don't reverse-engineer undocumented private APIs — drive the UI. - "Closed" vs "Open until X" is real-time and timezone-localized. The open-hours strings reflect the moment the AI generated the response, in the target city's local time. Don't cache them — they go stale within hours.
- No login required, no captcha walls past Cloudflare. A single session can run an arbitrary number of queries; only rate-limiting concern is the AI generation throughput on Wanderboat's side.
Expected Output
{
"query": "I want to get outside today",
"destination": "Hermiston, OR (IP-located)",
"conversation_url": "https://wanderboat.ai/chat/cov_XPPGLGUaWXo86hxkynUxL9",
"result_kind": "attractions",
"result_count": 20,
"event_count": 3,
"ai_commentary": "If you want to get outside in Hermiston today, these are the cleanest bets for a little fresh-air glory. It's Thursday morning, and all of these picks fit the outdoor brief nicely—no indoor detours, no drama.",
"attractions": [
{
"name": "Riverfront Park",
"rating": 4.5,
"review_count": 248,
"open_status": "Open until 10:00 PM",
"hours_summary": "6 a.m.–10 p.m.",
"best_seasons": ["spring", "summer", "fall"],
"post_count": 20,
"ai_summary": "Riverfront Park is the easygoing pick for a classic outdoor reset: open lawns, river vibes, and a solid 6 a.m.–10 p.m. window today."
},
{
"name": "Hat Rock State Park",
"rating": 4.5,
"review_count": 274,
"open_status": "Open until 9:00 PM",
"hours_summary": "7 AM–9 PM",
"best_seasons": ["spring", "summer", "fall"],
"post_count": 21,
"ai_summary": "Hat Rock State Park brings the bigger scenery energy, with that state-park feel and a 7 AM–9 PM schedule today."
}
]
}
Alternative outcome shapes:
// City-specific query (Path B), international destination
{
"query": "Show me top attractions in Paris",
"destination": "Paris",
"conversation_url": "https://wanderboat.ai/chat/cov_XPPGLGUaWXo86hxkynUxL9",
"result_kind": "attractions",
"ai_commentary": "Paris is serving the big-ticket classics today — the kind of spots that make your camera roll look slightly smug...",
"attractions": [
{ "name": "Eiffel Tower", "rating": 4.7, "review_count": 136900, "open_status": "Open until 11:00 PM", "post_count": 82, "likes": "6.2M" }
]
}
// Empty / no-results outcome (when AI cannot find direct matches)
{
"query": "find outdoor events today",
"destination": "Hermiston, OR (IP-located)",
"conversation_url": "https://wanderboat.ai/chat/cov_XPPGLGUaWXo86hxkynUxL9",
"result_kind": "events",
"result_count": 0,
"ai_commentary": "I couldn't find any exact outdoor events in Hermiston that match your request... but here are a few nearby outdoor happenings that still fit the fresh-air vibe.",
"fallback_results": [
{ "name": "Yakima Federal LIVE@5 - Summer Concert Series", "starts": "2026-05-28T17:00Z", "ends": "2026-05-28T23:59Z", "city": "Richland" }
]
}