5 MIN READ · Pedro Thomaz

The URL is a database you already have

Diorama runs on static hosting with no backend, yet you can share the exact room you arranged as a link. The trick: encode the whole app state into the URL hash. Here is how it works — and the four places it stops working.
The URL is a database you already have

Diorama, our new Lab room, runs on GitHub Pages. Static hosting, no backend, no database. And yet you can arrange a room and send someone a link that opens your exact room — no account, no server, no saved record anywhere. The trick is old and underused: put the whole state in the URL.

The hash is free storage

Everything after the # in a URL — the fragment — never travels to the server. It lives entirely in the browser. That makes it the perfect place to stash application state you want to travel with a link but never persist server-side.

Diorama's state is small and structured: a list of furniture (type, position, rotation, colour) and the room settings (walls, floor, rug, lamps). We serialise that to JSON, base64-encode it, and drop it in the hash — #s=eyJsYXlvdXQ…. On load, if that parameter is present, we decode it and rebuild the room before anything else runs. A shared link wins over local storage; local storage wins over the default room.

const encode = p => btoa(unescape(encodeURIComponent(JSON.stringify(p))));
const url = location.origin + location.pathname + '#s=' + encodeURIComponent(encode(state));

That is the entire "backend". Copy the string, paste the link, and the receiver's browser reconstructs the scene deterministically — the same data always produces the same room.

Why not just use a server?

Because for a lot of things you do not need one, and every server you add is something to host, secure, back up and pay for. If the state is small, structured, and only meaningful to the person who made it, the URL is a database you already have — globally distributed, free, and needing no auth.

Where it stops working

The pattern has honest limits, and pretending otherwise is how people get burned:

The other half: an image

A link rebuilds the interactive scene, but people also just want a picture to post. So Diorama has a second share path: render the current frame to a PNG with canvas.toDataURL() (with preserveDrawingBuffer enabled) and trigger a download. A link for "come play with mine", an image for "look what I made". Between the two, there is no server at all.

Play with it on the live Diorama, or read the source on GitHub.