Club Records Snap
WordPress plugin: athletics club age-group records va legacy seed plus Claude vision OCR of Power of 10 creenshots.
by Brentwood Beagles Athletics Club · github.com/ecaveo/club-records-snap · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/ecaveo/club-records-snap/archive/refs/heads/main.zipA WordPress plugin that maintains an athletics club's age-group records via a simple workflow: import legacy Ninja Tables records once, then keep them current by dropping Power of 10 screenshots into the plugin — Claude vision OCR extracts the new performances, you review and confirm, the records table updates.
Built for Brentwood Beagles AC after the agent-driven scraper approach proved fragile (CAPTCHA gates, stuck job queues, 200+ tool calls per session). This plugin replaces that complexity with: human-takes-screenshot → human-drops-into-plugin → AI-extracts → human-confirms.
Why not just scrape Power of 10?
Po10's ranking endpoints are protected by hCaptcha, the data is rendered client-side, and the page state machine doesn't expose deep links. Any server-side scraper gets blocked on first request. The previous plugin attempted to drive a Claude-in-Chrome agent through the queue manually but ran into stuck jobs, context exhaustion, and a slow grind for not-much-value-per-event.
Screenshots sidestep every one of those problems: you screenshot once per event/year/sex view that you care about, drop it in, and the plugin does the rest.
Architecture
Single records table, single workflow:
wp_crs_records — one row per (sex, age_group, event) cell
wp_crs_uploads — audit log of every screenshot processed
The UKA Competition Rules eligibility matrix (TR3 S2 + TR3 S4) is built in — disallowed cells like U14 Marathon, U14 Triple Jump, U16 race over 3000m, U18 Marathon never render in the public table.
Workflow
- Settings → Claude API key (get one at console.anthropic.com). Defaults to Claude Haiku 4.5 — fast, accurate enough, ~$0.001 per screenshot.
- Dashboard → Run seed — imports the legacy Ninja Tables records from beagles.org.uk (tables 9354 / 9359) into the new schema. Picks the best historical performance per cell.
- Upload Screenshot → drop a Po10 rankings screenshot → Claude returns a JSON list of rows → the review screen shows CREATE / UPDATE / SKIP (UKA) / SKIP (wind) / SKIP (not better) for each candidate vs your existing records.
- Records → manually edit, delete, or add. Tick "Lock" to mark a record as manual-override so screenshot updates can't overwrite it.
- Public site → drop
[crs_records]on any page. Built-in W/M/All radio filter and hide-empty toggle.
Installation
- Download the latest
club-records-snap-v1.0.0.zip. - wp-admin → Plugins → Add New → Upload Plugin → choose the zip → Install Now → Activate.
- Navigate to "Club Records" in the admin menu.
Settings
| Field | Purpose |
|---|---|
| Club name / short | Branding |
| Record colour | Hex code for the performance text on the public table |
| Performances since | Date the club started (default 2022-01-01) |
| Claude API key | sk-ant-... — stored in wp_options.crs_settings |
| Model | Haiku 4.5 / Sonnet 4.6 / Opus 4.6 |
| Ninja Tables endpoint + IDs | For one-off legacy seed |
File layout
club-records-snap/
├── club-records-snap.php bootstrap, helpers, settings, UKA filter
├── readme.txt
├── README.md
├── uninstall.php
├── includes/
│ ├── class-crs-activator.php DB schema
│ ├── class-crs-perfvalue.php performance string parser
│ ├── class-crs-records.php single-table CRUD
│ ├── class-crs-seeder.php legacy Ninja Tables import (TESTED)
│ ├── class-crs-claude.php Anthropic Messages API wrapper
│ ├── class-crs-snap.php screenshot → candidates → review
│ ├── class-crs-admin.php wp-admin menu + handlers
│ └── class-crs-shortcode.php public renderer
├── admin/
│ ├── views/{dashboard,upload,review,records,settings}.php
│ └── assets/{admin.css,admin.js}
└── public/assets/public.css
Shortcodes
[crs_records] # default: both sexes with W/M/All radio
[crs_records gender="women"] # women only
[crs_records gender="men"] # men only
[crs_records hide_empty="0"] # show every cell even when empty
[crs_records filter="0"] # hide the text search box
Differences from the old plugin (Athletics Club Records)
| Aspect | Old plugin | This plugin |
|---|---|---|
| Po10 sync | Agent-driven scraping with CAPTCHA solving | Manual screenshots + Claude OCR |
| Queue | Persistent jobs table, stuck-claimed bugs | None |
| Schema | 4 tables (records, performances, athletes, jobs) | 2 (records, uploads audit) |
| Setup | Plan refresh → SOP prompt → Claude in Chrome | Paste API key → drop screenshots |
| Per-record time | ~5 tool calls + captcha solving | One drop, one click |
Licence
GPL-2.0-or-later.