There’s a cinema in Barcelona called Phenomena Experience. If you haven’t been, stop reading this and go. They screen classics in 4K with Dolby Atmos. Blade Runner, The Godfather, Interstellar, Akira. A single beautiful 450-seat sala. It’s one of the best things about living here.
Their website is the worst thing about going there.
I don’t mean ugly. I mean actively hostile. You want to buy two tickets to see Pulp Fiction on Friday? Here’s what you do:
- Land on their homepage
- Click “Programación” in the nav (unless it’s showing today, in which case you can skip this)
- Scroll through the programme to find the film
- Click the showtime to go to the “patio” page
- Select your ticket count from a dropdown and submit
- On the checkout page: adjust the ticket type if needed, enter your name, email, phone, tick the terms checkbox
- Click “Comprar” and complete payment on the bank’s gateway
Seven steps. Some of them on pages that take several seconds to load. The mobile version is worse. Buttons are tiny, text overflows, and the checkout page requires scrolling past a wall of legalese to find the submit button.
So I rebuilt it
I sat down one Friday morning and thought: what if buying a ticket was just… good? What if the whole programme loaded instantly, you tapped a film, picked your showtime, filled in three fields, and went straight to payment?
An hour or two later I had a working site. By lunch it was deployed on a custom domain with monitoring, notifications, and auto-refreshing data.
The site is at phenomenarapida.com. “Rápida” means fast in Spanish. That’s the whole point.
Here’s the checkout flow, before and after. I’m in the checkout before the old site has even loaded:
Before (60s)
After (19s)
How it works
The frontend is a single HTML file. 32 kilobytes. No React, no Next.js, no build step, no npm install. One file with inline CSS and vanilla JavaScript. It loads the programme from a JSON file, renders a grid of films with posters and showtimes, and lets you tap through to buy tickets.
When you hit “Buy,” the backend talks to Phenomena’s actual ticketing system (powered by reservaentradas.com) and drives the entire checkout flow server-side. Gets a session, reserves your seats, validates your ticket selection, builds a payment URL. Then it redirects you straight to the bank’s payment page.
From the user’s perspective: pick film, pick time, enter details, pay. Four steps.
The old site does the same thing in seven.
The tech
This is what I find satisfying about it. The whole thing runs on Cloudflare’s free tier. Zero cost per month.
The frontend is a single HTML file served from Cloudflare Pages. The backend is a Cloudflare Worker, about 500 lines of JavaScript. Data lives in a Cloudflare KV store and gets refreshed twice a day by a cron. Poster images are proxied through the Worker, converted to WebP, and cached in KV. I get Telegram notifications when new films are added or sessions sell out.
No database. No Docker. No CI/CD pipeline. No infrastructure to maintain. It’s just files and functions. The way the web used to work, but with a global CDN underneath.
Reverse-engineering the checkout
The interesting engineering problem was reverse-engineering Phenomena’s checkout flow. Their site runs on a platform called reservaentradas.com, and all the interactivity goes through a single endpoint called ws.pro that accepts JSON POSTs with a UUID session cookie.
The checkout is a multi-step dance:
- GET the homepage to receive a UUID in a Set-Cookie header (which is itself a JSON blob nested inside the cookie value, fun)
- POST to
ws.prowithproc: "patio"to initialise the seat selection - POST to the resumen page with your ticket count
- POST to
ws.prowithproc: "resumen"to validate the order - Build a hex-encoded JSON payload and redirect to Redsys (the Spanish bank payment gateway)
The payment callbacks all go back to Phenomena’s server, so they handle ticketing and email delivery as normal. We just skip the UI.
Accessibility
This one matters to me. The old site is not accessible. The new one uses semantic HTML, proper ARIA attributes, keyboard navigation, focus-visible outlines, and respects prefers-reduced-motion. Screen readers can actually use it.
It’s also trilingual. Spanish, Catalan, and English, with automatic detection from browser locale. Because Barcelona.
The numbers
I measured both sites. The old site’s homepage loads 3 MB of data across 40+ HTTP requests: 23 CSS files, 13 JavaScript files (including the entirety of jQuery and jQuery UI), six giant slider banners, eight poster images, and two icon font libraries. Time to first byte: 617ms.
Ours loads 298 KB across about 10 requests. Time to first byte: 140ms. The whole page is interactive before the old server has even finished responding.
The old site is 10x heavier. The new one loads 4x faster. And that’s measuring from a server in Europe, not a phone on 4G in the Eixample.
The cost
The domain name. That’s it. Cloudflare Workers, Pages, KV, and cron triggers are all within the free tier. You’d need about 10,000 daily visitors to even get close to the limits.
The total monthly infrastructure cost is €0.00.
What I learned
A few things stood out building this.
You don’t need a framework. A single HTML file with vanilla JS handles i18n, modals, bottom sheets, swipe-to-dismiss, scroll locking, keyboard handling, and responsive layouts. The page loads in under a second on a 3G connection.
Cloudflare Workers are absurdly capable. The entire backend, checkout proxy, image proxy with caching, data refresh with diffing, Telegram notifications, is one JavaScript file. Deploy takes five seconds. No cold starts.
Reverse-engineering sounds harder than it is. Their checkout flow looks complicated from the outside, but it’s really just five POST requests in sequence.
Mobile-first means thinking about fingers. Half the iteration time was spent on the bottom sheet modals. Making sure the Buy button was visible without scrolling, inputs didn’t get obscured by the keyboard, double-tap zoom was disabled on interactive elements, and you could swipe to dismiss. None of that is hard. It just matters.
Should I be doing this?
Probably not. I’m using their data, proxying their checkout, and serving it on my own domain. They could send me a cease and desist and I’d take it down immediately.
But I also bought tickets through it and the experience was so much better that I kind of wish they’d just hire someone to fix their site. Phenomena is a Barcelona institution. They deserve a website that matches the experience of actually being there.
Until then, there’s phenomenarapida.com.
The code is on GitHub. The cinema is at C/ Sant Antoni Maria Claret, 168, Barcelona. Go see something.