An interactive storytelling web and mobile app powered by Claude and Mapbox. Chat with Carte, an AI travel tool, and watch your journey come to life — cinematic globe fly-through, animated transport markers, colour-coded route lines, a photo fan at every stop, and full PWA support for install on desktop and iOS/Android.
🌍 Live at map-storry-telling.onrender.com
- Conversational AI — Carte (Claude) asks where you went and how you got there, then flies the map there automatically
- Cinematic globe animation — smooth
flyToon a 3D Mapbox globe with fog and atmosphere - Transport modes — plane
✈️ , train 🚂, car 🚗, or any custom mode (bike, ferry, horse, helicopter…) with matching emoji marker and route colour - Animated route — coloured base line + white dashed overlay draws in real time as you travel
- Photo fan — add up to 5 photos at each stop; they fan out as a card arc on the map
- Lightbox viewer — click any photo to enlarge it
- Trip replay — replay your full journey step by step with a progress HUD and Next / Stop controls
- Mobile-first layout — bottom-drawer panel on phones (≤ 600 px) so the map fills the top half; safe-area insets for iOS notch/home-bar; momentum scroll; no auto-zoom on inputs
- PWA — installable on desktop (Chrome/Edge) and mobile (iOS Safari, Android Chrome); works offline for the app shell
| Layer | Technology |
|---|---|
| Map | Mapbox GL JS v3.3 |
| AI | Anthropic Claude (claude-sonnet-4) via API |
| Server | Node.js (ESM) — thin HTTP proxy, no framework |
| Frontend | Single-file HTML + CSS (carte.html + carte.css) |
| Storage | Firebase Firestore (cross-device sync) + IndexedDB (offline fallback) |
| PWA | Web App Manifest + Service Worker (sw.js) |
carte.html — app UI + all client-side JS
carte.css — all styles
server.js — Node proxy: serves static files, forwards /api/claude → Anthropic
manifest.json — PWA web app manifest
sw.js — Service worker (cache-first shell, network-only for AI + Mapbox)
icons/
icon-192.png — PWA home screen icon
icon-512.png — PWA splash / install icon
package.json
README.md
npm install| Key | Where to get it |
|---|---|
| Mapbox | mapbox.com → Tokens |
| Anthropic | console.anthropic.com → API Keys |
| Firebase | console.firebase.google.com → new project → web app registration |
- Go to Firebase Console and create a new project (or use an existing one).
- Click "Add app" → Web (
</>), register the app, and copy the config values. - In the left sidebar go to Build → Firestore Database → Create database.
- Choose production mode (you'll add rules in the next step).
- Pick any region close to your users.
- Open the Rules tab and paste these permissive rules (suitable for a personal/hobby app — restrict further if you go public):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /trips/{tripId} {
allow read, write: if true;
}
}
}
- Grab the three values you need from Project Settings → Your apps → SDK setup:
| Env var | Firebase config field |
|---|---|
Firebase_API_KEY |
apiKey |
Firebase_PROJECT_ID |
projectId |
Firebase_APP_ID |
appId |
Firebase is optional — the app falls back to local IndexedDB if the vars are not set.
export Mapbox_KEY=pk.eyJ1...
export Claude_KEY=sk-ant-...
export Firebase_API_KEY=AIza...
export Firebase_PROJECT_ID=my-carte-project
export Firebase_APP_ID=1:123456789:web:abc123Or inline:
Mapbox_KEY=pk... Claude_KEY=sk-ant-... Firebase_API_KEY=AIza... Firebase_PROJECT_ID=my-carte Firebase_APP_ID=1:...:web:... npm startnpm startOpen http://localhost:3000 in your browser.
server.jsservescarte.html,carte.css,manifest.json,sw.js, and theicons/folder as static files, injectingMapbox_KEYinto the HTML at request time (replacing the__MAPBOX_TOKEN__placeholder).- All Claude API calls from the browser go to
POST /api/claude, which the server proxies toapi.anthropic.comusingClaude_KEY— keeping your API key off the client. - The client runs a tool-use agent loop: Claude calls
resolve_location(Mapbox Geocoding API),set_transport, andfly_to_locationas structured tools, which execute locally in the browser.
- Type naturally — "I flew to Tokyo, then took the Shinkansen to Kyoto"
- Custom transport — click
+ custom transportto set any emoji + label before describing your next leg - Add photos — click the
+button on any map marker to attach photos (up to 5 per stop) - Replay — once you have 2+ stops, click
▶ replay tripto watch the whole journey play back
Visit the live URL (or localhost:3000), then click the install icon ⊕ in the address bar → "Install Carte".
Tap the browser menu → "Add to Home screen".
⚠️ Safari requires HTTPS for PWA install — use the deployed URL, not localhost.
- Open map-storry-telling.onrender.com in Safari
- Tap the Share button (box with arrow)
- Scroll down and tap "Add to Home Screen"
- Tap "Add" — Carte appears on your home screen with its amber globe icon
Once installed, the app shell (HTML, CSS, icons) loads instantly from cache. The map and AI features still require an internet connection.
The app is deployed on Render as a Node.js web service.
Environment variables to set in the Render dashboard:
| Variable | Value |
|---|---|
Mapbox_KEY |
Your Mapbox public token |
Claude_KEY |
Your Anthropic API key |
Firebase_API_KEY |
Your Firebase apiKey |
Firebase_PROJECT_ID |
Your Firebase projectId |
Firebase_APP_ID |
Your Firebase appId |
Render auto-deploys on every push to the connected GitHub branch. Make sure manifest.json, sw.js, and the icons/ folder are all committed — they are required for PWA install to work.
| Command | Description |
|---|---|
npm start |
Start server with nodemon (auto-restarts on changes) |