Skip to content

Claude/venue carousel tracker t jqgf#1

Open
Lmhgn wants to merge 15 commits intomainfrom
claude/venue-carousel-tracker-TJqgf
Open

Claude/venue carousel tracker t jqgf#1
Lmhgn wants to merge 15 commits intomainfrom
claude/venue-carousel-tracker-TJqgf

Conversation

@Lmhgn
Copy link
Owner

@Lmhgn Lmhgn commented Mar 1, 2026

No description provided.

claude added 10 commits March 1, 2026 14:33
Scrapes homepage carousel tiles for all 20 O2 Academy venues and Edinburgh
Corn Exchange, surfaces outdated and expiring-soon tiles on a live dashboard,
and sends alerts via email, Slack, and/or webhook when tiles need replacing.

- server.js: Express server with axios+cheerio scraping, hourly cron job,
  SSE real-time updates, and nodemailer/Slack/webhook notifications
- public/index.html: Dashboard with summary bar, filter buttons, and venue cards
- public/app.js: SSE client, browser notifications, filter/refresh UI
- public/style.css: Colour-coded status indicators (red/orange/green)
- .env.example: SMTP, Slack, and webhook configuration template

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
Replaces the Node.js server with a standalone index.html that works by
opening directly in any browser — no install or server required.

- Uses allorigins.win as a CORS proxy to fetch venue pages client-side
- DOMParser replaces cheerio for HTML parsing (same selectors)
- Skeleton cards render immediately while venues load in batches of 4
- Browser Notifications API for desktop alerts
- Slack and generic webhook support via settings panel (localStorage)
- Configurable warning threshold (default 7 days)
- Auto-refreshes every hour via setTimeout

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
Replaces the single allorigins.win proxy with an ordered fallback chain:
corsproxy.io → allorigins (JSON) → codetabs. Each venue request tries
all three in sequence before failing. Added AbortController timeout
(18 s per attempt) and a custom proxy URL option in Settings.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
parseAMG now scans both carousel-slide elements AND the
module-content-list-large/medium/small sections that carry the full
event listing (16 events on O2 Ritz vs 6 from the carousel alone).
Items with no parseable date are skipped to filter out navigation links
that share the same selector. Deduplication prevents double-counting
events that appear in both sections.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
…d more

Features added:
- Sort tiles by date ascending within every venue card
- Per-venue ↺ refresh button (event delegation, skips full scan)
- Cross-venue Events tab — flat date-sorted table of all events across
  all venues, filtered by the same status pills and search box
- Artist/venue search — live-filters both card and events views
- Configurable auto-refresh interval (off / 15 min / 30 min / 1h / 2h)
  replacing the hardcoded 1-hour timer; footer label updates dynamically
- Change detection — compares each scan against the previous (persisted
  in localStorage); NEW badge on new tiles, REMOVED tiles shown
  struck-through, changes summary in card footer
- Relative scan-age per card ("Checked 4m ago"), turns amber after 3h
  and refreshes every 30s without re-rendering
- Export CSV button (header + footer) — downloads all events with venue,
  artist, date, status, days-until, and is-new columns
- Total Events counter added to summary bar
- Settings modal now includes auto-refresh interval select

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
These are automatic content feeds, not manually maintained carousel
tiles, so flagging them as outdated would be misleading.

Added buildExcludedItems(doc): scans the parsed DOM for h1-h4 headings
matching "What's New" or "Coming up" (handles straight and curly
apostrophes), walks up to find the containing module, and marks every
module-content-list-item inside it as excluded.

Both parseAMG and parseECE now call buildExcludedItems and skip any
item in the returned Set before adding a tile.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
- Add user authentication with bcrypt password hashing and express-session
- Add SQLite database for persistent storage (users, venues, catalogue)
- Add venue catalogue with add/remove/manage functionality
- Add Server-Sent Events (SSE) for real-time scraping progress updates
- Add db/ directory to .gitignore
- Update dependencies: bcryptjs, better-sqlite3, express-session

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
Adds Node.js engines field so Railpack detects the app correctly,
and nixpacks.toml to provide gcc/python build tools for better-sqlite3.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
@railway-app railway-app bot temporarily deployed to honest-fascination / production March 3, 2026 08:20 Inactive
Railway's nginx proxy buffers SSE responses by default, causing the
dashboard to stay stuck on "Starting up..." after login. This header
disables proxy buffering so events flow through immediately.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
@railway-app railway-app bot temporarily deployed to honest-fascination / production March 5, 2026 11:31 Inactive
The page was calling the old client-side CORS proxy scraper (startScrape)
at init, which conflicted with the server-side SSE system. Both shared
the isScraping flag, causing the dashboard to stay stuck on "Starting up..."
after login. Now the page calls initApp() which checks auth and connects
to the server SSE, and auto-refresh uses triggerRefresh() (server API)
instead of the client-side scraper.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
@railway-app railway-app bot temporarily deployed to honest-fascination / production March 5, 2026 11:45 Inactive
SSE on Railway can be delayed or dropped before the first event arrives,
leaving the dashboard stuck on "Starting up...". After login (and on page
load if already authenticated), immediately fetch /api/status via a normal
HTTP request to render the current state, then use SSE only for live
real-time updates.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
@railway-app railway-app bot temporarily deployed to honest-fascination / production March 5, 2026 11:53 Inactive
In-memory sessions are lost on every process restart (deploy, crash).
Replace the default MemoryStore with a minimal SQLite-backed store using
the already-available better-sqlite3 connection, so sessions survive
restarts. Also add app.set('trust proxy', 1) so Express correctly reads
X-Forwarded-Proto from Railway's edge proxy.

On the client, show an error banner if /api/status fails instead of
silently swallowing the error and leaving the grid stuck on "Starting up...".

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
@railway-app railway-app bot temporarily deployed to honest-fascination / production March 5, 2026 12:31 Inactive
Railway's HAProxy terminates long-lived SSE connections. After 3 consecutive
SSE errors the client now switches to polling /api/status every 20 s instead
of showing a permanent "Connection lost" banner. SSE ping interval also
reduced from 25 s to 15 s to stay well under Railway's 60-second idle
timeout so SSE works if the proxy allows it.

https://claude.ai/code/session_01JoKM72wEiTc7vswPJGxsSM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants