Private transfers — price list and booking
A five-language price list where picking a car and a destination opens a ready WhatsApp booking.
- Vite 7
- Vanilla JS
- Web Animations API
- IntersectionObserver
- node:test
- GitHub Actions
- 5languages, WhatsApp messages included
- 7screen widths checked with no overflow, from 320 to 1920 px
- 0cookies, analytics or map iframes
From the fare sheet to a WhatsApp booking
The operator's fares become tested data, the page is generated as static HTML, and one tap opens a WhatsApp message with route, car and price already written.
Tap a block to see what it does.
- Input
- Logic
- Data
- Infrastructure
- Output
- People
Input
Fare sheet
The operator's fare sheet: two airports and a port, three vehicle classes from 1–3 to 7–8 passengers, a fare per direction.
Hands to Fare data
Logic
Five languages
IT, EN, FR, ES and PT strings, including a translated WhatsApp message for every fare.
- Vanilla JS
Hands to Booking panel
Data
Fare data
Destinations, fleet with capacities and fares as plain JS modules, kept out of the markup and covered by unit tests.
- ES modules
- node:test
Gets from Fare sheetHands to Render script
Logic
Render script
Builds index.html from JS section templates at build time, so all prices and links are already in static HTML.
- Node.js
Gets from Fare dataHands to Static page
Infrastructure
Static page
A Vite bundle with self-hosted fonts; content and links work with JavaScript off, and CI runs the quality checks.
- Vite 7
- GitHub Actions
Gets from Render scriptHands to Motion layer, Booking panel
Logic
Motion layer
Hero blur-in with Web Animations, a scroll-linked film mask, clips loaded on demand; every effect can be destroyed cleanly.
- Web Animations API
- IntersectionObserver
Gets from Static page
Output
Booking panel
Car buttons and destination tabs; each fare is a link to a prefilled WhatsApp message with route, car, direction and price.
- WhatsApp links
Gets from Static page, Five languagesHands to WhatsApp chat
People
WhatsApp chat
The operator confirms vehicle, availability, VAT and extras in the chat. No backend, no cookies, no forms.
Gets from Booking panel
The problem
A private transfer service, covering airports, a cruise port and day tours, had a dense static site with no clear path to booking. It needed a clear price list, built from its fare sheet, that leads straight to a booking with no backend.
What I built
- Iterated quickly: a zero-build static version, a shorter one with booking in three taps, two design artefacts from a Claude Design brief, then the final Vite build.
- Turned the fare sheet into tested data: destinations, vehicles with their capacities and a fare per direction, kept apart from the markup.
- Generated the page from JS templates at build time, so every price and link exists in static HTML and works without JavaScript.
- Built the booking panel: pick a car and a destination, tap a fare, and WhatsApp opens with route, car, direction and price already written, in the visitor's language.
- Chose video chapters with native scroll over WebGL or a continuous scroll film, which would not help anyone pick a route and would add weight.
The hard part
Video chapters that stay light on a phone over 4G. Clips load on demand with IntersectionObserver, pause off screen or in a hidden tab, never autoplay with Reduced Motion or Save-Data, and are encoded as muted H.264 with fast start and posters.
Result
A verified build: unit tests on fares, booking messages, translations and security, and no horizontal overflow at seven widths from 320 to 1920 px. No cookies, analytics or map iframes; fares stay marked as indicative until VAT and extras are confirmed.
My role
Solo, with agents. I supplied the brief and the sources and directed four iterations; OpenAI Codex wrote 6 of the 8 commits and I made the last 2, which completed the design and the per-vehicle pricing.