6 min läsning

The other half of the road trip: building the page with Claude Code

Lovable built the app we post from. The page you follow the trip on was built here, in our own theme, with Claude Code — and the browser said no before it said anything else. The proxy, the privacy problem, and what we left out on purpose.

Illustration: stops on a line with hand-offs between them, like legs of a journey.

Our road trip has two halves. One is the app the team shoots from: open the phone, take the picture, tap once, done. That half is Lovable’s, and it is written up on their side. The other half is the page you are following the trip on, and it was built here — in our own WordPress theme, with Claude Code, in an afternoon. This is what that afternoon actually looked like.

The brief: our design, not an iframe

The easy version of this page is an embed. Drop the Lovable app in an iframe, call it done, go back to work. We did not want that, and not out of pride: an embed brings its own typography, its own colours and its own loading behaviour onto a page that spent a long time getting those things right. It also tends to be the slowest thing on the page.

So the brief was narrow. The data comes from Lovable. Everything a visitor sees — the intro, the timeline, the day headings, the gallery, the share link — is built from our own design tokens, in the same block system as the rest of the site, and editable in wp-admin like any other page.

Then the browser said no

The first version worked locally and showed an empty gallery in production. The timeline endpoint sends Access-Control-Allow-Origin: * and is happy to talk to anyone. The feed endpoint answers with https://hdlcommerce.com and nothing else — our sister site, not this one. A browser on hdlagency.se is simply refused.

The honest options were to wait for the API to add a header, or to stop asking the browser to make the call. We took the second one. A small read-only route in our own plugin — hdl-kit/v1/roadtrip — fetches both endpoints server-side and serves them from this site’s own origin, which removes CORS from the picture entirely.

Two details made it worth doing properly rather than quickly. The answer is cached for sixty seconds, so the page’s sixty-second poll never hammers the upstream no matter how many people are watching. And when an upstream call fails, the last good copy is served instead of an error: a road trip page that blanks because a dev API hiccuped is worse than one that is a minute stale.

The upstream address is never taken from the request. It is whatever the block on the page last rendered with, and only an https host under lovable.app is stored at all — so the proxy cannot be talked into fetching something else on our behalf.

The ids gave the customers away

This one we nearly missed. Every stop in the API has an id, and the ids are descriptive in the way internal ids usually are: they contain the customer’s name. Rendering them into the markup would have published our route — and our customer list — days before the visits happened.

So nothing writes an id into the page. A stop is identified by where it sits in time, numbered in arrival order, and a stop we have not reached yet stays masked: a marker on the timeline with no name, no place and nothing to view-source. The suspense is a side effect of a privacy decision, but it turned out to be the best thing about the page.

What we left out

There is no map. A map means a mapping library, a tile provider, a key to manage and a few hundred kilobytes on a page that people open on a phone, in the car, on mobile data. The timeline already answers the only question anyone is asking — where are they now, and what have they seen — so the map was cut from the spec and never missed.

There is also no stop list in the markup, no analytics beyond what the site already runs, and no separate app to install. The page is the product.

The small things that are easy to get wrong

Days, not UTC. Day headings group on the date as written in the trip’s own timezone. Slicing the ISO timestamp instead would have grouped on UTC and filed an 06:30 departure under the previous day — which is exactly the kind of bug nobody reports and everybody notices.

Every string editable. The labels all arrive from the block, so the copy stays in wp-admin rather than in a JavaScript file. Changing ”Follow our journey” does not need a deploy.

The gallery keeps its own shapes. The pictures from the road are every proportion you would expect from a phone in a hurry. They sit in a column masonry where each picture keeps its natural height, because forcing them into a uniform grid made a wall of identical rectangles out of a wall of photographs. The trade-off is that the page reflows a little as images load; we took it.

What it cost, and what it returned

An afternoon of building, one real problem to solve, and a page that updates itself. No new plugin, no subscription, no dependency added to the theme. The whole thing is roughly three hundred lines of JavaScript, one REST route and one block.

The trip has brought over 500 unique new visitors to the site — people who came to see where the car was, and found out what we do on the way. We have run campaigns that cost considerably more and did considerably less.

That is the honest lesson, and it is not really about the tooling. Lovable made the app possible without a backend team. Claude Code made the page possible in an afternoon. Neither of them had the idea of pointing a camera at an ordinary work week and letting people watch.

Follow along

The car is still out. You can follow the rest of the trip at hdlagency.se/roadtrip — the stops appear as we reach them, and the pictures go up while they are still warm.

If you want the same thing for your own site, get in touch and we will tell you which half was the hard one.