GlobeTrail 3D: A Cinematic Travel Globe, Built Solo, Entirely in the Browser: preview
Realtime 3DThree.jsWebCodecsCloudflareSolo ProductGlobeTrail 3D

GlobeTrail 3D: A Cinematic Travel Globe, Built Solo, Entirely in the Browser

GlobeTrail 3D turns a list of places into a film. You add the stops, the globe draws the route, and the journey replays as an animation you can export as an MP4, a poster set or a printed storybook, with nothing installed and nothing uploaded until you choose to share. I designed, built and shipped the whole product on my own: the WebGL scene, the playback engine, the video encoder path, the PDF writer, the edge backend and the accounts. This is the engineering behind it.

Role
Founder and sole engineer. Product design, rendering, backend, infrastructure and release.
Period
July 2026 to present6 min read
Stack
Vue 3 · TypeScript · Three.js · WebGL · WebCodecs · Vite · Cloudflare Pages Functions · D1 · R2 · Service worker (PWA) · Playwright · Vitest
5
globe worlds
219k
places
4K
video export
3,577
unit tests
454
browser tests
800
roadmap items

Problem

A travel map is a static picture. The product had to make a route feel like a journey, then hand the traveller a file they could post, print or keep, with no server rendering, no install, and their data staying on their device by default.

Approach

One composition pipeline drives both the on-screen playback and the exported frame, so the preview and the file cannot disagree. Everything heavy runs in the browser. The backend exists only for the things a browser cannot do alone: a share link, a gallery and an account.

Outcome

A live product with five globe worlds, seven lighting looks, 4K video export, a printed storybook with embedded fonts, shared journey pages, a curated gallery and passwordless accounts, all built and maintained by one engineer.

Context and challenge

Most travel-map tools produce a picture: pins on a flat map, sometimes an arc between them. What people actually want to share is the story of the trip, and a story has order, pacing and an ending. GlobeTrail 3D was built around that idea. A journey is a sequence of stops with dates, places, transport and photographs, and the product's job is to replay it well enough that the traveller wants to post the result.

That framing set three constraints. The film had to look the same in the app and in the exported file, which rules out rendering the two differently. The product had to be local-first, so the journey lives on the device and leaves it only through an act the traveller takes, which rules out server-side rendering and a simple upload-and-process pipeline. And it had to be finished as a product rather than a demo, which means posters, a printed book, sharing, offline support, accounts and the legal documents to go with them, all of it maintained by one person.

Approach

The globe is a Three.js scene with five worlds: a satellite Earth, an Atlas reference map, a Relief map with hillshade, and two illustrated worlds, Toon and Ink. The drawn worlds are generated from real elevation and bathymetry data by scripts in the repository, so the artwork is reproducible rather than painted. Country borders come from Natural Earth's India-worldview dataset, and the city gazetteer is two tiers: a small base index that ships with the app, and 234 per-country packs from GeoNames, around 219,000 places, fetched only when a journey touches that country.

Playback runs from a plan rather than a timer. A director computes every camera move, dwell and transition from the journey's stops, and both the on-screen stage and the recorder consume the same composeFrame output. That single rule is what makes the exported MP4 a faithful copy of what the traveller watched. Titles, the vehicle riding the arc, the polaroid that rises at a photographed stop and the closing card are all part of that one frame.

Export happens in the browser through WebCodecs. Frames are encoded to H.264 and muxed into MP4 on the main thread with no server involved, at Full HD, 2K or 4K, always at 24 frames per second. A reel or square film can split itself into platform-capped parts, cut only on stop boundaries, with the closing card glued to the final part. The same pipeline renders the poster set and the social card.

The backend is deliberately small. Cloudflare Pages Functions serve a shared journey page with its own Open Graph card, store the payload in D1 and the photo pack in R2, and run a curated gallery and an admin room. Accounts are an email address and a six-digit code, with no password anywhere in the system. The service worker makes the app installable and keeps the globe working offline, with bounded, versioned caches for textures and previews.

Engineering decisions

Own the byte formats. The storybook is a real PDF with selectable text and embedded, subsetted Source Serif and Source Sans faces, written by a PDF writer I wrote for the project rather than a library. The QR code on the share card comes from an in-house ISO 18004 encoder, proved in tests by an independent decoder reading its output back. The EXIF reader that pulls dates and coordinates from a photograph is dependency-free and treats every failure as a missing field, never a crash. Each of these was cheaper to own than to depend on, and owning them meant no hidden behaviour in the path between the traveller's data and the file they download.

One plan, two renderers. The storybook is laid out once into pages of primitives, then drawn to a canvas for the preview and to the file for the download. Both measure text with the PDF's own font advances, so the preview is a picture of the page rather than an approximation of it. The video works the same way. Wherever the product shows a preview, the preview and the artefact share a plan.

Let the machine propose and the traveller decide. Transport between stops is inferred from geometry alone: a sea crossing under a threshold suggests a boat, a long hop suggests a flight, the traveller's own precedent wins over both. A photograph's date and location are offered, never applied. A machine's guess is flagged in the data so it can never be mistaken for something the traveller said. This rule runs through the whole product and it is the reason the app never argues with a user about their own trip.

Measure before deciding. The project keeps a decision register of 296 entries and a report for every commit, and a large share of those record a measurement: the frame that blocked for 553 ms on a colour change until the work moved behind the paint, the label collision rule borrowed from map engines after five city names wrote over each other, the export ceiling probed up front so a phone is told honestly what it can record. The unit suite covers the pure logic, the browser suite covers the surfaces, and a set of 44 committed appearance baselines catches a change to how the globe looks before it ships.

Privacy is handled in the design rather than in a policy document. Analytics fire only with consent and carry counts and enumerations, never a string, so a place name structurally cannot leave the device. The privacy document is edited in the same commit as any change to what the product stores, and a test walks the source to keep the two in step. Photographs stay in the browser's own database and travel only inside a backup, a share or an account the traveller signed up for.

Outcome

GlobeTrail 3D is live at globetrail3d.com. A traveller can build a route by searching cities, pasting a Google Maps link, importing a GPX track or dropping in a batch of photographs and letting the dates and coordinates place the stops. They can watch it back with a generative ambient soundtrack, export it as a film in landscape, reel or square, print a poster set or a storybook, share a link with its own preview card, and sign in to keep a copy across devices.

The scale of the codebase reflects a finished product rather than a prototype: about 175,000 lines of TypeScript and Vue across the app and the edge functions, 3,577 unit tests, 454 Playwright tests in 70 specs, and 800 tracked roadmap items with a written decision behind every reversal. All of it was designed, built, tested and deployed by one engineer.

What it demonstrates

The work is realtime 3D graphics and video encoding delivered as a consumer product, with the whole stack under one person's control. The same habits the enterprise work relies on run through it end to end: keeping heavy computation on the GPU and off the main thread, designing one pipeline that several outputs share, and treating performance and privacy as correctness problems.

It also shows product judgement. Every feature that ships has a reason written down, and several that were built were removed when they turned out to argue with the traveller rather than serve them. Building alone made that discipline necessary; the register is what kept the product coherent across a thousand commits.

Outcomes

  • Designed and shipped a complete 3D travel product solo, from the WebGL scene to the edge backend, in production at globetrail3d.com
  • Built a browser-side video pipeline on WebCodecs that exports Full HD, 2K and 4K MP4 with the on-screen playback and the file rendered from one frame composer
  • Wrote the product's own PDF writer with embedded subsetted fonts, its own QR encoder and its own EXIF reader, each proven by tests against independent readers
  • Generated five globe worlds from real elevation and bathymetry data, with a two-tier gazetteer of 219,000 places loaded per country on demand
  • Shipped sharing, a curated gallery, passwordless accounts and an admin room on Cloudflare Pages Functions, D1 and R2, with a consent-gated analytics layer that structurally cannot carry personal data
  • Kept 175,000 lines of code coherent through a decision register, a report per commit and a test gate of 3,577 unit and 454 browser tests