Add an achievements system and give rider cards and pack openings a livelier, rarity-driven visual overhaul.
- Feature Rider cards now have a distinct look per rarity tier (flat for Common, a glow for Rare/Epic, an animated pulsing border for Legendary/All-Star), a holographic foil shine on Epic+ cards, and a subtle 3D tilt on hover (cards with an action button scale up slightly instead, so the button stays easy to hit).
- Feature Reworked the pack-opening reveal: the pack now shakes, tears open, and the card tosses and flips into view with stats counting up (highest first) — pulling a Legendary or All-Star rider triggers a confetti burst and dims the page to spotlight the reveal. The navbar and footer hide for the duration (reappearing once you continue to the full results), the rest of the pack's cards then slide in one by one instead of all at once, and riders (both new pulls and duplicates) are sorted by rarity, then overall rating.
- Feature Converting a duplicate rider into shards now shows a brief "converted" message with an Undo button, so an accidental conversion can be reversed within a few seconds.
- Feature Race previews are now available in Dutch on
/nl/preview/....
- Change Race previews now weigh how riders have performed so far in this specific race (current GC standing, stage results already achieved) as the top factor, ahead of generic recent form and raw stats.
- Change Race preview write-ups now cite specific past wins by race and stage instead of vague averages or ratios.
- Change Various improvements to the race and stage scrapers, mainly performance.
- Change The favorite-star toggle no longer appears on rider cards in the Riders (dashboard) page.
- Fixed The last stages of stage races that turn out to have less stages, are now automatically removed.
- Fixed Race stage profile images now load faster on repeat visits.
- Fixed Fixed a performance issue where the home page, races page, and claiming race rewards could become very slow (and occasionally slow down other pages too) when a race's results stayed incomplete for a long time.
- Feature Added an Achievements system — tiered badges for race wins, top-3/top-5/top-10 stage finishes, perfect-score stages, riders crafted, teams completed, and packs opened, viewable on the new Achievements page and on player profiles.
- Feature Achievement badges for race wins, perfect stages, and teams completed now appear next to usernames on rankings, race results, and the home page.
- Change Objectives and Achievements are now combined under a single Progress menu.
- Change Ranking point totals now show as plain bold numbers with thousands separators instead of a pill badge.
Version 2026.25.2:
- Change Further reduced scraper proxy bandwidth usage: stages outside a run's date window are no longer re-fetched just to read their date, race results scraping now skips stages that haven't started yet, and preview generation enforces its PCS rider-lookup cap across an entire run instead of per stage.
Version 2026.25.3:
- Change Scrapers no longer download images, fonts, stylesheets, or media while reading race/stage/result pages, cutting proxy bandwidth usage further.
Version 2026.25.4:
- Change Race results scraping now checks a stage's startlist for dropped-out riders at most once per day instead of on every run, further cutting proxy bandwidth usage.
Version 2026.25.5:
- Change Scrapers now retry a failed cheap page fetch once before falling back to the more expensive full browser fetch, avoiding unnecessary proxy bandwidth on transient network blips.
Version 2026.25.6:
- Fixed Fixed a bug where a single momentary proxy hiccup during scraping would abandon the proxy for the rest of that run, causing most races' startlists/results to fail to update for that run.
Version 2026.25.7:
- Fixed Fixed a bug where a stage whose page temporarily failed to load during a scrape could be wrongly treated as removed from the race calendar, wiping its startlist, results, and any submitted teams for it. Scraping a stage now also never deletes a stage that still has a submitted team.
Version 2026.25.8:
- Change Internal: scraper Discord alerts now group errors by type and summarize routine retry noise instead of dumping raw log lines, so a critical warning can no longer get silently cut off by a long run's Cloudflare retry spam.
Version 2026.25.9:
- Feature Internal: added an automated health check that flags any stage starting soon with a suspiciously empty startlist, so a scraping gap surfaces as an alert instead of a player report.
Version 2026.25.10:
- Fixed Fixed a bug where a partial/broken startlist fetch could wipe most of a stage's real startlist in one write. That write is now always blocked instead, regardless of scrape mode.
Version 2026.25.11:
- Change Internal: production scraper scheduling now enforces a cooldown between pipeline runs, preventing back-to-back scraping bursts with no rest between them during periods of heavy blocking.
Version 2026.25.12:
- Fixed Fixed a bug where a race's startlist stopped updating entirely once the race began, permanently leaving later stages empty (e.g. the Vuelta a España).
- Change Internal: replaced the scraper's Playwright-based Cloudflare bypass with Bright Data's Web Unlocker API after Cloudflare started blocking every headless-browser request regardless of source IP, and manually refreshed the Vuelta a España's startlists/results.
Version 2026.25.13:
- Change Internal: each scraper run now logs a fetch-usage breakdown (requests/bytes per IPRoyal vs. Bright Data, by PCS page type) to help spot which step is driving proxy/API cost.
Version 2026.25.14:
- Fixed Internal: fixed the new fetch-usage breakdown (2026.25.13) being silently dropped from production's scraper logs instead of printed.
Version 2026.25.15:
- Change Internal: the race/stage scraper no longer re-fetches a stage's or one-day race's metadata page once it has already started (previously only skipped once its date was 2+ days in the past), and no longer re-fetches a one-day race's page unconditionally on every run at all - cutting proxy/API request volume.
Version 2026.25.16:
- Fixed Internal: a fetch that "succeeds" with an empty body (seen briefly overnight on 2026-09-01) is now treated as a failure and retried/escalated, instead of silently being handed to the scraper as if it were a real (empty) page.
- Change Internal: Bright Data's own API gateway failing (exhausted credits, billing, a broken key) is now detected and alerted on separately from PCS/Cloudflare blocking us.
Version 2026.25.17:
- Fixed Internal: a scraper full-refresh scoped to specific races/stages (
--race-ids/--stage-ids) no longer recreates the entire underlying table, which previously wiped every other race's data. Restored the results data lost this way on 2026-08-31/09-01 from backup.
Version 2026.25.18:
- Change Internal: a results full-refresh scoped to specific races/stages now explicitly drops and rebuilds just that race's results up front, instead of relying only on each stage's own incremental refresh.
Version 2026.25.19:
- Fixed A race that gets cancelled on PCS after it was already scraped is now automatically removed (race, stages, startlists, results) instead of lingering in the calendar forever. Removed the fully-cancelled Maryland Cycling Classic.
Version 2026.25.20:
- Fixed Sped up page loads on mobile: the site logo was being served far larger than it's ever displayed, and two scripts were blocking the page from rendering until they finished loading.
Version 2026.25.21:
- Change Internal: documented the automated production deployment pipeline in CLAUDE.md/AGENTS.md.
Version 2026.25.22:
- Change Every page now loads noticeably faster: the server was serving CSS/JS/HTML uncompressed and over HTTP/1.1 only — enabled gzip compression and HTTP/2.
Version 2026.25.23:
- Change Redesigned the homepage hero for logged-out visitors: removed the logo image and sized Craft your Dream Team. as the largest headline with Score on Real Races. underneath it.
Version 2026.25.24:
- Fixed Fixed a bug where the daily Instagram preview carousel's caption could occasionally name a stale top favorite (e.g. one no longer in the race) even though the carousel images themselves were showing the correct, up-to-date favorites.
- Change Internal: race preview generation now retries less often by fixing an AI output schema ambiguity that was causing the "star rating" field to occasionally come back as text instead of a number, and added logging to make any recurrence of this visible without enabling verbose mode.
- Change Internal: the results scraper no longer logs a "results not found" error for a stage that's still likely racing (within 5 hours of its start), only once that grace period has passed.
Version 2026.25.25:
- Feature The Instagram preview carousel's cover image for a General Classification preview now lists every stage of the race (number, terrain icon, and start/finish towns), laid out in two columns for Grand Tours, plus the race's full start-end date range.