Three new modals wired into the planner with real interactions:
CustomiseStopModal (4 tabs)
- Tab rail (Charger / Overnight / Duration / Things to do / Detour)
auto-hides tabs that don't apply (e.g. Charger only for chargers,
Overnight only for hotels, Things to do only when nearby[] exists).
- Charger tab: radio-style picker over stop.chargerOptions with
kW/stalls/€/network/detour badge per option.
- Overnight tab: lists the current hotel + stop.alternatives as
swappable options with Choose buttons.
- Duration tab: 48px figure + range slider (10–120 min, snaps to
presets) with arrive/leave battery % shown live; preset grid
(Quick top-up / Coffee / Sit-down lunch / Explore / Full charge /
Skip).
- Things to do tab: checkbox grid over stop.nearby[] for picking what
you want to do at the stop.
- Apply Changes commits chargeMinutes + durationMin back into the
itinerary via a new updateStop() handler.
AddDetourOverlay
- Spotlight-style search bar (autofocus, esc to close) with a
curated POPULAR_DETOURS list (York Minster, Lake District,
Hadrian's Wall, Beaune town centre, etc.). Insert button adds the
detour as a new stop in the current day via a new insertDetour()
handler. The map polyline / leg metrics recompute automatically.
GpxExportModal
- Real downloadable export — GPX (XML), KML (Google Earth), CSV.
- Live preview pane shows the generated file, with line count + KB
in the footer. Copy puts the file content on the clipboard;
Download .gpx writes it as a Blob with the right MIME type and
triggers a real browser download. Filename derived from the trip's
first/last stop.
- GPX include-toggles for stop notes and nearby places.
- Empty-trip state shows a friendly message instead of an empty pane.
Plumbing
- Modal state lifted into the planner as { kind, stopId? } | null.
- Top bar Export button, the rail's Add stop button, and the bottom
Add detour link all open the relevant modal.
- The Customise stop button inside the expanded stop card now opens
the Customise modal for that stop.
- ModalShell handles backdrop, escape-to-close, scroll-clamp, and
optional header/footer/subtitle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tesla Roadtrip — Grok-Powered Planner (UK & Europe First)
Beautiful split-pane Tesla trip planner.
Left side: Natural language chat with Grok Drive (powered by the real xAI Grok API)
Right side: Interactive Leaflet map + live itinerary that updates as you talk
First Release Focus
- United Kingdom
- Europe (France, Germany, Benelux, Switzerland, Spain)
Key Features
- Real Grok intelligence via the xAI API
- Excellent Supercharger coverage awareness across the UK & Europe
- Metric units (km, Wh/km)
- Proactive route planning — just say where you want to go
- Safe, restricted tool use
Tech Stack
- Vite + React + Tailwind + Leaflet (client)
- Express + Prisma + pino (server)
- Real xAI Grok API (with local
grokCLI as optional path) - Heavy structured logging for fast debugging
Local Development
1. Install dependencies
npm install
cd client && npm install && cd ..
2. Set up environment variables
cp .env.example .env
Then edit .env and add your xAI API key:
XAI_API_KEY=xai-YourKeyHere
You can get a key from: https://console.x.ai
3. Start the development environment
You have two options:
Option A (Recommended) – Better developer experience:
./scripts/dev.sh
Option B – Using npm:
npm run dev
Both commands will start:
- Backend: http://localhost:3000 (with detailed logging)
- Frontend: http://localhost:5173
4. Open the app
Visit: http://localhost:5173
Useful Commands
| Command | Description |
|---|---|
npm run dev |
Start both frontend and backend |
./scripts/dev.sh |
Recommended way to start (better output) |
npm run dev:server |
Start only the backend |
npm run dev:client |
Start only the frontend |
Security & Philosophy
This project follows a strict security policy:
- No packages with known active critical or high vulnerabilities
react-markdown/ remark ecosystem avoided (LLM output sanitization via DOMPurify)- All AI tool use is heavily restricted
- Maximum logging so we can debug the "chat → route → stops" flow easily
Deployment Target
Will be deployed via Dokku on Hetzner with Gitea CI.
First launch target: United Kingdom & Europe.
Need Help?
- Make sure your
XAI_API_KEYis set (otherwise you'll get very basic responses) - Check the backend terminal — it has extremely detailed logs
- The app is designed so you can iterate quickly by watching the logs
Development & Iteration Workflow (Autonomous Loop)
This project is designed for fast, autonomous iteration using Playwright.
One-Command Iteration Loop
The recommended way to test and iterate is:
./scripts/iterate.sh
This script will:
- Ensure both backend and frontend are running (via
./scripts/dev.sh) - Run the fast backend diagnostic test (
smoke test) - Run the full E2E Playwright test in headed mode
- Open the Playwright HTML report
- Show the latest screenshots and video
- Print the most relevant backend log lines from the test window
After the script finishes, review the artifacts and tell me what to fix. Then just run ./scripts/iterate.sh again.
Fast Smoke Test (Backend Only)
When you only want to quickly test if Grok is responding (without waiting for the full UI flow):
./scripts/smoke.sh
This runs in ~30–90 seconds and is perfect for prompt tuning or backend debugging.
Manual Commands
| Command | Description |
|---|---|
./scripts/dev.sh |
Start both servers (recommended) |
npm run dev |
Start both servers (via npm) |
./scripts/iterate.sh |
Full autonomous test + report loop |
./scripts/smoke.sh |
Fast backend-only Grok test |
npx playwright test |
Run all Playwright tests manually |
Test Reports & Artifacts
- Playwright HTML report:
npx playwright show-report - Screenshots & videos:
test-results/ - Backend logs: Look in your terminal or
/tmp/tesla-roadtrip-backend.log(if you enabled logging to file)
Workflow Summary
- Make a code or prompt change
- Run
./scripts/iterate.sh - Review the report + screenshots + backend logs
- Tell me what to fix
- Repeat
This loop lets me drive most of the testing and debugging with minimal manual work from you.