The big picture
The heavy lifting (reading and judging listings) happens once a day on my laptop. Your phone only downloads the finished list.
Step by step
The alarm goes off Laptop
Windows Task Scheduler starts the refresh at 6am. If the laptop was asleep, it catches up the next time I log in. A full run takes one to two hours.
Fifteen scrapers visit about 115 sites Laptop
Python scripts read council event calendars, ticketing sites, church and club websites, university student union calendars and even PDF parish newsletters. They check each site's robots.txt first and skip any site that asks bots to stay away.
Cheap filters go first Laptop
A keyword check throws out listings that are obviously irrelevant. Anything more than 100 km from Sydney is dropped, and the same event listed on two sites is merged into one.
Claude reads the survivors Claude
Only new or changed listings go to Claude. For each one it decides whether it's really free, whether food or drink is on offer (and copies the host's exact words as proof), and whether you can walk in or need to book. It also flags who it's for (students, seniors, members only, and so on). When food isn't mentioned, it estimates how likely there is some.
A second check catches sneaky prices Claude
Each morning Claude re-reads every live event looking for hidden ticket prices or entry limits. The first time this ran, it removed 55 paid events that had slipped through.
The feed file is written Laptop
Past events are dropped. Short names, images, times and "what's on the table" phrases are added, and everything is saved into one file: events.json.
Push to GitHub, and Cloudflare publishes GitHub → Cloudflare
The file is checked and then committed to GitHub. Cloudflare notices the change and redeploys crashers.app within a minute or two.
Your phone does the personal part Your phone
When you open the app, it downloads the event list and sorts it by walking time from you (or from the CBD if you don't share your location). It groups events into shelves like "Free drinks" and "Turn up, nothing to book", and shows everything on a map.
Reminders without accounts Your phone
Save an event and the phone app schedules its own reminder. No login, no push server. Your saved events and preferences never leave your device.
The pieces
Python scrapers
Fifteen fetchers, each written for one family of sites (for example, one adapter covers 15 councils that use the same website platform).
Every source publishes events differently, so each needs its own reader.
Claude (Sonnet)
The judge. Reads each listing and returns a structured verdict with a quote as evidence. Runs through Claude Code on my subscription.
"Is there food?" needs reading comprehension, not keyword matching. Requiring a quote keeps it honest.
An answer key
A set of listings I've judged by hand. Claude's verdicts are scored against them whenever I change the instructions.
You can't improve an AI step you can't measure.
GitHub
Stores the code and every day's events file, so there's a full history of what was published.
A file in git is simpler and cheaper than running a database.
Cloudflare Workers
Hosts crashers.app and serves the site from data centres close to each user. It redeploys on every push.
Fast, free at this scale, and nothing to maintain.
Leaflet + MapLibre
The map, drawn with free OpenFreeMap tiles.
A good map without paying Google per view.
Capacitor
Wraps the web app as an iPhone and Android app (currently in testing), adding local reminders.
One codebase for the web and both app stores.
Trade-offs I chose
- The daily run lives on my laptop, not a cloud server. That's free and uses my Claude subscription instead of a paid API, but a day is skipped if the laptop is off all day.
- Claude only sees new or edited listings, and old verdicts are never overwritten, so each day's cost stays small.
- No accounts means nothing to sign up for and no personal data to protect. The trade-off is that saved events don't sync between devices.