Clusterflick is a free, open-source site listing every film showing in London, from 450+ venues in one search: chains, independents, film clubs, festivals and pop-ups. Each film shows its screenings across every venue, with ratings from IMDb, Letterboxd, Rotten Tomatoes and Metacritic, and filters for subtitled, audio-described, relaxed and baby-friendly showings.
🎬 Looking for something to watch? Head to https://clusterflick.com 🍿
This organisation holds the code behind it. Listings are pulled from each venue's own website several times a day, put into one format, matched to The Movie Database, and built into a static site. The pipeline runs in the open as a chain of GitHub Actions, one repository per stage (see Pipeline).
📄 For data you can use, see clusterflick.com/data-licence.
Most of the repositories below are internal build artifacts, published because
the pipeline runs in the open rather than offered for reuse. Each one carries a
LICENSE-DATA file saying which it is.
The code in every repository is separately available under the MIT licence.
The site
- clusterflick.com — the website
- api-tmdb-search — the Cloudflare Worker behind the site's film search
- branding — brand guide, logos and icons
The data pipeline
- scripts — the code behind every stage, with a module for each venue and ticketing source
- data-retrieved — pulls raw listings from venue websites and ticketing platforms
- data-transformed — puts each venue's listings into one format and matches films to TMDB
- data-diffed — records what changed between runs
- data-backedup — keeps a copy of every transformed release off GitHub, one archive per week
- data-cached — caches TMDB metadata for every film
- data-combined — merges every venue into the single dataset the site is built from
- data-matched — adds ratings from IMDb, Letterboxd, Rotten Tomatoes and Metacritic
- data-calendar — calendar feeds, one per venue
- host-non-web-sources — hand-transcribed listings for venues with nothing on the web to read
Tooling and operations
- data-analysed — finds new venues, checks listings against other sources, tracks pipeline reliability
- manage.clusterflick.com — internal review site for the pipeline
- analysis.clusterflick.com — the original site, kept for reviewing the combined data
- generate-spotlights — social media posts
- self-hosted-workflows — workflows for the Raspberry Pi runners
- themoviedb-data — TMDB catalogue download for experimentation
- release-downloader — fork of a GitHub Action for downloading release assets
- .github — this profile and shared reusable workflows
flowchart LR
retrieved["data-retrieved"]
transformed["data-transformed"]
calendar["data-calendar"]
cached["data-cached"]
diffed["data-diffed"]
backedup["data-backedup"]
nonweb["host-non-web-sources"]
combined["data-combined"]
matched["data-matched"]
scripts["scripts"]
analysed["data-analysed<br>(comparisons)"]
runstats["data-analysed<br>(run stats)"]
llmusage["data-analysed<br>(LLM usage log)"]
releaselog["data-analysed<br>(release log)"]
venuehealth["data-analysed<br>(venue health, hourly)"]
subgraph retrival[" "]
direction TB
retrieved --> retrival-release>Release]
end
subgraph transformation[" "]
direction TB
transformed --> transformation-release>Release]
end
subgraph calendars[" "]
direction TB
calendar --> calendar-release>Release]
end
subgraph caching[" "]
direction TB
cached --> cached-release>Release]
end
subgraph diffing[" "]
direction TB
diffed --"if changed"--> diffed-release>Release]
end
subgraph backup[" "]
direction TB
backedup --"each finished week"--> backup-archive[("R2 archive")]
end
subgraph combination[" "]
direction TB
combined --> combined-release>Release]
end
subgraph matching[" "]
direction TB
matched --> matched-release>Release]
end
subgraph website[" "]
direction TB
clusterflick.com --> id1[[Generate website]]
analysis["analysis.clusterflick.com"] --> id2[[Generate analysis site]]
manage["manage.clusterflick.com"] --> id3[[Generate management site]]
end
nonweb -.->|read by| retrival
retrival --triggers--> transformation
transformation --triggers--> backup
transformation --triggers--> diffing
transformation --triggers--> scripts
transformation --triggers--> analysed
transformation --triggers--> runstats
transformation --triggers--> llmusage
transformation --triggers--> releaselog
diffing --triggers--> caching
caching --triggers--> combination
combination --triggers--> calendars
combination --triggers--> matching
combination --triggers--> analysis
calendars --triggers--> clusterflick.com
calendars --triggers--> releaselog
matching --"triggers (if new data)"--> clusterflick.com
clusterflick.com --triggers--> manage
venuehealth --triggers--> manage
(daily at 11am UTC)
(manual)
(after each transform)
(after each transform)
(after each transform)
(after each transform)
(after each transform — feeds the stability badges above)
Failed runs of these stages are re-run automatically, up to 3 attempts.
(after each transform)
(every 3 hours — catches runs the log missed)
(after each transform and calendar release)
(hourly)
(hourly)
(weekly)
Each repo audits its GitHub Actions workflows with
zizmor via the shared
.github
reusable workflow.