Oktoberfest Notification Bot
A headless Playwright bot that monitors 5 Oktoberfest tent reservation portals
Vote to see the stats!
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What This Is
A headless Playwright bot that monitors 5 Oktoberfest tent reservation portals every 2 hours, detects when Friday evening / Saturday / Sunday slots become available, and sends a macOS notification. It runs as a launchd agent -- zero resources between checks.
This was built entirely with Claude Code as a real-world example of AI-assisted automation. The goal: never miss a weekend Oktoberfest reservation slot.
Commands
npm run check # Run a single check manually
bash install.sh # Install launchd agent (runs every 2 hours + on login)
launchctl list | grep oktoberfest # Verify the agent is loaded
How It Works
check.mjs is the entire bot -- one file, no framework:
- Launches headless Chromium (single instance, reused across all tents)
- Visits each tent's reservation portal sequentially
- Each tent has a dedicated checker function because the portals differ:
- Schutzenfestzelt -- Nuxt SPA, waits for hydration, reads
select.form-selectoptions - Armbrustschutzenzelt -- Requires login (credentials from
.env), then reads date options - Fischer Vroni -- Page exists but is empty; detects when a reservation form appears
- Ochsenbraterei -- Portal says "noch geschlossen"; detects when that message disappears
- Braeurosl -- Laravel Livewire/Filament, reads
select.fi-select-inputoptions
- Schutzenfestzelt -- Nuxt SPA, waits for hydration, reads
- Filters dates for Freitag/Samstag/Sonntag
- Compares against
~/.oktoberfestbot/state.jsonto find NEW slots only - Sends macOS notification via
osascriptif new target dates found - Logs everything to
~/.oktoberfestbot/check.log
All tents use the "Festzelt OS" platform but with two different frontends (Nuxt vs Laravel Livewire/Filament) and varying states of readiness.
Key Design Decisions
- Sequential tent checks, not parallel -- Avoids overwhelming the shared platform and keeps memory low (one page at a time)
- State diffing -- Only notifies on NEW Fri/Sat/Sun dates, not ones already seen. Prevents notification spam on every run.
- Graceful degradation -- If a tent check fails (network error, selector changed), the error is logged but other tents still get checked. Previous state is preserved for failed tents.
- No cookies/cookie consent handling needed -- None of these portals show cookie banners. Do NOT add cookie dismissal logic.
Adding a New Tent
- Add an entry to the
TENTSarray withid,name,url, andcheckfunction - Write a
checkTentName(page)function that returns one of:{ type: "dates", dates: ["Freitag, 25.09.2026", ...] }-- date option text must include German day names{ type: "closed" }-- portal not yet open{ type: "no-form" }-- page exists but no reservation form{ type: "form-appeared" }-- form detected but no date options yet{ type: "error", message: "..." }-- something went wrong
- Before writing the checker, visit the portal with Playwright MCP browser to inspect the actual DOM -- these sites change without notice
File Layout
check.mjs-- The entire bot.env-- Armbrustschutzenzelt login credentials (gitignored)com.oktoberfestbot.check.plist-- launchd agent template (install.sh adapts paths)install.sh-- One-time setup: creates~/.oktoberfestbot/, installs and loads the launchd agent~/.oktoberfestbot/state.json-- Persisted state (last-seen dates per tent)~/.oktoberfestbot/check.log-- Append-only log of every check run
Reproducing This Project From Scratch
This bot was built with Claude Code in one session. Here's how to build your own version for any reservation/availability monitoring task:
-
Tell Claude Code what you want to monitor. Be specific: which URLs, what you're looking for, how you want to be notified. Example prompt:
"I want to monitor these 5 Oktoberfest tent reservation pages for when Friday/Saturday/Sunday slots become available. They all use the Festzelt OS platform. Some require login, some aren't open yet. Notify me via macOS notification."
-
Let it explore the sites first. Claude Code will use Playwright to visit each URL, inspect the DOM structure, and understand what selectors to use. This is critical because SPAs and server-rendered pages look completely different under the hood.
-
It builds the checker. One script, tent-specific logic per portal, state management to avoid duplicate notifications, and macOS scheduling via launchd.
-
Test it live. Run once manually, verify the output makes sense, then install the scheduler.
The same pattern works for any "check a website periodically and alert me" task -- concert tickets, apartment listings, appointment slots, product restocks. Swap the URLs, adjust the selectors, change the notification method.