You are browsing as a guest. Sign up (or log in) to start making projects!

Wanderpin

  • 9 Devlogs
  • 40 Total hours

A trip planner built around a 3D globe - drop pins, get a route with distances and country counts. Search a city or click the map to add stops

Ship #1

Wanderpin is a 3D-globe trip planner where the journey is the product, not the spreadsheet. Drop pins on a spinning night-earth, watch your route stitch together, then hit Play and fly the whole trip as a cinematic reel - gliding across the globe for long hops and dropping into real 3D terrain when two stops are close.

The hardest part was making the globe-to-3D handoff feel continuous. Two heavy engines (three.js for the globe, MapLibre for terrain) had to crossfade without a tile-load flash, so I warm the 3D view in the background and only commit once it's actually ready. I also caught the play-through reel re-rendering the entire app - globe included - on every caption tick; moving the caption into its own useSyncExternalStore so only it updates made the fly-through visibly smoother.

I'm proud that it feels like a journey instead of a form: the cinematic reel, ~40k curated places that each carry a vibe and a fun fact, and one-tap sharing as a postcard, a public link, or an embeddable live globe.

To try it: open the live link, search a city or just click the globe to drop pins (or start from a template like India's Golden Triangle), then hit Play. Zoom all the way into a pin to watch it cross into street-level 3D. Built with React 19 + TypeScript, three.js, MapLibre GL, and Vercel serverless.

  • 9 devlogs
  • 40h
Try project → See source code →
Open comments for this post

3h 56m 5s logged

Wanderpin - the first five seconds, final touchups

Everything in this batch is about the moment someone lands: a blank globe is intimidating, so I built a real first-run, made it personal, and fixed a jank I’d been ignoring.

A front door instead of an empty globe

New visitors get a welcome dialog: Plan a trip, or Remember one you took. Either way there are starter templates (a week in Italy, around the world, a California road trip) you can drop in with one tap and start dragging stops around.

Coachmarks that follow the actual UI

A short guided tour spotlights real elements: search, the view toggle, Play. It measures each target’s live bounding rect, re-measures on resize and focus, flips above/below by screen half, and hides itself the moment you focus the search box so it never fights you while typing. Dismissals persist so it doesn’t nag on return visits.

Where it stands

Build’s green, all staged, not yet committed. Next: watch real first sessions, do people tap through a template or skip straight to search?

Wanderpin - the first five seconds, final touchups

Everything in this batch is about the moment someone lands: a blank globe is intimidating, so I built a real first-run, made it personal, and fixed a jank I’d been ignoring.

A front door instead of an empty globe

New visitors get a welcome dialog: Plan a trip, or Remember one you took. Either way there are starter templates (a week in Italy, around the world, a California road trip) you can drop in with one tap and start dragging stops around.

Coachmarks that follow the actual UI

A short guided tour spotlights real elements: search, the view toggle, Play. It measures each target’s live bounding rect, re-measures on resize and focus, flips above/below by screen half, and hides itself the moment you focus the search box so it never fights you while typing. Dismissals persist so it doesn’t nag on return visits.

Where it stands

Build’s green, all staged, not yet committed. Next: watch real first sessions, do people tap through a template or skip straight to search?

Replying to @darshjain

0
1
Open comments for this post

4h 1m 2s logged

Wanderpin - getting routes to leave the ground

Live: https://wanderpin-ecru.vercel.app/

One update, mostly one stubborn visual I’d twice given up on: real lifted route arcs on the 3D map.

Arcs that finally hug the globe

deck.gl’s ArcLayer drifts on a MapLibre globe (it only knows Web Mercator), and my earlier hand-rolled layer compiled, ran, threw zero errors, and painted nothing. The fix came from reading MapLibre’s own shaders: inject its projection prelude and call projectTileFor3D(pos, elevation).

The thing I’d missed every time - elevation is in meters above the sphere, fed through five per-frame uniforms, not a raw matrix. Then the polish fights: a z-fight speckle (fixed by not writing depth), a 50 km minimum lift that made short hops launch like fireworks, and a fat vertical wall at city zoom (now fades out past ~zoom 10).

An optional day timeline

New “Days” view in the trip panel. Weekend trip? You’ll never see it. Month-long? Hit “Organize into days” and stops group into collapsible days you can split, reorder, fit the globe to, or play one at a time. A day is a contiguous slice of the route, so “move to Day 3” repositions the stop and re-normalizes - the route and itinerary stay honest. Days travel on share links too.

Where it stands

Live at site, (Also squashed a deploy bug: one .tsx API route made Vercel type-check the whole api/ folder with no tsconfig - a tiny api/tsconfig.json fixed it.)

Wanderpin - getting routes to leave the ground

Live: https://wanderpin-ecru.vercel.app/

One update, mostly one stubborn visual I’d twice given up on: real lifted route arcs on the 3D map.

Arcs that finally hug the globe

deck.gl’s ArcLayer drifts on a MapLibre globe (it only knows Web Mercator), and my earlier hand-rolled layer compiled, ran, threw zero errors, and painted nothing. The fix came from reading MapLibre’s own shaders: inject its projection prelude and call projectTileFor3D(pos, elevation).

The thing I’d missed every time - elevation is in meters above the sphere, fed through five per-frame uniforms, not a raw matrix. Then the polish fights: a z-fight speckle (fixed by not writing depth), a 50 km minimum lift that made short hops launch like fireworks, and a fat vertical wall at city zoom (now fades out past ~zoom 10).

An optional day timeline

New “Days” view in the trip panel. Weekend trip? You’ll never see it. Month-long? Hit “Organize into days” and stops group into collapsible days you can split, reorder, fit the globe to, or play one at a time. A day is a contiguous slice of the route, so “move to Day 3” repositions the stop and re-normalizes - the route and itinerary stay honest. Days travel on share links too.

Where it stands

Live at site, (Also squashed a deploy bug: one .tsx API route made Vercel type-check the whole api/ folder with no tsconfig - a tiny api/tsconfig.json fixed it.)

Replying to @darshjain

0
3
Open comments for this post

5h 0m 49s logged

Wanderpin - the globe looked dumb on a 20 km hop, so I taught it to zoom

This batch turns a Wanderpin trip from a thing on your screen into a thing you can send to a friend - with a real link preview, an embeddable globe, and a reel that finally looks good on short hops.

Share a journey, for real

Hit Share and you get a public link (/t/slug) in a box, plus Copy, the native share sheet, and WhatsApp / Instagram / X buttons. The interesting part is what happens when someone opens that link:

  • /t/:slug is server-rendered (api/share.ts) and serves a dynamically generated Open Graph image (api/og.tsx via @vercel/og) - so pasting a Wanderpin link into a chat unfurls into a proper preview card instead of a blank rectangle.
  • There’s an embeddable globe too: /embed/:slug renders just the spinning globe (a tiny route check in main.tsx swaps the whole app for EmbedView), and the share dialog hands you the <iframe> snippet.
  • Shared trips auto-expire after 7 days via a pg_cron job, so the table stays small and old links quietly die.

The reel got smarter - 3D for the short hops

The globe fly-through looks flat when two stops are 20 km apart - the arc is a stub and the camera barely moves. So now the Play reel checks each leg: anything under 200 km crosses into the 3D map (terrain + buildings) with a zoom picked from the distance, longer legs stay as globe arcs. It asks once before playing, and video recording stays globe-only so captures never go blank.

What bit me

  • Instagram has no web “share a link” intent (unlike WhatsApp/X). So the IG button copies the link and opens Instagram - the native share sheet handles it properly on phones.
  • The slug kept vanishing from the URL. A shared trip was calling replaceState("/") the instant it loaded, so /t/slug disappeared mid-playback and you couldn’t re-share what you were watching. Moved that reset onto the “Create yourslongs.
  • The reel switch reused the globe↔3D handoff plumbing, and the type-checker caught a flyTo signature mismatch before it shipped - the map handle wants { zoom }, not a bare number.

Where it stands

It all builds clean, Try it: https://wanderpin-ecru.vercel.app/

Wanderpin - the globe looked dumb on a 20 km hop, so I taught it to zoom

This batch turns a Wanderpin trip from a thing on your screen into a thing you can send to a friend - with a real link preview, an embeddable globe, and a reel that finally looks good on short hops.

Share a journey, for real

Hit Share and you get a public link (/t/slug) in a box, plus Copy, the native share sheet, and WhatsApp / Instagram / X buttons. The interesting part is what happens when someone opens that link:

  • /t/:slug is server-rendered (api/share.ts) and serves a dynamically generated Open Graph image (api/og.tsx via @vercel/og) - so pasting a Wanderpin link into a chat unfurls into a proper preview card instead of a blank rectangle.
  • There’s an embeddable globe too: /embed/:slug renders just the spinning globe (a tiny route check in main.tsx swaps the whole app for EmbedView), and the share dialog hands you the <iframe> snippet.
  • Shared trips auto-expire after 7 days via a pg_cron job, so the table stays small and old links quietly die.

The reel got smarter - 3D for the short hops

The globe fly-through looks flat when two stops are 20 km apart - the arc is a stub and the camera barely moves. So now the Play reel checks each leg: anything under 200 km crosses into the 3D map (terrain + buildings) with a zoom picked from the distance, longer legs stay as globe arcs. It asks once before playing, and video recording stays globe-only so captures never go blank.

What bit me

  • Instagram has no web “share a link” intent (unlike WhatsApp/X). So the IG button copies the link and opens Instagram - the native share sheet handles it properly on phones.
  • The slug kept vanishing from the URL. A shared trip was calling replaceState("/") the instant it loaded, so /t/slug disappeared mid-playback and you couldn’t re-share what you were watching. Moved that reset onto the “Create yourslongs.
  • The reel switch reused the globe↔3D handoff plumbing, and the type-checker caught a flyTo signature mismatch before it shipped - the map handle wants { zoom }, not a bare number.

Where it stands

It all builds clean, Try it: https://wanderpin-ecru.vercel.app/

Replying to @darshjain

0
1
Open comments for this post

6h 9m 57s logged

Wanderpin - zoom into the world

Two big things landed this week: the map went from 26 hand-picked places to ~40,000, and zooming into the globe now drops you into a real 3D city.

From 26 places to 40,000 - and they all have a vibe

Wanderpin used to know about 26 famous spots. Now it knows ~40k: cities, towns, UNESCO sites, landmarks, and the world’s most-visited attractions - each tagged with a one-word vibe (Coastal, Alpine, Arid, Heritage, Sacred, Volcanic…).

The fun part is the vibes aren’t hand-typed. They’re derived at build time from real data: a Köppen climate raster (so Cairo reads “Arid” and Athens “Mediterranean”), distance to an actual coastline for “Coastal”, GeoNames elevation/feature codes for peaks and castles, and Wikidata’s annual-visitor numbers to rank “most visited”. Facts come from Wikipedia and UNESCO descriptions. Search is now instant and offline - type “Firenze” and Florence shows up.

The fun part: zoom in and the globe becomes a city

The home view is a space globe (three.js). The close-up is a different engine entirely - maplibre with 3D terrain and buildings. I wired up a level-of-detail handoff between them: zoom into a pin and it crosses from globe to 3D automatically, and zoom back out and it returns to the globe.

The trick to making it not feel janky: when you start zooming in, it quietly mounts the 3D map hidden and lets it pull tiles in the background. Only once the tiles are warm does it crossfade. No blank loading flash.

What broke (twice)

  1. It hung forever in preload. The crossfade waited on maplibre’s idle event to know tiles were ready - but that event sometimes never fires. The globe just kept zooming into black. Fix: commit after a 2.2s fallback even if idle is silent.
  2. The way back never worked. Zooming out in 3D wouldn’t return to the globe. Turned out map.on("zoom") captured the callback once at mount - back when the view was still “globe” - so its if (view !== "3d") return guard killed every event forever. Fix: call the latest callback through a ref.

Both are real bugs that would’ve bitten actual users on slow connections, not just test artifacts.

Where it stands

Globe -> 3D -> globe round-trips cleanly on both laptop and mobile, with zero console errors. Try it: https://wanderpin-ecru.vercel.app/

Wanderpin - zoom into the world

Two big things landed this week: the map went from 26 hand-picked places to ~40,000, and zooming into the globe now drops you into a real 3D city.

From 26 places to 40,000 - and they all have a vibe

Wanderpin used to know about 26 famous spots. Now it knows ~40k: cities, towns, UNESCO sites, landmarks, and the world’s most-visited attractions - each tagged with a one-word vibe (Coastal, Alpine, Arid, Heritage, Sacred, Volcanic…).

The fun part is the vibes aren’t hand-typed. They’re derived at build time from real data: a Köppen climate raster (so Cairo reads “Arid” and Athens “Mediterranean”), distance to an actual coastline for “Coastal”, GeoNames elevation/feature codes for peaks and castles, and Wikidata’s annual-visitor numbers to rank “most visited”. Facts come from Wikipedia and UNESCO descriptions. Search is now instant and offline - type “Firenze” and Florence shows up.

The fun part: zoom in and the globe becomes a city

The home view is a space globe (three.js). The close-up is a different engine entirely - maplibre with 3D terrain and buildings. I wired up a level-of-detail handoff between them: zoom into a pin and it crosses from globe to 3D automatically, and zoom back out and it returns to the globe.

The trick to making it not feel janky: when you start zooming in, it quietly mounts the 3D map hidden and lets it pull tiles in the background. Only once the tiles are warm does it crossfade. No blank loading flash.

What broke (twice)

  1. It hung forever in preload. The crossfade waited on maplibre’s idle event to know tiles were ready - but that event sometimes never fires. The globe just kept zooming into black. Fix: commit after a 2.2s fallback even if idle is silent.
  2. The way back never worked. Zooming out in 3D wouldn’t return to the globe. Turned out map.on("zoom") captured the callback once at mount - back when the view was still “globe” - so its if (view !== "3d") return guard killed every event forever. Fix: call the latest callback through a ref.

Both are real bugs that would’ve bitten actual users on slow connections, not just test artifacts.

Where it stands

Globe -> 3D -> globe round-trips cleanly on both laptop and mobile, with zero console errors. Try it: https://wanderpin-ecru.vercel.app/

Replying to @darshjain

0
1
Open comments for this post

3h 18m 50s logged

Wanderpin - Blog 5 - Update press play, watch your trip turn into a movie

Live: https://wanderpin-ecru.vercel.app/

You drop a few pins on a globe and hit Play - and instead of a checklist, you get a cinematic fly-through you can actually share. This update was about chasing one idea until the app felt alive: the journey is the hero, the logistics hide in a drawer.

The payoff

Play used to just stop. Now it lands: the camera pulls back to frame the route, the arcs light up, and a date-stamped card counts up your distance, stops, countries and time. A little classifier scores the trip and picks the camera - a city hop zooms in, a round-the-world trip shows the marble. You also pick how you travel each leg (walk/train/flight…), which bends both the arc shape and the trip’s duration.

Then three swings: export the fly-through as a video (recorded straight off the globe canvas, no server), “been there” pins that glow gold once visited, and a living globe - a warm daylight terminator plus each stop’s local time and current weather.

What broke

Geocode 500’d in prod, every call. Not a geocoding bug at all: type: "module" means Vercel runs the API as native ESM, and Node demands file extensions on imports. from "./_nominatim" crashed at load. One .js fixed it.

The terminator looked gloomy. Darkening the night side just made an already-night map muddy. I flipped it - glow the sunlit side instead - and it finally read as “half the globe is lit.”

Two suns. Every clear-sky stop showed ☀️ 06:28 · ☀️ 15° - my day marker next to the weather glyph.

ngl used AI to build this image 😛

Wanderpin - Blog 5 - Update press play, watch your trip turn into a movie

Live: https://wanderpin-ecru.vercel.app/

You drop a few pins on a globe and hit Play - and instead of a checklist, you get a cinematic fly-through you can actually share. This update was about chasing one idea until the app felt alive: the journey is the hero, the logistics hide in a drawer.

The payoff

Play used to just stop. Now it lands: the camera pulls back to frame the route, the arcs light up, and a date-stamped card counts up your distance, stops, countries and time. A little classifier scores the trip and picks the camera - a city hop zooms in, a round-the-world trip shows the marble. You also pick how you travel each leg (walk/train/flight…), which bends both the arc shape and the trip’s duration.

Then three swings: export the fly-through as a video (recorded straight off the globe canvas, no server), “been there” pins that glow gold once visited, and a living globe - a warm daylight terminator plus each stop’s local time and current weather.

What broke

Geocode 500’d in prod, every call. Not a geocoding bug at all: type: "module" means Vercel runs the API as native ESM, and Node demands file extensions on imports. from "./_nominatim" crashed at load. One .js fixed it.

The terminator looked gloomy. Darkening the night side just made an already-night map muddy. I flipped it - glow the sunlit side instead - and it finally read as “half the globe is lit.”

Two suns. Every clear-sky stop showed ☀️ 06:28 · ☀️ 15° - my day marker next to the weather glyph.

ngl used AI to build this image 😛

Replying to @darshjain

0
16
Open comments for this post

4h 33m 56s logged

Wanderpin - I deleted the spreadsheet

You open the app or you can :) (check it out - https://wanderpin-ecru.vercel.app/ ). A night-side Earth, city lights glowing, a slow spin. You drop a pin in Paris. Another in Tokyo. The arc draws across the globe, and right next to all of that, a panel quietly tells you your dream weighs 2.2 tonnes of CO₂.

That panel was killing the magic. This phase was about fixing it.

The shift

I stopped showing the numbers on the dream surface. Same numbers, just hidden one click deep behind a “Trip details” disclosure. In their place: one warm line that grows with the trip - “4 stops · 4 countries · An adventure taking shape.” You build a journey. The app reacts like it’s excited about it.

Surprise me, the most fun thing the app could do, was buried under a dice icon. It’s the front door now: Take me somewhere. The empty state stopped being homework - “Your map’s a blank canvas, click to start” - and became an invitation: “Where are you dreaming of?”

Drop your very first pin and the app whispers back: “Your journey begins in Santorini ✨”. Hover over a stop and a small card appears: “Why go - its iconic caldera is the rim of a colossal volcanic eruption.” Hit Play and the screen goes cinematic. Full-screen overlay, place name, vibe, progress dots, the route lighting up beneath.

The trip used to be a spreadsheet. Now it’s a memory you haven’t made yet.

The mobile catch

Almost shipped a bug that would’ve made this look broken. On a phone, the empty-state “Take me somewhere” lives inside a bottom sheet. Tap it, and the surprise card was rendering behind the still-open sheet. To the user, nothing happened. To me, a testing pass on an iPhone-shaped viewport caught it the morning of. One-line fix. The kind that disappears in the diff but would have left every mobile user thinking the button was broken.

Where it stands

Empty state, surprise card, first pin, the reel - all warm now. The numbers are still there for the planners, behind one small toggle. The dreamers don’t see them at all.

When Play ends, the camera pulls back, the whole route lights up, and the same numbers I just buried come surging back as a celebration - “You crossed 4 countries. Today, that’s a journey.” Same data, different feeling. The closing frame becomes a postcard you can share.

The whole phase is one belief: people don’t open a travel app because they want to know how many kilometres a trip is. They open it because they want, for a minute, to imagine going somewhere. So show them the somewhere.

Wanderpin - I deleted the spreadsheet

You open the app or you can :) (check it out - https://wanderpin-ecru.vercel.app/ ). A night-side Earth, city lights glowing, a slow spin. You drop a pin in Paris. Another in Tokyo. The arc draws across the globe, and right next to all of that, a panel quietly tells you your dream weighs 2.2 tonnes of CO₂.

That panel was killing the magic. This phase was about fixing it.

The shift

I stopped showing the numbers on the dream surface. Same numbers, just hidden one click deep behind a “Trip details” disclosure. In their place: one warm line that grows with the trip - “4 stops · 4 countries · An adventure taking shape.” You build a journey. The app reacts like it’s excited about it.

Surprise me, the most fun thing the app could do, was buried under a dice icon. It’s the front door now: Take me somewhere. The empty state stopped being homework - “Your map’s a blank canvas, click to start” - and became an invitation: “Where are you dreaming of?”

Drop your very first pin and the app whispers back: “Your journey begins in Santorini ✨”. Hover over a stop and a small card appears: “Why go - its iconic caldera is the rim of a colossal volcanic eruption.” Hit Play and the screen goes cinematic. Full-screen overlay, place name, vibe, progress dots, the route lighting up beneath.

The trip used to be a spreadsheet. Now it’s a memory you haven’t made yet.

The mobile catch

Almost shipped a bug that would’ve made this look broken. On a phone, the empty-state “Take me somewhere” lives inside a bottom sheet. Tap it, and the surprise card was rendering behind the still-open sheet. To the user, nothing happened. To me, a testing pass on an iPhone-shaped viewport caught it the morning of. One-line fix. The kind that disappears in the diff but would have left every mobile user thinking the button was broken.

Where it stands

Empty state, surprise card, first pin, the reel - all warm now. The numbers are still there for the planners, behind one small toggle. The dreamers don’t see them at all.

When Play ends, the camera pulls back, the whole route lights up, and the same numbers I just buried come surging back as a celebration - “You crossed 4 countries. Today, that’s a journey.” Same data, different feeling. The closing frame becomes a postcard you can share.

The whole phase is one belief: people don’t open a travel app because they want to know how many kilometres a trip is. They open it because they want, for a minute, to imagine going somewhere. So show them the somewhere.

Replying to @darshjain

0
12
Open comments for this post

5h 20m 45s logged

Wanderpin - phase 3: real sharing, and the bug that ate an afternoon

This update gave Wanderpin proper short links, a saved-trips library, and a route optimizer. But the part I’ll remember is a 100 KB mystery.

Short links + a trip library

Sharing used to cram the whole trip into a giant #... URL. Now there’s a tiny Supabase backend: hit Share and you get a clean …/t/aB3xY9 link that anyone can open, no login. Reads come straight from the browser (a public read policy), and writes go through a serverless function with the secret key, so nobody can scribble on the database from the client. When someone opens a shared link, the route flies stop to stop and a little “Make your own” card invites them to start their own.

Click polish

Spinning the globe was dropping stray pins, because react-globe.gl fires a click even at the end of a drag. Added a pointer-distance guard (under ~5px = a real click). Clicking open ocean now offers an “Add anyway” instead of a useless pin, and there’s an “Optimize route” button that reorders stops with nearest-neighbour + 2-opt to cut total distance.

The bug: a 5-stop trip that was 400 KB

Share kept failing in the browser with a 413 (payload too large). But the function worked fine when I hit it with curl. Same 5-stop trip, totally different size.

I had the user dump their saved trip in the console. Five stops. 403,682 characters. Each stop had two mystery keys: __threeObjPoint and __threeObjLabel, ~100 KB each.

Turns out react-globe.gl mutates the data objects you hand it - it bolts the entire Three.js render object (meshes, geometry, materials) straight onto your data. I was passing my live trip array to the globe, so it was quietly fattening every stop by 100 KB, which then got saved to localStorage and sent on publish. The hash link looked fine only because it re-packs specific fields, so it never saw the junk.

Fix was two-fold: hand the globe throwaway copies so it scribbles on those instead of my real data, and sanitize trips to known fields on save/load (which also cleans up the bloated localStorage on next visit). Back to ~1 KB per trip.

Where it stands

Live at https://wanderpin-ecru.vercel.app/ - build a trip, optimize it, save it, share a short link, watch it fly.

Honest caveats: shared trips are snapshots (open a link, get a copy - not live collaboration), and the globe’s three.js bundle is still the heavy chunk (lazy-loaded, so it only hits the 3D view). Lesson logged: never trust a viz library not to mutate your state.

Wanderpin - phase 3: real sharing, and the bug that ate an afternoon

This update gave Wanderpin proper short links, a saved-trips library, and a route optimizer. But the part I’ll remember is a 100 KB mystery.

Short links + a trip library

Sharing used to cram the whole trip into a giant #... URL. Now there’s a tiny Supabase backend: hit Share and you get a clean …/t/aB3xY9 link that anyone can open, no login. Reads come straight from the browser (a public read policy), and writes go through a serverless function with the secret key, so nobody can scribble on the database from the client. When someone opens a shared link, the route flies stop to stop and a little “Make your own” card invites them to start their own.

Click polish

Spinning the globe was dropping stray pins, because react-globe.gl fires a click even at the end of a drag. Added a pointer-distance guard (under ~5px = a real click). Clicking open ocean now offers an “Add anyway” instead of a useless pin, and there’s an “Optimize route” button that reorders stops with nearest-neighbour + 2-opt to cut total distance.

The bug: a 5-stop trip that was 400 KB

Share kept failing in the browser with a 413 (payload too large). But the function worked fine when I hit it with curl. Same 5-stop trip, totally different size.

I had the user dump their saved trip in the console. Five stops. 403,682 characters. Each stop had two mystery keys: __threeObjPoint and __threeObjLabel, ~100 KB each.

Turns out react-globe.gl mutates the data objects you hand it - it bolts the entire Three.js render object (meshes, geometry, materials) straight onto your data. I was passing my live trip array to the globe, so it was quietly fattening every stop by 100 KB, which then got saved to localStorage and sent on publish. The hash link looked fine only because it re-packs specific fields, so it never saw the junk.

Fix was two-fold: hand the globe throwaway copies so it scribbles on those instead of my real data, and sanitize trips to known fields on save/load (which also cleans up the bloated localStorage on next visit). Back to ~1 KB per trip.

Where it stands

Live at https://wanderpin-ecru.vercel.app/ - build a trip, optimize it, save it, share a short link, watch it fly.

Honest caveats: shared trips are snapshots (open a link, get a copy - not live collaboration), and the globe’s three.js bundle is still the heavy chunk (lazy-loaded, so it only hits the 3D view). Lesson logged: never trust a viz library not to mutate your state.

Replying to @darshjain

0
105
Open comments for this post

3h 15m 9s logged

Wanderpin - phase 2: trips you can shape, share, and watch fly

Phase 1 let you drop pins on a globe. Phase 2 turns that into an actual trip planner: reorder stops, edit them, share a link, and hit Play to watch the camera fly your whole route.

Play: the globe earns its keep

The feature I’m happiest with. There’s now a Play button that flies the camera stop to stop along your route, advancing the highlighted pin as it goes. On the 3D globe it looks the way I wanted the whole app to feel.

The nice surprise: it was almost free. Back in phase 1 both the globe and the flat map exposed the same tiny flyTo handle. So the tour loop doesn’t know or care which view you’re on

Editing, sharing, exporting

  • Reorder by dragging (dnd-kit), with the route redrawing live. The drag handle is the only draggable bit, so dragging never fights tapping a stop to edit it.
  • Edit a stop inline — rename, swap the emoji, add a note. Undo on remove and “clear all” via the toast, because I deleted my own trip twice testing it.
  • Share builds a link with the whole trip compressed into the URL (lz-string), no backend. Open it anywhere and the trip loads. IDs are regenerated on import so a shared trip never collides with one you already have.
  • Export to JSON or GPX, so a route can open in Google Earth.

Where it stands

Live at https://wanderpin-ecru.vercel.app/. Every phase builds clean (tsc + Vite) and deploys to Vercel on push. The loop now: build a trip, reorder and annotate it, watch it fly, share the link.

Wanderpin - phase 2: trips you can shape, share, and watch fly

Phase 1 let you drop pins on a globe. Phase 2 turns that into an actual trip planner: reorder stops, edit them, share a link, and hit Play to watch the camera fly your whole route.

Play: the globe earns its keep

The feature I’m happiest with. There’s now a Play button that flies the camera stop to stop along your route, advancing the highlighted pin as it goes. On the 3D globe it looks the way I wanted the whole app to feel.

The nice surprise: it was almost free. Back in phase 1 both the globe and the flat map exposed the same tiny flyTo handle. So the tour loop doesn’t know or care which view you’re on

Editing, sharing, exporting

  • Reorder by dragging (dnd-kit), with the route redrawing live. The drag handle is the only draggable bit, so dragging never fights tapping a stop to edit it.
  • Edit a stop inline — rename, swap the emoji, add a note. Undo on remove and “clear all” via the toast, because I deleted my own trip twice testing it.
  • Share builds a link with the whole trip compressed into the URL (lz-string), no backend. Open it anywhere and the trip loads. IDs are regenerated on import so a shared trip never collides with one you already have.
  • Export to JSON or GPX, so a route can open in Google Earth.

Where it stands

Live at https://wanderpin-ecru.vercel.app/. Every phase builds clean (tsc + Vite) and deploys to Vercel on push. The loop now: build a trip, reorder and annotate it, watch it fly, share the link.

Replying to @darshjain

0
4
Open comments for this post

4h 40m 34s logged

Wanderpin - first build

Check it out yourself -> https://wanderpin-ecru.vercel.app/

A little travel app where you drop pins on a spinning 3D globe (or a flat map if you prefer), and it stitches them into a trip with distances and country counts. Here’s where it’s at after the first couple of sessions.

What it does so far

  • Globe + map, same data. A 3D night-earth globe (three.js via react-globe.gl) with glowing pins and animated arcs between stops, and a 2D Leaflet map with a dashed route line. One toggle swaps between them - they render off the same trip array.
  • Search and click to add. Type a city and it geocodes through OpenStreetMap’s Nominatim; or just click anywhere on the map and it reverse-geocodes the spot into a named pin.
  • Surprise me. A pile of hand-picked destinations, each with a fun fact and a vibe, for when you don’t know where you want to go.
  • It remembers. Trip, view, and “is this still the sample” all persist to localStorage. First-time visitors get a seeded Paris -> Rome -> Cairo route so the app isn’t empty on load.

Spent a bit making the Nominatim calls polite: searches are debounced so a fast typer doesn’t fire a request per keystroke.

Where it stands

The core loop works end to end: search or click -> pin lands on globe and map -> trip panel updates distance (haversine) and country count -> reload and it’s all still there. Next up is editing/reordering stops and tidying the mobile layout

Wanderpin - first build

Check it out yourself -> https://wanderpin-ecru.vercel.app/

A little travel app where you drop pins on a spinning 3D globe (or a flat map if you prefer), and it stitches them into a trip with distances and country counts. Here’s where it’s at after the first couple of sessions.

What it does so far

  • Globe + map, same data. A 3D night-earth globe (three.js via react-globe.gl) with glowing pins and animated arcs between stops, and a 2D Leaflet map with a dashed route line. One toggle swaps between them - they render off the same trip array.
  • Search and click to add. Type a city and it geocodes through OpenStreetMap’s Nominatim; or just click anywhere on the map and it reverse-geocodes the spot into a named pin.
  • Surprise me. A pile of hand-picked destinations, each with a fun fact and a vibe, for when you don’t know where you want to go.
  • It remembers. Trip, view, and “is this still the sample” all persist to localStorage. First-time visitors get a seeded Paris -> Rome -> Cairo route so the app isn’t empty on load.

Spent a bit making the Nominatim calls polite: searches are debounced so a fast typer doesn’t fire a request per keystroke.

Where it stands

The core loop works end to end: search or click -> pin lands on globe and map -> trip panel updates distance (haversine) and country count -> reload and it’s all still there. Next up is editing/reordering stops and tidying the mobile layout

Replying to @darshjain

0
4

Followers

Loading…