FullOut

Changelog

Track all updates, improvements, and fixes to FullOut

Latest

Version 0.2.587

fix(college): reparent 26 orphaned college teams off the "Unknown" bucket into real universities

July 9, 2026 at 8:57 PM GMT+0
7c3ad030
🐛Fixed
  • fix(college): reparent 26 orphaned college teams off the "Unknown" bucket into real universities
  • The /college hub's "Most Active Programs" was topped by a junk placeholder gym
  • named "Unknown" (mistyped ALLSTAR_GYM) holding 26 college teams whose names are
  • actually their universities (USC, Portland State, New Mexico State, ...). They
  • were imported without a matched university and fell into the catch-all.
  • scripts/maintenance/reparent-unknown-college-teams.ts (audited, idempotent, dry-run

Files Changed

Created (1):
  • + scripts/maintenance/reparent-unknown-college-teams.ts
Modified (2):
  • ~ scripts/maintenance/reparent-unknown-college-teams.ts
  • ~ src/lib/hubs/hub-data.ts

Version 0.2.586

feat(admin): title /admin/partners "Partners" and badge each row Event Producer vs Affiliate

July 9, 2026 at 7:46 PM GMT+0
fa105792
🔄Changed
  • feat(admin): title /admin/partners "Partners" and badge each row Event Producer vs Affiliate
  • The list mixed EP-linked partners (e.g. Redline) with pure affiliates and
  • called them all "Affiliate Partners". Renamed the page to "Partners" and added
  • a Type column badging each row Event Producer (has eventProducerId) or Affiliate.
  • Claude-Session: https://claude.ai/code/session_01Qz5BcppF3gPYrvFJmV7BnX

Files Changed

Modified (1):
  • ~ src/app/admin/partners/page.tsx

Version 0.2.585

feat(admin): cross-link Partner <-> EventProducer consoles; resolve EP page by id/slug too

July 9, 2026 at 7:00 PM GMT+0
e20985b3
🔄Changed
  • feat(admin): cross-link Partner <-> EventProducer consoles; resolve EP page by id/slug too
  • Redline (and any EP-linked partner) exists as two linked admin records, which
  • made the admin trees feel scattered. Now:
  • Admin partner page shows a "Manage as Event Producer" button when the partner
  • has a linked EP; the EP page shows an "Affiliate & payouts" button back.
  • /admin/event-producers/[id] resolves a subscription id (as before) OR the

Files Changed

Modified (2):
  • ~ src/app/admin/event-producers/[id]/page.tsx
  • ~ src/app/admin/partners/[id]/page.tsx

Version 0.2.584

feat: discipline data-quality loops (placement, dedup, division reclassification)

July 9, 2026 at 6:38 PM GMT+0
fa82fa2e
🔄Changed
  • feat: discipline data-quality loops (placement, dedup, division reclassification)
  • Six new clean-data assertions with staged fixes: team-discipline-mismatch,
  • division-discipline-misclass (prep->AllStar, junior high/crowdleader->School,
  • variety/jazz->Dance, with collision merges), competition-discipline majority
  • vote, gym-discipline-links backfill, multi-discipline-teams and
  • unregistered-disciplines monitors. duplicate-teams is now discipline-aware

Files Changed

Created (7):
  • + scripts/debug/probe-dance-event-divisions.ts
  • + scripts/debug/probe-dance-token-divisions.ts
  • + scripts/debug/probe-discipline-placement.ts
  • + scripts/debug/probe-division-misclass.ts
  • + scripts/debug/probe-empty-competitions.ts
  • + scripts/debug/probe-multi-discipline-teams.ts
  • + scripts/maintenance/recompute-competition-disciplines.ts
Modified (12):
  • ~ scripts/debug/probe-dance-event-divisions.ts
  • ~ scripts/debug/probe-dance-token-divisions.ts
  • ~ scripts/debug/probe-discipline-placement.ts
  • ~ scripts/debug/probe-division-misclass.ts
  • ~ scripts/debug/probe-empty-competitions.ts
  • ~ scripts/debug/probe-multi-discipline-teams.ts
  • ~ scripts/maintenance/delete-empty-disciplines.ts
  • ~ scripts/maintenance/recompute-competition-disciplines.ts
  • ~ src/lib/data-quality/assertions.ts
  • ~ src/lib/data-quality/fixes.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/import/schedule-import.ts

Version 0.2.583

feat(profile): free parent/child account linking (reuse PersonRelationship)

July 9, 2026 at 6:37 PM GMT+0
32ae56e8
🔄Changed
  • feat(profile): free parent/child account linking (reuse PersonRelationship)
  • Parents can link to their athlete kids without either account paying. Reuses the existing PersonRelationship model + request/approve flow instead of a new table; only the Elite gating and UI mounting are new.
  • src/lib/relationships.ts: isGuardianRelationship + effectiveRelationshipLimits + free tier-independent limit floor (parent/child only)
  • relationships POST/PATCH/GET: parent/child skip the both-sides Elite gate; guardian links active when accepted regardless of tier
  • people/[username]: mount RelationshipButton + RelationshipsSection, seeded via cached getProfileViewer
  • spouse/partner/family unchanged (still Elite)

Files Changed

Created (1):
  • + src/lib/relationships.ts
Modified (4):
  • ~ src/app/api/person/[id]/relationships/[relationshipId]/route.ts
  • ~ src/app/api/person/[id]/relationships/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/lib/relationships.ts

Version 0.2.582

docs: FOV IAP + App Store approval status and handoff

July 9, 2026 at 5:00 PM GMT+0
b17cdbd1
🔄Changed
  • docs: FOV IAP + App Store approval status and handoff
  • Compact record of what's done, current state, and the two remaining blockers
  • (Vercel REVENUECAT_SECRET_API_KEY + IAP review screenshot) so work can resume.
  • Claude-Session: https://claude.ai/code/session_01SWcAqsXEBQ2XSy5Cqit6dd

Version 0.2.581

feat(ep): landing-page traffic + acquisition funnel on EP program dashboard

July 8, 2026 at 11:50 PM GMT+0
83110a08
🔄Changed
  • feat(ep): landing-page traffic + acquisition funnel on EP program dashboard
  • Gives event producers real performance insight: how many people hit their
  • pages and where they come from. New GA4-backed section on
  • /event-producers/[slug]/program showing, for the producer's /<slug> landing
  • page and any ?p=<slug> ref link:
  • volume tiles (page views, visitors, new visitors, sessions) vs prior period

Files Changed

Created (2):
  • + src/components/event-producers/ep-traffic-section.tsx
  • + src/lib/ep-traffic-analytics.ts
Modified (3):
  • ~ src/app/event-producers/[slug]/program/page.tsx
  • ~ src/components/event-producers/ep-traffic-section.tsx
  • ~ src/lib/ep-traffic-analytics.ts

Version 0.2.580

docs(brand): correct pink-SVG download label and asset-kit Redline logo reference

July 8, 2026 at 10:44 PM GMT+0
9a1fc4ea
🔄Changed
  • docs(brand): correct pink-SVG download label and asset-kit Redline logo reference
  • /brand: the pink wordmark SVG is a scalable raster embed, not a true vector;
  • relabel the download from "Vector source" to "Scalable wordmark".
  • asset-kit: Redline's white logo now ships in-repo (public/Logos/redline-logo-white.svg)
  • and on /redline; note that instead of "get it from Kevin's team".
  • Claude-Session: https://claude.ai/code/session_01Qz5BcppF3gPYrvFJmV7BnX

Files Changed

Modified (1):
  • ~ src/app/brand/page.tsx

Version 0.2.579

fix(brand): rebuild fullout-pink.svg without mask-seam artifacts; add Redline logo to /redline

July 8, 2026 at 10:38 PM GMT+0
96349b42
🐛Fixed
  • fix(brand): rebuild fullout-pink.svg without mask-seam artifacts; add Redline logo to /redline
  • The pink wordmark SVG was a Figma export of 8 raster letter-images used as
  • alpha masks over a full-bleed pink rectangle; the mask/pattern tile seams
  • rendered as stray pink lines in the download. Rebuilt as a clean single-image
  • SVG wrapping the high-res FullOut - Pink.png (2984x767) — same look, no seams.
  • /redline: add Redline Championships' own logo (redline-logo-white.svg) to the

Files Changed

Modified (1):
  • ~ src/app/redline/page.tsx

Version 0.2.578

feat(partners): hide redundant Affiliate tab for EP-linked partners; generalize commission-defaults button; GTM doc fixes

July 8, 2026 at 10:25 PM GMT+0
9f5b9371
🔄Changed
  • feat(partners): hide redundant Affiliate tab for EP-linked partners; generalize commission-defaults button; GTM doc fixes
  • settings: only show the standalone Affiliate tab for pure affiliates
  • (Partner.eventProducerId == null). EP-linked partners (e.g. Redline) see
  • the same ledger inside their richer EP Program dashboard, so the second
  • tab was redundant.
  • admin: rename "Apply FullOut x LTC defaults" button (and applyLtcSchedule

Files Changed

Modified (3):
  • ~ src/app/settings/page.tsx
  • ~ src/components/admin/partner-form.tsx
  • ~ src/components/admin/partners/commission-rate-editor.tsx

Version 0.2.577

refactor(mobile): FOV IAP uses a single consumable product for all levels

July 8, 2026 at 10:07 PM GMT+0
2df04d2e
🔄Changed
  • refactor(mobile): FOV IAP uses a single consumable product for all levels
  • One "fov_verification" consumable covers any level (the chosen level is passed
  • to the backend grant), instead of 8 per-level products. Fewer App Store Connect
  • products to create + review, same result.
  • Claude-Session: https://claude.ai/code/session_01SWcAqsXEBQ2XSy5Cqit6dd

Version 0.2.576

feat(brand): update brand-page core palette to 8 colors; use "Redline Championships" on /redline

July 8, 2026 at 9:55 PM GMT+0
ff09f4ce
🔄Changed
  • feat(brand): update brand-page core palette to 8 colors; use "Redline Championships" on /redline
  • /brand: replace 3-swatch Core palette with the 8 approved core colors
  • (Cyan, FullOut Pink, Black, White, Ice, Blush, Ink, Mist) in a 4x2 grid;
  • accents unchanged. Fix accessibility note Ink hex to #261F27.
  • /redline: use full partner name "Redline Championships" throughout.
  • Claude-Session: https://claude.ai/code/session_01Qz5BcppF3gPYrvFJmV7BnX

Files Changed

Modified (2):
  • ~ src/app/brand/page.tsx
  • ~ src/app/redline/page.tsx

Version 0.2.575

feat(mobile): FOV Apple IAP purchase flow + web handoff

July 8, 2026 at 9:53 PM GMT+0
5f5491d9
🔄Changed
  • feat(mobile): FOV Apple IAP purchase flow + web handoff
  • purchases.ts: getFovOffering() + purchaseFovPackage() (consumable, returns the
  • StoreKit transaction id for server-side grant).
  • api.ts: grantFovUnlock() -> POST /api/skills/iap/grant.
  • New native FOV screen (app/(main)/fov.tsx): reads personId + levels handed off
  • from the WebView, buys one consumable per level, grants the unlock.

Files Changed

Modified (1):
  • ~ src/components/people/unlock-levels-dialog.tsx

Version 0.2.574

fix(security): verify IAP receipt server-side + ownership check on FOV grant

July 8, 2026 at 7:04 PM GMT+0
f599c202
🐛Fixed
  • fix(security): verify IAP receipt server-side + ownership check on FOV grant
  • Harden POST /api/skills/iap/grant per security review:
  • Verify the Apple transaction with RevenueCat's REST API server-side (fail
  • closed if unconfigured or not found) instead of trusting the client's claim —
  • closes a free-unlock trust-boundary bypass.
  • Require the caller to own the athlete (person.userId === caller), mirroring

Files Changed

Modified (1):
  • ~ src/app/api/skills/iap/grant/route.ts

Version 0.2.573

feat: FOV Apple IAP grant endpoint + appleTransactionId (Verified IAP foundation)

July 8, 2026 at 6:58 PM GMT+0
9be7d992
🔄Changed
  • feat: FOV Apple IAP grant endpoint + appleTransactionId (Verified IAP foundation)
  • Add appleTransactionId (nullable, indexed, deduped in code) to
  • SkillLevelPurchase for Apple In-App Purchase records.
  • New POST /api/skills/iap/grant: grants a SkillLevelUnlock from a native
  • RevenueCat IAP purchase, idempotent on the Apple transaction, guarding
  • already-unlocked levels. Web (Stripe) and in-app (IAP) purchases now both

Files Changed

Created (1):
  • + src/app/api/skills/iap/grant/route.ts
Modified (2):
  • ~ prisma/schema.prisma
  • ~ src/app/api/skills/iap/grant/route.ts

Version 0.2.572

feat: attribute Apple IAP/RevenueCat conversions to partners

July 8, 2026 at 1:35 AM GMT+0
14182c16
🔄Changed
  • feat: attribute Apple IAP/RevenueCat conversions to partners
  • Wire the RevenueCat webhook into the commission engine so in-app
  • purchases credit the buyer's durable origin partner (Redline): first
  • purchase, renewals capped at 36 months, and 60-day refund clawbacks, on
  • a net-of-Apple revenue basis. Adds PartnerCommission.externalPaymentId
  • for IAP payment dedup. Dark behind IAP_ATTRIBUTION_ENABLED until the

Files Changed

Created (2):
  • + src/lib/__tests__/iap-attribution.test.ts
  • + src/lib/iap-attribution.ts
Modified (6):
  • ~ prisma/schema.prisma
  • ~ src/app/api/webhooks/revenuecat/route.ts
  • ~ src/lib/__tests__/iap-attribution.test.ts
  • ~ src/lib/iap-attribution.ts
  • ~ src/lib/origin-attribution.ts
  • ~ src/lib/partner-attribution.ts

Version 0.2.571

fix: prevent a producer from being its own broker

July 8, 2026 at 1:35 AM GMT+0
df725e2f
🐛Fixed
  • fix: prevent a producer from being its own broker
  • Skip the broker override when the broker is the EP's own partner, so an
  • EP that is also a broker (Redline) never double-earns direct rev share
  • plus a broker override on its own conversions. Enforced at the settlement
  • chokepoint and rejected at the admin write path.
  • Claude-Session: https://claude.ai/code/session_01W9vPhHp47P93n6HHLsPcn2

Files Changed

Modified (2):
  • ~ src/app/api/admin/event-producers/[id]/route.ts
  • ~ src/lib/ep-settlement.ts

Version 0.2.570

feat: attribution-only partner promo codes at checkout

July 8, 2026 at 1:35 AM GMT+0
2c3e2782
🔄Changed
  • feat: attribution-only partner promo codes at checkout
  • A 0-discount partner promo code (e.g. base REDLINE) now attributes the
  • partner without attaching an invalid 0% Stripe coupon, at both new
  • checkout and in-app plan change. Enables handing out an attribution-only
  • code alongside discount codes like REDLINEPRO.
  • Claude-Session: https://claude.ai/code/session_01W9vPhHp47P93n6HHLsPcn2

Files Changed

Modified (2):
  • ~ src/app/api/stripe/change-plan/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts

Version 0.2.570

fix(hubs): bump hub-data cache key to v2 to bust stale Data Cache after the discipline-membership change

July 8, 2026 at 1:31 AM GMT+0
c2286a61
🐛Fixed
  • fix(hubs): bump hub-data cache key to v2 to bust stale Data Cache after the discipline-membership change
  • unstable_cache keys off keyParts, not the function body, and Vercel's Data Cache
  • persists across deployments, so the previous (Competition.disciplineId) results kept
  • serving on prod even after the query fix deployed. Versioning the key forces the new
  • deployment to recompute. Tags stay version-free so revalidateTag("hub:data") still
  • busts every hub on demand.

Files Changed

Modified (1):
  • ~ src/lib/hubs/hub-data.ts

Version 0.2.569

feat: /redline landing page with vanity-link attribution

July 8, 2026 at 1:34 AM GMT+0
7f93ebf6
🔄Changed
  • feat: /redline landing page with vanity-link attribution
  • Conversion-focused co-branded landing page for the Redline partnership.
  • Middleware tags a bare /redline visit to the Redline partner (same as
  • ?p=redline), so a printed QR or typed URL attributes on load. The redline
  • slug is reserved against usernames.
  • Claude-Session: https://claude.ai/code/session_01W9vPhHp47P93n6HHLsPcn2

Files Changed

Created (1):
  • + src/app/redline/page.tsx
Modified (3):
  • ~ src/app/redline/page.tsx
  • ~ src/lib/username-validation.ts
  • ~ src/middleware.ts

Version 0.2.569

feat(stunt): add discipline-filtered programs map to the STUNT hub

July 8, 2026 at 1:21 AM GMT+0
f3af5511
🔄Changed
  • feat(stunt): add discipline-filtered programs map to the STUNT hub
  • Brings the STUNT hub in line with the other discipline hubs, which each render a
  • gym map. Reuses the existing MapLibre GymsMap filtered to the STUNT discipline
  • (self-fetches /api/gyms/map?discipline=<id> client-side, ssr:false). STUNT programs
  • are colleges, so pin density depends on college geocoding coverage.
  • Claude-Session: https://claude.ai/code/session_016MBCg7qCGcjdaEhEVTY8wt

Files Changed

Modified (1):
  • ~ src/app/stunt/page.tsx

Version 0.2.568

feat(profile): make Experience athletic-only; close coach self-assign backdoors

July 8, 2026 at 1:19 AM GMT+0
9d30ba50
🔄Changed
  • feat(profile): make Experience athletic-only; close coach self-assign backdoors
  • Profile Experience is now athletic history only. Removed the free-text role picker (Athlete/Coach/Team Rep/Staff/Parent); coaching, staff, and parent belong to the Pro coach/choreo flow and guardian linking instead.
  • person-experience.tsx: drop role checkboxes; card title = position or Athlete
  • experience POST/PATCH: ignore incoming role, force TeamSeasonPerson ATHLETE (kills role=Coach backdoor)
  • team-seasons POST: clamp non-admins to ATHLETE (was arbitrary role self-assign)
  • remove dead AddTeamSeasonForm (unused coach self-assign UI)

Files Changed

Created (2):
  • + scripts/debug/audit-experience-roles.ts
  • + scripts/maintenance/delete-nonathletic-experience-roles.ts
Modified (7):
  • ~ scripts/debug/audit-experience-roles.ts
  • ~ scripts/maintenance/delete-nonathletic-experience-roles.ts
  • ~ src/app/api/person/[id]/experience/[experienceId]/route.ts
  • ~ src/app/api/person/[id]/experience/route.ts
  • ~ src/app/api/person/[id]/team-seasons/route.ts
  • ~ src/components/athletes/add-team-season-form.tsx
  • ~ src/components/people/person-experience.tsx

Version 0.2.568

fix(hubs): derive discipline hub competitions from Division.disciplineId, not Competition.disciplineId

July 8, 2026 at 1:21 AM GMT+0
93e17c96
🐛Fixed
  • fix(hubs): derive discipline hub competitions from Division.disciplineId, not Competition.disciplineId
  • Competition.disciplineId is NULL on ~40% of recent comps (507 since 2024), so the
  • hub Upcoming/Recent/Top Teams lists silently fell back to only the handful of old
  • (2000-2018) events that happened to be tagged. College recent results showed 2018
  • and earlier.
  • A competition now belongs to a hub if it has any performance in one of the hub's

Files Changed

Modified (1):
  • ~ src/lib/hubs/hub-data.ts

Version 0.2.567

@ feat: /disciplines landing page, choreographers + coaches in nav, gym map on discipline hubs

July 7, 2026 at 11:38 PM GMT+0
670b9093
🔄Changed
  • @ feat: /disciplines landing page, choreographers + coaches in nav, gym map on discipline hubs
  • feat: /disciplines landing page, choreographers + coaches in nav, gym map on discipline hubs
  • New /disciplines page with big gradient buttons (one per discipline), copy
  • and hero gradients sourced from the shared hub config.
  • Nav: add Choreographers and Coaches to the Explore group, and collapse the
  • seven discipline hub links into a single "Disciplines" entry (Explore group

Files Changed

Created (1):
  • + src/app/disciplines/page.tsx
Modified (3):
  • ~ src/app/disciplines/page.tsx
  • ~ src/components/hub/discipline-hub.tsx
  • ~ src/lib/nav-config.ts

Version 0.2.566

fix: add Restore Purchases to account menu, wired to native StoreKit (Apple 3.1.1)

July 7, 2026 at 10:55 PM GMT+0
115b2c0d
🐛Fixed
  • fix: add Restore Purchases to account menu, wired to native StoreKit (Apple 3.1.1)
  • Build 18 was rejected because Restore Purchases wasn't reachable after the
  • floating Upgrade button was removed. Add a distinct "Restore Purchases" item to
  • the web account menu (shown only inside the native WebView via
  • window.ReactNativeWebView) that navigates to an /app/restore sentinel; the iOS
  • WebView intercepts it and runs the native StoreKit restore. Upgrade stays in the

Files Changed

Modified (1):
  • ~ src/components/navbar.tsx

Version 0.2.565

feat: Verified in-person grant + payment-provider foundation (Verified IAP phase 1)

July 7, 2026 at 5:09 PM GMT+0
1de41538
🔄Changed
  • feat: Verified in-person grant + payment-provider foundation (Verified IAP phase 1)
  • Add PaymentProvider enum (STRIPE | APPLE_IAP | IN_PERSON) and paymentProvider
  • column to SkillLevelPurchase (existing rows default to STRIPE).
  • New admin API POST /api/admin/skills/grant-in-person: record a cash/manual
  • FullOut Verified sale and unlock levels for an athlete, skipping already-owned
  • levels. Bypasses Stripe and Apple IAP (no Apple cut).

Files Changed

Created (2):
  • + src/app/admin/skill-unlocks/in-person-grant-form.tsx
  • + src/app/api/admin/skills/grant-in-person/route.ts
Modified (4):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/skill-unlocks/in-person-grant-form.tsx
  • ~ src/app/admin/skill-unlocks/page.tsx
  • ~ src/app/api/admin/skills/grant-in-person/route.ts

Version 0.2.564

fix(mobile): route all upgrade paths to Apple IAP, drop floating button, fix double username

July 7, 2026 at 12:59 AM GMT+0
dc8bf353
🐛Fixed
  • fix(mobile): route all upgrade paths to Apple IAP, drop floating button, fix double username
  • Add /go-pro to the WebView purchase-intercept list so every in-app upgrade
  • entry point (pricing, subscribe, checkout, go-pro) opens the native StoreKit
  • paywall.
  • Remove the floating "Upgrade" overlay button; the web navbar's Upgrade CTA
  • and premium-feature links already open the Apple paywall, so it was redundant.

Version 0.2.563

feat: nest Report/Block into the profile ••• menu

July 6, 2026 at 11:13 PM GMT+0
6aef7516
🔄Changed
  • feat: nest Report/Block into the profile ••• menu
  • Move the user Report and Block controls into the existing "More options"
  • dropdown next to the Follow button instead of a separate menu, so a profile
  • has one ••• menu. Removes the standalone UserSafetyMenu component.
  • Claude-Session: https://claude.ai/code/session_01SWcAqsXEBQ2XSy5Cqit6dd

Files Changed

Modified (3):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/components/profile/user-safety-menu.tsx

Version 0.2.562

fix: only list EP-program-enrolled producers as dashboards in settings

July 6, 2026 at 9:57 PM GMT+0
d7d87faf
🐛Fixed
  • fix: only list EP-program-enrolled producers as dashboards in settings
  • EventProducerAccess grants also exist for gated-data visibility (e.g. The
  • Open mirrors Redline's grants), so the settings page showed a program
  • dashboard link for producers with no EventProducerSubscription. The link
  • 404'd on the program page anyway. Filter the list to producers with a
  • subscription row, matching the dashboard's own access check.

Files Changed

Modified (1):
  • ~ src/app/settings/page.tsx

Version 0.2.561

feat: App Store rejection fixes (crash, UGC moderation, support URL)

July 6, 2026 at 9:22 PM GMT+0
750ecba2
🔄Changed
  • feat: App Store rejection fixes (crash, UGC moderation, support URL)
  • Address all four items from Apple review of FullOut - Cheer Analytics
  • (submission 57173d2c):
  • 2.1(a) crash: add NSCamera/PhotoLibrary/Microphone usage descriptions to
  • mobile/app.json so the WebView profile-photo "Take Photo" flow no longer
  • crashes on iOS.

Files Changed

Created (4):
  • + src/app/api/users/block/route.ts
  • + src/app/support/page.tsx
  • + src/components/profile/user-safety-menu.tsx
  • + src/lib/blocks.ts
Modified (17):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/media-reports/page.tsx
  • ~ src/app/api/feed/route.ts
  • ~ src/app/api/media/report/route.ts
  • ~ src/app/api/users/block/route.ts
  • ~ src/app/home/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/post/[id]/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/app/support/page.tsx
  • ~ src/app/terms/page.tsx
  • ~ src/app/verify-email/page.tsx
  • ~ src/components/profile/user-safety-menu.tsx
  • ~ src/lib/admin-alerts.ts
  • ~ src/lib/blocks.ts
  • ~ src/lib/feed/global-feed.ts

Version 0.2.560

feat: gym data enrichment pipeline (contact discovery, logos, geocoding) with provenance chokepoint

July 6, 2026 at 6:26 PM GMT+0
6840f3f9
🔄Changed
  • feat: gym data enrichment pipeline (contact discovery, logos, geocoding) with provenance chokepoint
  • Reusable tooling to enrich orgs (gyms/schools/colleges) with phone, email,
  • address, website, Instagram, profile logos, and map coords:
  • src/lib/enrichment/write.ts: single write chokepoint. Every enrichment
  • write records provenance (logoSource/logoFetchedAt) + a GymEnrichmentLog
  • audit row, so a bad run (e.g. Pride-month pics) is a one-query rollback.

Files Changed

Created (13):
  • + scripts/maintenance/apply-discovery.ts
  • + scripts/maintenance/apply-location-corrections.ts
  • + scripts/maintenance/apply-logo-urls.ts
  • + scripts/maintenance/best-gyms-targets.ts
  • + scripts/maintenance/build-enrichment-worklist.ts
  • + scripts/maintenance/detect-pride-pics.ts
  • + scripts/maintenance/fetch-website-logos.ts
  • + scripts/maintenance/geocode-gym-addresses.ts
  • + scripts/maintenance/refetch-gym-pics.ts
  • + scripts/maintenance/slice-discovery-wave.ts
  • + src/lib/enrichment/instagram.ts
  • + src/lib/enrichment/pride-detect.ts
  • + src/lib/enrichment/write.ts
Modified (14):
  • ~ scripts/maintenance/apply-discovery.ts
  • ~ scripts/maintenance/apply-location-corrections.ts
  • ~ scripts/maintenance/apply-logo-urls.ts
  • ~ scripts/maintenance/best-gyms-targets.ts
  • ~ scripts/maintenance/build-enrichment-worklist.ts
  • ~ scripts/maintenance/detect-pride-pics.ts
  • ~ scripts/maintenance/enrich-gyms-instagram.ts
  • ~ scripts/maintenance/fetch-website-logos.ts
  • ~ scripts/maintenance/geocode-gym-addresses.ts
  • ~ scripts/maintenance/refetch-gym-pics.ts
  • ~ scripts/maintenance/slice-discovery-wave.ts
  • ~ src/lib/enrichment/instagram.ts
  • ~ src/lib/enrichment/pride-detect.ts
  • ~ src/lib/enrichment/write.ts

Version 0.2.559

feat: GA4 + Search Console web analytics dashboard in admin

July 6, 2026 at 6:24 PM GMT+0
34740b41
🔄Changed
  • feat: GA4 + Search Console web analytics dashboard in admin
  • New /admin/web-analytics page surfaces Google Analytics traffic and Search
  • Console performance inside the platform: realtime active users, sessions/
  • pageviews/engagement with previous-period comparison, top pages, channels,
  • referrers, countries, cities, devices, plus GSC clicks/impressions/CTR/
  • position, top and rising queries. Reuses the existing service-account JWT

Files Changed

Created (12):
  • + src/app/admin/web-analytics/page.tsx
  • + src/app/api/admin/web-analytics/realtime/route.ts
  • + src/components/admin/web-analytics/range-filter.tsx
  • + src/components/admin/web-analytics/realtime-card.tsx
  • + src/components/admin/web-analytics/search-trend-chart.tsx
  • + src/components/admin/web-analytics/setup-card.tsx
  • + src/components/admin/web-analytics/top-list-card.tsx
  • + src/components/admin/web-analytics/traffic-trend-chart.tsx
  • + src/lib/google-analytics.ts
  • + src/lib/google-auth.ts
  • + src/lib/search-console.ts
  • + src/lib/web-analytics-data.ts
Modified (15):
  • ~ src/app/admin/web-analytics/page.tsx
  • ~ src/app/api/admin/check-env/route.ts
  • ~ src/app/api/admin/web-analytics/realtime/route.ts
  • ~ src/components/admin/web-analytics/range-filter.tsx
  • ~ src/components/admin/web-analytics/realtime-card.tsx
  • ~ src/components/admin/web-analytics/search-trend-chart.tsx
  • ~ src/components/admin/web-analytics/setup-card.tsx
  • ~ src/components/admin/web-analytics/top-list-card.tsx
  • ~ src/components/admin/web-analytics/traffic-trend-chart.tsx
  • ~ src/lib/__tests__/admin-nav.test.ts
  • ~ src/lib/admin-nav.tsx
  • ~ src/lib/google-analytics.ts
  • ~ src/lib/google-auth.ts
  • ~ src/lib/search-console.ts
  • ~ src/lib/web-analytics-data.ts

Version 0.2.558

feat: split company roster into Current and Previously

July 6, 2026 at 4:06 PM GMT+0
b1ab1829
🔄Changed
  • feat: split company roster into Current and Previously
  • Company 'Our Team' now groups members by tenure: leftAt null = Current,
  • leftAt set = Previously (alumni), with a 'Since 2022' / '2022 - 2024' label
  • per person. Uses the existing joinedAt/leftAt fields.
  • Claude-Session: https://claude.ai/code/session_016MBCg7qCGcjdaEhEVTY8wt

Files Changed

Modified (2):
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/components/choreographers/choreographer-member-section.tsx

Version 0.2.557

fix: discipline chips on /gyms now filter the map, not just the table

July 6, 2026 at 3:36 PM GMT+0
e12746d8
🐛Fixed
  • fix: discipline chips on /gyms now filter the map, not just the table
  • The map self-fetches from /api/gyms/map, which never received the ?discipline param, so selecting a discipline chip updated the gym list but left the map pins unchanged. The param now flows page -> map component -> API, where it applies the same Team-in-discipline filter the table uses. With an explicit discipline selected the map also drops its ALLSTAR_GYM-only restriction so STUNT and dance programs (school orgTypes) appear, matching the table; invalid discipline ids are validated against active disciplines and fall back to the default map.
  • Claude-Session: https://claude.ai/code/session_01VAHEPaNTRpd1m42VnNmdhS

Files Changed

Modified (4):
  • ~ src/app/api/gyms/map/route.ts
  • ~ src/app/gyms/page.tsx
  • ~ src/components/gyms/gyms-map-wrapper.tsx
  • ~ src/components/gyms/gyms-map.tsx

Version 0.2.556

feat: EP member + broker delete/deactivate, and traffic intel on admin EP page

July 6, 2026 at 3:14 PM GMT+0
a9306487
🔄Changed
  • feat: EP member + broker delete/deactivate, and traffic intel on admin EP page
  • Member management (admin EP detail page): Deactivate/Reactivate (status
  • flip) and Delete. DELETE /api/admin/event-producers/[id] hard-deletes only
  • when there's no settlement history (statements/accruals); otherwise 409 ->
  • deactivate instead, so the financial audit trail is never destroyed.
  • Broker management (admin brokers page): 'Remove' per broker clears the

Files Changed

Created (3):
  • + src/app/api/admin/event-producers/brokers/[partnerId]/route.ts
  • + src/components/admin/event-producers/broker-remove-button.tsx
  • + src/components/admin/event-producers/ep-member-actions.tsx
Modified (6):
  • ~ src/app/admin/event-producers/[id]/page.tsx
  • ~ src/app/admin/event-producers/brokers/page.tsx
  • ~ src/app/api/admin/event-producers/[id]/route.ts
  • ~ src/app/api/admin/event-producers/brokers/[partnerId]/route.ts
  • ~ src/components/admin/event-producers/broker-remove-button.tsx
  • ~ src/components/admin/event-producers/ep-member-actions.tsx

Version 0.2.555

fix: merge duplicate gyms + identify ghost gym records behind state rankings

July 6, 2026 at 2:25 PM GMT+0
899b5c3f
🐛Fixed
  • fix: merge duplicate gyms + identify ghost gym records behind state rankings
  • Merged 8 duplicate/artifact gym records via merge-gyms.ts, all performances preserved: Storm All-Stars into Storm Athletics (NY), New York Icons - Rochester into New York Icons, Titanium Force into Titanium Force Cheer (IL), Elite Cheer Center into Elite Cheer (NE), duplicate Fierce Idaho (ID), ghost record Lexington into Cheer Athletics - Lexington (its horse-racing Cats team names identified it), and two North Star Athletics single-team artifacts
  • Relocated two misfiled programs identified by their competition footprints: North Star Athletics to East Longmeadow MA, Express Cheer Force (Express Dance and Acro) to Milford MA
  • Regenerated authored copy for the 8 affected states (NY, IL, NE, ID, KY, MA, MD, MT); DATA_VERSION bumped to v3 so merged rankings go live with this deploy
  • New tooling: inventory-flagged-gyms.ts (teams + competition history per flagged record), fix-ghost-gym-locations.ts
  • Remaining unidentifiable records left untouched (real results); listed in tasks/todo.md for manual review

Files Changed

Created (3):
  • + scripts/debug/find-canonical-gyms.ts
  • + scripts/debug/inventory-flagged-gyms.ts
  • + scripts/seo/fix-ghost-gym-locations.ts
Modified (12):
  • ~ scripts/debug/find-canonical-gyms.ts
  • ~ scripts/debug/inventory-flagged-gyms.ts
  • ~ scripts/seo/fix-ghost-gym-locations.ts
  • ~ src/content/best-cheer-gyms/idaho.ts
  • ~ src/content/best-cheer-gyms/illinois.ts
  • ~ src/content/best-cheer-gyms/kentucky.ts
  • ~ src/content/best-cheer-gyms/maryland.ts
  • ~ src/content/best-cheer-gyms/massachusetts.ts
  • ~ src/content/best-cheer-gyms/montana.ts
  • ~ src/content/best-cheer-gyms/nebraska.ts
  • ~ src/content/best-cheer-gyms/new-york.ts
  • ~ src/lib/best-gyms/data.ts

Version 0.2.554

fix: verify + correct ranked gym locations, surface state rankings in UX

July 6, 2026 at 1:38 PM GMT+0
0e6a1e50
🐛Fixed
  • fix: verify + correct ranked gym locations, surface state rankings in UX
  • Verified all 366 ranked gyms via web research; corrected 42 wrong-location records through the audited enrichment chokepoint (Top Gun Allstars UK off the Texas page, Dakota Spirit to SD, Stealth Elite to IL, Rocket Elite to PA, 7 gyms moved out of the US entirely), with Nominatim re-geocoding for corrected pins
  • Rewrote authored copy for the 38 states whose rankings changed; AK/DC/WY now render the zero-ranked layout
  • Gym profile badge: Top 10 Cheer Gym in {State} (no rank number), linking to the state page via daily-cached getGymStateRanking
  • Cross-links: /gyms header button + per-state contextual link, footer Best Gyms link, /cheer hub banner, /leaderboards header link
  • POST /api/admin/revalidate-best-gyms (admin or CRON_SECRET bearer) + DATA_VERSION cache-key bump so corrections go live with this deploy

Files Changed

Created (4):
  • + scripts/seo/apply-location-corrections.ts
  • + scripts/seo/build-location-verification-batches.ts
  • + scripts/seo/diff-best-gyms-worklists.ts
  • + src/app/api/admin/revalidate-best-gyms/route.ts
Modified (20):
  • ~ scripts/seo/apply-location-corrections.ts
  • ~ scripts/seo/build-location-verification-batches.ts
  • ~ scripts/seo/diff-best-gyms-worklists.ts
  • ~ src/app/api/admin/revalidate-best-gyms/route.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/gyms/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/app/leaderboards/page.tsx
  • ~ src/components/hub/discipline-hub.tsx
  • ~ src/content/best-cheer-gyms/alabama.ts
  • ~ src/content/best-cheer-gyms/alaska.ts
  • ~ src/content/best-cheer-gyms/arizona.ts
  • ~ src/content/best-cheer-gyms/colorado.ts
  • ~ src/content/best-cheer-gyms/connecticut.ts
  • ~ src/content/best-cheer-gyms/delaware.ts
  • ~ src/content/best-cheer-gyms/florida.ts
  • ~ src/content/best-cheer-gyms/georgia.ts
  • ~ src/content/best-cheer-gyms/idaho.ts
  • ~ src/content/best-cheer-gyms/illinois.ts
  • ~ src/content/best-cheer-gyms/indiana.ts

Version 0.2.553

feat: Best Cheer Gyms in {State} SEO pages for all 50 states + DC

July 6, 2026 at 4:41 AM GMT+0
550c5dd3
🔄Changed
  • feat: Best Cheer Gyms in {State} SEO pages for all 50 states + DC
  • /best-cheer-gyms index + /best-cheer-gyms/[state] (51 pages, on-demand ISR, 24h revalidate)
  • Top 10 all-star gyms per state ranked by 2025-26 banners (1st in finals) and podiums (top 3)
  • Interactive MapLibre map with rank-numbered markers (bad-geocode guard), ranking table, per-gym profiles with links
  • AI-authored copy per state keyed by gym ID with data-driven fallbacks; no-em-dash rule enforced via npm run seo:check-copy
  • ItemList/FAQ/Breadcrumb JSON-LD, sitemap entries (states with gyms only), best-cheer-gyms reserved username

Files Changed

Created (20):
  • + scripts/debug/audit-best-gyms-states.ts
  • + scripts/debug/explain-best-gyms-query.ts
  • + scripts/seo/check-no-emdash.ts
  • + scripts/seo/export-best-gyms-worklist.ts
  • + src/app/best-cheer-gyms/[state]/page.tsx
  • + src/app/best-cheer-gyms/page.tsx
  • + src/components/best-gyms/best-gyms-map-wrapper.tsx
  • + src/components/best-gyms/best-gyms-map.tsx
  • + src/content/best-cheer-gyms/alabama.ts
  • + src/content/best-cheer-gyms/alaska.ts
  • + src/content/best-cheer-gyms/arizona.ts
  • + src/content/best-cheer-gyms/arkansas.ts
  • + src/content/best-cheer-gyms/california.ts
  • + src/content/best-cheer-gyms/colorado.ts
  • + src/content/best-cheer-gyms/connecticut.ts
  • + src/content/best-cheer-gyms/delaware.ts
  • + src/content/best-cheer-gyms/florida.ts
  • + src/content/best-cheer-gyms/georgia.ts
  • + src/content/best-cheer-gyms/hawaii.ts
  • + src/content/best-cheer-gyms/idaho.ts
Modified (20):
  • ~ scripts/debug/audit-best-gyms-states.ts
  • ~ scripts/debug/explain-best-gyms-query.ts
  • ~ scripts/seo/check-no-emdash.ts
  • ~ scripts/seo/export-best-gyms-worklist.ts
  • ~ src/app/best-cheer-gyms/[state]/page.tsx
  • ~ src/app/best-cheer-gyms/page.tsx
  • ~ src/app/sitemap.ts
  • ~ src/components/best-gyms/best-gyms-map-wrapper.tsx
  • ~ src/components/best-gyms/best-gyms-map.tsx
  • ~ src/content/best-cheer-gyms/alabama.ts
  • ~ src/content/best-cheer-gyms/alaska.ts
  • ~ src/content/best-cheer-gyms/arizona.ts
  • ~ src/content/best-cheer-gyms/arkansas.ts
  • ~ src/content/best-cheer-gyms/california.ts
  • ~ src/content/best-cheer-gyms/colorado.ts
  • ~ src/content/best-cheer-gyms/connecticut.ts
  • ~ src/content/best-cheer-gyms/delaware.ts
  • ~ src/content/best-cheer-gyms/florida.ts
  • ~ src/content/best-cheer-gyms/georgia.ts
  • ~ src/content/best-cheer-gyms/hawaii.ts

Version 0.2.552

feat: admin merge UI for duplicate choreographers

July 6, 2026 at 4:06 AM GMT+0
068a53cb
🔄Changed
  • feat: admin merge UI for duplicate choreographers
  • Merge duplicates dialog on /admin/choreographers: pick source + target, preview
  • what moves (members/credits/videos/followers, dedupe counts, identity fill),
  • then merge. Backed by admin-only /api/admin/choreographers/merge wrapping the
  • verified choreographer-merge lib.
  • Claude-Session: https://claude.ai/code/session_016MBCg7qCGcjdaEhEVTY8wt

Files Changed

Created (2):
  • + src/app/api/admin/choreographers/merge/route.ts
  • + src/components/admin/merge-choreographers-dialog.tsx
Modified (3):
  • ~ src/app/admin/choreographers/page.tsx
  • ~ src/app/api/admin/choreographers/merge/route.ts
  • ~ src/components/admin/merge-choreographers-dialog.tsx

Version 0.2.551

feat: choreographer merge/dedup tool for consolidating duplicate company pages

July 6, 2026 at 3:59 AM GMT+0
0a21c7a6
🔄Changed
  • feat: choreographer merge/dedup tool for consolidating duplicate company pages
  • Adds src/lib/choreographer-merge.ts (transactional previewMerge + mergeChoreographers)
  • and a dry-run-by-default CLI (scripts/maintenance/merge-choreographers.ts). Moves all
  • members, credits, videos, and followers onto the target, deduping by personId /
  • unique-credit-key (scopes unioned) / follower, fills the target's empty identity
  • fields, then deletes the source. Verified end-to-end against the DB (15/15 checks).

Files Changed

Created (2):
  • + scripts/maintenance/merge-choreographers.ts
  • + src/lib/choreographer-merge.ts
Modified (2):
  • ~ scripts/maintenance/merge-choreographers.ts
  • ~ src/lib/choreographer-merge.ts

Version 0.2.550

feat: traffic & click intel on the EP program page

July 6, 2026 at 3:46 AM GMT+0
dcd4817f
🔄Changed
  • feat: traffic & click intel on the EP program page
  • The EP program page managed tracking URLs but showed no click intel. Add
  • the same PartnerAnalytics view affiliates get - clicks over time, referral
  • sources, and per-link click/conversion breakdown.
  • Authorization: the analytics API only let admins pass ?partnerId=. New
  • resolvePartnerAnalyticsAccess authorizes EP seat holders too and reports

Files Changed

Modified (4):
  • ~ src/app/api/partner/dashboard/analytics/route.ts
  • ~ src/app/event-producers/[slug]/program/page.tsx
  • ~ src/components/partner/partner-analytics.tsx
  • ~ src/lib/partner-campaign-access.ts

Version 0.2.549

feat: notify choreo-company owner on affiliation claim, choreographer on confirm

July 6, 2026 at 3:42 AM GMT+0
db04e808
🔄Changed
  • feat: notify choreo-company owner on affiliation claim, choreographer on confirm
  • Closes the self-reported affiliation loop: POST affiliation notifies the company
  • owner (if claimed) so the confirm inbox doesn't sit unseen; confirming notifies
  • the choreographer that their entry is now verified. Both non-fatal in-app
  • notifications, reusing the CHOREO_AFFILIATION_CLAIMED/CONFIRMED helpers.
  • Claude-Session: https://claude.ai/code/session_016MBCg7qCGcjdaEhEVTY8wt

Files Changed

Modified (2):
  • ~ src/app/api/choreographers/[id]/members/[memberId]/route.ts
  • ~ src/app/api/person/[id]/choreo-affiliations/route.ts

Version 0.2.548

feat: EP program seats (up to 5) + admin brokers page

July 6, 2026 at 12:53 AM GMT+0
44893c57
🔄Changed
  • feat: EP program seats (up to 5) + admin brokers page
  • Seats: EventProducerAccess grows a role (OWNER/FULL/ANALYTICS). Up to 5
  • seats per producer; each seat grants the holder PRO on their own account
  • (resolved non-destructively at auth time via the access _count, so Stripe
  • stays authoritative and revoking reverts cleanly). Owner + Full seats see
  • financials; Analytics seats see program analytics only - enforced on the

Files Changed

Created (7):
  • + scripts/maintenance/backfill-ep-seat-owners.ts
  • + src/app/admin/event-producers/brokers/page.tsx
  • + src/app/api/event-producers/[producerId]/seats/[userId]/route.ts
  • + src/app/api/event-producers/[producerId]/seats/route.ts
  • + src/components/event-producers/ep-seat-manager.tsx
  • + src/lib/__tests__/ep-access.test.ts
  • + src/lib/ep-access.ts
Modified (14):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/backfill-ep-seat-owners.ts
  • ~ src/app/admin/event-producers/[id]/page.tsx
  • ~ src/app/admin/event-producers/brokers/page.tsx
  • ~ src/app/api/event-producers/[producerId]/seats/[userId]/route.ts
  • ~ src/app/api/event-producers/[producerId]/seats/route.ts
  • ~ src/app/event-producers/[slug]/program/page.tsx
  • ~ src/components/event-producers/ep-seat-manager.tsx
  • ~ src/lib/__tests__/admin-nav.test.ts
  • ~ src/lib/__tests__/ep-access.test.ts
  • ~ src/lib/admin-nav.tsx
  • ~ src/lib/auth.ts
  • ~ src/lib/ep-access.ts
  • ~ src/lib/notifications.ts

Version 0.2.547

feat: choreographers can list companies they've worked with (self-reported affiliations + owner confirm)

July 6, 2026 at 12:29 AM GMT+0
e2624860
🔄Changed
  • feat: choreographers can list companies they've worked with (self-reported affiliations + owner confirm)
  • Choreographers add companies to their profile's Choreography tab with a role and
  • year range. Each shows as Self-reported until the company owner confirms it into
  • a Verified roster member. Company owners get a confirm inbox in Our Team;
  • unconfirmed claims stay out of the public roster so they can't be spoofed onto a
  • company page. Completes the choreographer-companies feature alongside self-serve

Files Changed

Created (4):
  • + src/app/api/person/[id]/choreo-affiliations/[memberId]/route.ts
  • + src/app/api/person/[id]/choreo-affiliations/route.ts
  • + src/components/choreographers/choreo-affiliation-claim-inbox.tsx
  • + src/components/choreographers/person-choreo-affiliations.tsx
Modified (7):
  • ~ src/app/api/choreographers/[id]/members/[memberId]/route.ts
  • ~ src/app/api/person/[id]/choreo-affiliations/[memberId]/route.ts
  • ~ src/app/api/person/[id]/choreo-affiliations/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/choreographers/choreo-affiliation-claim-inbox.tsx
  • ~ src/components/choreographers/person-choreo-affiliations.tsx

Version 0.2.546

feat: include event producers (Redline etc.) in search

July 5, 2026 at 11:54 PM GMT+0
0d31ac1a
🔄Changed
  • feat: include event producers (Redline etc.) in search
  • Search now covers a seventh entity: event producers. runUnifiedSearch
  • grows a buildEventProducerSearchSql that rides the same trigram matching
  • and the SAME gating posture as competition search - confidential
  • (non-PUBLIC) producers stay hidden except for admins and
  • EventProducerAccess holders, whose widened results only ship on private

Files Changed

Created (1):
  • + src/components/choreographers/company-details-editor.tsx
Modified (14):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/add-discover-search-indexes.ts
  • ~ src/app/api/choreographers/[id]/logo/route.ts
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/search/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/discover/page.tsx
  • ~ src/components/choreographers/company-details-editor.tsx
  • ~ src/components/choreographers/create-company-form.tsx
  • ~ src/components/discover/sortable-tables.tsx
  • ~ src/components/home-search.tsx
  • ~ src/lib/search/__tests__/unified-search.test.ts
  • ~ src/lib/search/unified-search.ts
  • ~ src/lib/utils.ts

Version 0.2.545

fix: hide broker relationship from the brokered EP (confidential)

July 5, 2026 at 11:40 PM GMT+0
08b09250
🐛Fixed
  • fix: hide broker relationship from the brokered EP (confidential)
  • The EP program page showed 'Brokered by {name}' in the negotiated-terms
  • card and fetched BrokerPartner into an EP-facing page. A brokered producer
  • must never learn a broker took a cut. Remove the display and the include;
  • broker data now lives only on the admin console and the broker's own
  • /broker portfolio. Statement table already excludes the override (it

Files Changed

Modified (1):
  • ~ src/app/event-producers/[slug]/program/page.tsx

Version 0.2.544

feat: broker verification link on admin EP editor - when an EP is brokered, show the relationship + a link to that broker's rolled-up portfolio

July 5, 2026 at 11:29 PM GMT+0
193ea6b6
🔄Changed
  • feat: broker verification link on admin EP editor - when an EP is brokered, show the relationship + a link to that broker's rolled-up portfolio

Files Changed

Modified (1):
  • ~ src/app/admin/event-producers/[id]/page.tsx

Version 0.2.543

feat: dedicated EP Broker portfolio page

July 5, 2026 at 9:50 PM GMT+0
36d07c92
🔄Changed
  • feat: dedicated EP Broker portfolio page
  • New /event-producers/[slug]/broker rolls up every EP a broker (e.g. Redline)
  • brought to the platform PLUS their own EP: portfolio revenue (lifetime
  • platform rev share across the book), lifetime and current-month broker
  • override, a per-producer override chart, and a roster flagging 'Your EP' vs
  • 'Brokered' with each EP's rev-share rate, broker %, platform revenue, and

Files Changed

Created (1):
  • + src/app/event-producers/[slug]/broker/page.tsx
Modified (4):
  • ~ src/app/event-producers/[slug]/broker/page.tsx
  • ~ src/app/event-producers/[slug]/program/page.tsx
  • ~ src/app/settings/page.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.542

feat: EP partners can create multiple tracking URLs (campaign links) from their program dashboard

July 5, 2026 at 9:45 PM GMT+0
43978ae5
Added
  • feat: EP partners can create multiple tracking URLs (campaign links) from their program dashboard
  • New resolveManageablePartnerId helper authorizes campaign management for the partner's own account, admins, and EventProducerAccess holders (EP staff)
  • Campaign create/toggle/delete now honor the target partnerId, so admins and EP staff can manage a partner's links (previously self-only)
  • PartnerCampaigns surfaced on the EP program page: one attributed URL per event/channel/campaign

Files Changed

Created (1):
  • + src/lib/partner-campaign-access.ts
Modified (6):
  • ~ src/app/api/partner/dashboard/campaigns/[id]/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/route.ts
  • ~ src/app/event-producers/[slug]/program/page.tsx
  • ~ src/components/partner/partner-campaigns.tsx
  • ~ src/lib/__tests__/admin-nav.test.ts
  • ~ src/lib/partner-campaign-access.ts

Version 0.2.541

feat: add Event Producers and EP Settlements (incl. brokers) to admin Revenue & Partnerships nav

July 5, 2026 at 3:05 PM GMT+0
ba126bae
🔄Changed
  • feat: add Event Producers and EP Settlements (incl. brokers) to admin Revenue & Partnerships nav

Files Changed

Modified (1):
  • ~ src/lib/admin-nav.tsx

Version 0.2.540

Reorganize admin nav + fix dead-end Settings Admin tab

July 5, 2026 at 4:39 AM GMT+0
129dc18c
🔄Changed
  • Reorganize admin nav + fix dead-end Settings Admin tab
  • Single source of truth: src/lib/admin-nav.tsx (ADMIN_NAV_SECTIONS),
  • consumed by both /admin dashboard and Settings → Admin.
  • Regrouped 28 admin links from 5 loose groups into 7 coherent ones
  • (Revenue & Partnerships, Users & Growth, Competition Data, Directory,
  • Verification, Content & Hub, System), each with a one-line blurb and

Files Changed

Created (3):
  • + src/components/settings/admin-launcher.tsx
  • + src/lib/__tests__/admin-nav.test.ts
  • + src/lib/admin-nav.tsx
Modified (6):
  • ~ src/app/admin/page.tsx
  • ~ src/components/settings/admin-launcher.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/settings-nav.tsx
  • ~ src/lib/__tests__/admin-nav.test.ts
  • ~ src/lib/admin-nav.tsx

Version 0.2.539

Reorganize admin nav + fix dead-end Settings Admin tab

July 5, 2026 at 4:39 AM GMT+0
1bc9f9e1
🔄Changed
  • Reorganize admin nav + fix dead-end Settings Admin tab
  • Single source of truth: src/lib/admin-nav.tsx (ADMIN_NAV_SECTIONS),
  • consumed by both /admin dashboard and Settings → Admin.
  • Regrouped 28 admin links from 5 loose groups into 7 coherent ones
  • (Revenue & Partnerships, Users & Growth, Competition Data, Directory,
  • Verification, Content & Hub, System), each with a one-line blurb and

Files Changed

Created (3):
  • + src/components/settings/admin-launcher.tsx
  • + src/lib/__tests__/admin-nav.test.ts
  • + src/lib/admin-nav.tsx
Modified (6):
  • ~ src/app/admin/page.tsx
  • ~ src/components/settings/admin-launcher.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/settings-nav.tsx
  • ~ src/lib/__tests__/admin-nav.test.ts
  • ~ src/lib/admin-nav.tsx

Version 0.2.538

Add API docs to footer + Partner API Keys to admin/settings menus

July 5, 2026 at 4:16 AM GMT+0
b9f56701
Added
  • Add API docs to footer + Partner API Keys to admin/settings menus
  • Footer: "API" link to /developers.
  • /admin dashboard: "Partner API Keys" card under Business.
  • Settings admin section: direct "Partner API Keys" button.
  • /developers contact email -> team@fullout.energy (was a personal gmail).
  • Claude-Session: https://claude.ai/code/session_013BKXE8nWCjdWyHSEuVzFUH

Files Changed

Modified (4):
  • ~ src/app/admin/page.tsx
  • ~ src/app/developers/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.537

Add API docs to footer + Partner API Keys to admin/settings menus

July 5, 2026 at 4:16 AM GMT+0
71e50752
Added
  • Add API docs to footer + Partner API Keys to admin/settings menus
  • Footer: "API" link to /developers.
  • /admin dashboard: "Partner API Keys" card under Business.
  • Settings admin section: direct "Partner API Keys" button.
  • /developers contact email -> team@fullout.energy (was a personal gmail).
  • Claude-Session: https://claude.ai/code/session_013BKXE8nWCjdWyHSEuVzFUH

Files Changed

Modified (4):
  • ~ src/app/admin/page.tsx
  • ~ src/app/developers/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.536

feat: consolidate partner API invoicing by billing account + direct mark-paid

July 4, 2026 at 7:58 PM GMT+0
fac8df2a
🔄Changed
  • feat: consolidate partner API invoicing by billing account + direct mark-paid
  • Partner API invoicing was strictly per-key, so a partner with a secret key and
  • a publishable embed key produced two separate invoice rows each month. Introduce
  • a PartnerAccount billing entity: keys attach to an account, the flat monthly
  • price and billing email live on the account, and invoices are generated one per
  • account per month with usage summed across all the account's keys.

Files Changed

Created (2):
  • + scripts/maintenance/backfill-partner-accounts.ts
  • + src/app/api/admin/api-accounts/route.ts
Modified (7):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/backfill-partner-accounts.ts
  • ~ src/app/api/admin/api-accounts/route.ts
  • ~ src/app/api/admin/api-invoices/route.ts
  • ~ src/app/api/admin/api-keys/[id]/route.ts
  • ~ src/app/api/admin/api-keys/route.ts
  • ~ src/components/admin/api-keys-manager.tsx

Version 0.2.535

fix: de-duplicate admin nav - Settings > Admin now links to the dashboard instead of a stale link subset; admin dashboard verification card points to the unified queue (credits + gym claims) and drops the dead page-verification link

July 4, 2026 at 7:50 PM GMT+0
451e476c
🐛Fixed
  • fix: de-duplicate admin nav - Settings > Admin now links to the dashboard instead of a stale link subset; admin dashboard verification card points to the unified queue (credits + gym claims) and drops the dead page-verification link

Files Changed

Modified (2):
  • ~ src/app/admin/page.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.534

feat: create + manage choreography companies self-serve

July 4, 2026 at 7:48 PM GMT+0
03a5ceee
Added
  • feat: create + manage choreography companies self-serve
  • 'Create Company Page' on /choreographers for Pro users
  • Owner member management on the company page: add/edit/remove members with tenure years (Member since 2022 / 2022-2024), title, IG, bio, photo
  • Member credits roll up into company-wide accolades (existing season stats aggregate all company credits)
  • External links (booking/camps/merch) via the shared https-only bulletin board
  • ChoreographerMember gains joinedAt/leftAt for membership tenure

Files Changed

Created (2):
  • + src/components/choreographers/choreographer-member-manager.tsx
  • + src/components/choreographers/create-company-form.tsx
Modified (8):
  • ~ prisma/schema.prisma
  • ~ src/app/api/choreographers/[id]/members/[memberId]/route.ts
  • ~ src/app/api/choreographers/[id]/members/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/choreographers/page.tsx
  • ~ src/components/choreographers/choreographer-member-manager.tsx
  • ~ src/components/choreographers/create-company-form.tsx
  • ~ src/components/gyms/bulletin-board.tsx

Version 0.2.533

feat: choreography company backend (owner-managed members + external links) + EP/broker program link in settings

July 4, 2026 at 7:42 PM GMT+0
5d08b8b8
🔄Changed
  • feat: choreography company backend (owner-managed members + external links) + EP/broker program link in settings
  • Choreographer.bioLinks (https-only external links, shared parseBioLinks)
  • Company members: page owners (not just admins) can add/edit/remove members
  • One COMPANY page per non-admin account; individual activation never touches a company page (type INDIVIDUAL scoping)
  • Settings gains an EP Program section for EventProducerAccess holders (brokers included), linking to their program dashboards

Files Changed

Modified (10):
  • ~ prisma/schema.prisma
  • ~ src/app/api/choreographers/[id]/members/[memberId]/route.ts
  • ~ src/app/api/choreographers/[id]/members/route.ts
  • ~ src/app/api/choreographers/[id]/route.ts
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/profile/choreographer-page/route.ts
  • ~ src/app/settings/page.tsx
  • ~ src/app/settings/profile-pages/page.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/settings-nav.tsx

Version 0.2.532

feat: pro profile section order - posts move to the bottom; skills, highlights, and timeline sit above the feed

July 4, 2026 at 7:26 PM GMT+0
43df01a1
🔄Changed
  • feat: pro profile section order - posts move to the bottom; skills, highlights, and timeline sit above the feed

Files Changed

Modified (2):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-pro-skin.tsx

Version 0.2.531

feat: photo gallery reorder for gym/team pages + robust gym-claims flag parsing (env values with trailing newlines)

July 4, 2026 at 5:42 PM GMT+0
e8357e03
🔄Changed
  • feat: photo gallery reorder for gym/team pages + robust gym-claims flag parsing (env values with trailing newlines)

Files Changed

Modified (4):
  • ~ src/app/api/gyms/[id]/photos/route.ts
  • ~ src/app/api/teams/[id]/photos/route.ts
  • ~ src/components/gyms/entity-photo-gallery.tsx
  • ~ src/lib/gym-admin.ts

Version 0.2.530

feat: gated events visible in search for authorized viewers + home location setting

July 4, 2026 at 5:03 PM GMT+0
16fe5bce
🔒Security
  • feat: gated events visible in search for authorized viewers + home location setting
  • Admins and EventProducerAccess holders now see their gated competitions
  • (e.g. ASW under The Open) in /discover and navbar search; everyone else
  • keeps the strict isGated=false filter. Widened results only ship on
  • private (per-user) responses.
  • New Home Location setting (Settings > Account) feeds the near-you search

Files Changed

Created (2):
  • + src/app/api/user/home-location/route.ts
  • + src/components/settings/home-location-form.tsx
Modified (10):
  • ~ src/app/api/search/route.ts
  • ~ src/app/api/user/home-location/route.ts
  • ~ src/app/discover/page.tsx
  • ~ src/app/settings/page.tsx
  • ~ src/components/settings/home-location-form.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/lib/search/__tests__/boost-context.test.ts
  • ~ src/lib/search/__tests__/unified-search.test.ts
  • ~ src/lib/search/boost-context.ts
  • ~ src/lib/search/unified-search.ts

Version 0.2.529

feat: professional profile skin + credit-form dropdown fix + directories list activated pros

July 4, 2026 at 4:49 PM GMT+0
e42ae5df
🔄Changed
  • feat: professional profile skin + credit-form dropdown fix + directories list activated pros
  • Profile skin: profiles with an active Coach/Choreographer module no longer
  • use tabs. The page reformats into a professional layout: an identity band
  • under the profile card (role title pulled from the newest season's custom
  • title, current gym affiliations, jump pills), then stacked full-width
  • sections: Coaching, Choreography, Athlete Career (experience + posts),

Files Changed

Created (1):
  • + src/components/profile/profile-pro-skin.tsx
Modified (9):
  • ~ src/app/choreographers/page.tsx
  • ~ src/app/coaches/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/admin/choreographer-credit-form.tsx
  • ~ src/components/admin/coach-credit-form.tsx
  • ~ src/components/choreographers/choreographer-card.tsx
  • ~ src/components/coaches/coach-card.tsx
  • ~ src/components/profile/profile-pro-skin.tsx
  • ~ src/components/profile/profile-role-badges.tsx

Version 0.2.528

feat: manage coach/choreo credits directly on your profile - owners get add/edit/delete in the Coaching and Choreography tabs, and owner-added credits publish immediately (no admin queue)

July 4, 2026 at 4:28 PM GMT+0
7ab4043e
🔄Changed
  • feat: manage coach/choreo credits directly on your profile - owners get add/edit/delete in the Coaching and Choreography tabs, and owner-added credits publish immediately (no admin queue)

Files Changed

Modified (5):
  • ~ src/app/api/choreographers/[id]/credits/route.ts
  • ~ src/app/api/coaches/[id]/credits/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-choreography-section.tsx
  • ~ src/components/profile/profile-coaching-section.tsx

Version 0.2.527

feat: coach/choreo are now modules that reskin /@username, not separate pages

July 4, 2026 at 3:51 PM GMT+0
4ca2d7a7
🔄Changed
  • feat: coach/choreo are now modules that reskin /@username, not separate pages
  • One person, one page. Activating a Coach or Choreographer module now
  • transforms the owner's profile: the header stats strip switches to
  • professional stats (teams coached, seasons, routines), the Coaching or
  • Choreography section becomes the default view for visitors, and the
  • professional tabs lead the tab row. Athlete history stays one tab away.

Files Changed

Modified (9):
  • ~ src/app/api/profile/choreographer-page/route.ts
  • ~ src/app/api/profile/coach-page/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/coaches/[id]/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-choreography-section.tsx
  • ~ src/components/profile/profile-coaching-section.tsx
  • ~ src/components/profile/profile-role-badges.tsx
  • ~ src/components/profile/profile-tabs.tsx

Version 0.2.526

feat: Division Winner Scores chart now displays ICU named tiers (Novice-Premier) as levels

July 4, 2026 at 3:30 PM GMT+0
02c894ac
🔄Changed
  • feat: Division Winner Scores chart now displays ICU named tiers (Novice-Premier) as levels
  • The top-of-page competition chart collapsed every ICU Europeans division into
  • a single 'Other' row because it only parsed numeric levels (L1-L7). Named
  • ability tiers (Novice, Intermediate, Median, Advanced, Elite, Premier) now
  • rank, color, and label like numeric levels, ordered lowest to highest, with
  • the legend showing the tier name and a wider Y axis for long tier labels.

Files Changed

Created (1):
  • + scripts/import/run-icu-europeans-import.cmd
Modified (3):
  • ~ scripts/import/import-icu-europeans-2026.ts
  • ~ scripts/import/run-icu-europeans-import.cmd
  • ~ src/components/competitions/division-winners-chart.tsx

Version 0.2.525

feat: ICU European Championships 2026 results import (Prague, Jul 3-5)

July 4, 2026 at 2:49 PM GMT+0
9008ea96
🔄Changed
  • feat: ICU European Championships 2026 results import (Prague, Jul 3-5)
  • New importer scripts/import/import-icu-europeans-2026.ts pulls the per-division
  • result PDFs the ICU posts on cheerunion.org/championships/european/ and loads
  • them as the icu-europeans-2026 competition under the International Cheer
  • discipline. Parses all three pdf-parse text layouts (row-per-line, columnar,
  • glued-rank), anchors rows on a European country whitelist, canonicalizes

Files Changed

Created (1):
  • + scripts/import/import-icu-europeans-2026.ts
Modified (1):
  • ~ scripts/import/import-icu-europeans-2026.ts

Version 0.2.524

feat: Partner Stunt discipline hub at /partner-stunt with Future Flyer and Stunting is a Habit event producers

July 4, 2026 at 2:39 PM GMT+0
ecacbfc7
🔄Changed
  • feat: Partner Stunt discipline hub at /partner-stunt with Future Flyer and Stunting is a Habit event producers

Files Changed

Created (2):
  • + scripts/setup/seed-partner-stunt-producers.ts
  • + src/app/partner-stunt/page.tsx
Modified (6):
  • ~ scripts/setup/seed-partner-stunt-producers.ts
  • ~ src/app/partner-stunt/page.tsx
  • ~ src/components/hub/discipline-hub.tsx
  • ~ src/lib/hubs/hub-config.ts
  • ~ src/lib/nav-config.ts
  • ~ src/lib/username-validation.ts

Version 0.2.523

feat: differentiate cheer hubs - All Star (/cheer), Sideline (/sideline, Game Day format), High School (/school), College (/college); nav labels updated

July 4, 2026 at 2:30 PM GMT+0
ae05ea1f
🔄Changed
  • feat: differentiate cheer hubs - All Star (/cheer), Sideline (/sideline, Game Day format), High School (/school), College (/college); nav labels updated

Files Changed

Created (1):
  • + src/app/sideline/page.tsx
Modified (4):
  • ~ src/app/sideline/page.tsx
  • ~ src/lib/hubs/hub-config.ts
  • ~ src/lib/nav-config.ts
  • ~ src/lib/username-validation.ts

Version 0.2.522

feat: coach and choreographer pages are now fully self-serve for Pro users - auto-verified on activation, verification form and Unverified labels removed (manual review stays for gym claims)

July 4, 2026 at 2:27 PM GMT+0
5ee76770
🔄Changed
  • feat: coach and choreographer pages are now fully self-serve for Pro users - auto-verified on activation, verification form and Unverified labels removed (manual review stays for gym claims)

Files Changed

Created (1):
  • + scripts/maintenance/verify-claimed-coach-choreo-pages.ts
Modified (9):
  • ~ scripts/maintenance/verify-claimed-coach-choreo-pages.ts
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/coaches/route.ts
  • ~ src/app/api/profile/choreographer-page/route.ts
  • ~ src/app/api/profile/coach-page/route.ts
  • ~ src/app/coaches/[id]/page.tsx
  • ~ src/components/coaches/coach-verification-form.tsx
  • ~ src/components/teams/team-choreography-section.tsx
  • ~ src/components/teams/team-coaches-section.tsx

Version 0.2.521

fix: nav search Enter left the dropdown open over results when already on /discover - clear input, close dropdown, and blur before navigating

July 4, 2026 at 2:17 PM GMT+0
94f6dd2e
🐛Fixed
  • fix: nav search Enter left the dropdown open over results when already on /discover - clear input, close dropdown, and blur before navigating

Files Changed

Modified (1):
  • ~ src/components/home-search.tsx

Version 0.2.520

Partner API: discipline + division filters, /api/v1/disciplines reference

July 4, 2026 at 2:16 PM GMT+0
b45d133a
🔄Changed
  • Partner API: discipline + division filters, /api/v1/disciplines reference
  • /api/v1/competitions?discipline=<name>: include-semantics (an event matches
  • if any of its divisions run that discipline; Competition.disciplineId is
  • null for mixed cheer/dance events). Pre-fetched division/competition ids
  • per the no-nested-relation-filter rule; combines with producer/state/status.
  • /api/v1/competitions/{id}?division=<id|slug|exact name>: narrow results to

Files Changed

Created (3):
  • + scripts/debug/check-api-usage.ts
  • + scripts/debug/list-disciplines.ts
  • + src/app/api/v1/disciplines/route.ts
Modified (8):
  • ~ scripts/debug/check-api-usage.ts
  • ~ scripts/debug/list-disciplines.ts
  • ~ src/app/api/v1/competitions/[id]/route.ts
  • ~ src/app/api/v1/competitions/route.ts
  • ~ src/app/api/v1/disciplines/route.ts
  • ~ src/app/developers/page.tsx
  • ~ src/app/embed/scoreboard/route.ts
  • ~ src/lib/competition-results.ts

Version 0.2.519

Partner API: discipline + division filters, /api/v1/disciplines reference

July 4, 2026 at 2:16 PM GMT+0
05a2a59e
🔄Changed
  • Partner API: discipline + division filters, /api/v1/disciplines reference
  • /api/v1/competitions?discipline=<name>: include-semantics (an event matches
  • if any of its divisions run that discipline; Competition.disciplineId is
  • null for mixed cheer/dance events). Pre-fetched division/competition ids
  • per the no-nested-relation-filter rule; combines with producer/state/status.
  • /api/v1/competitions/{id}?division=<id|slug|exact name>: narrow results to

Files Changed

Created (3):
  • + scripts/debug/check-api-usage.ts
  • + scripts/debug/list-disciplines.ts
  • + src/app/api/v1/disciplines/route.ts
Modified (8):
  • ~ scripts/debug/check-api-usage.ts
  • ~ scripts/debug/list-disciplines.ts
  • ~ src/app/api/v1/competitions/[id]/route.ts
  • ~ src/app/api/v1/competitions/route.ts
  • ~ src/app/api/v1/disciplines/route.ts
  • ~ src/app/developers/page.tsx
  • ~ src/app/embed/scoreboard/route.ts
  • ~ src/lib/competition-results.ts

Version 0.2.518

feat: gym claiming + gym-admin content tools (flagged off pending soft launch)

July 4, 2026 at 12:38 PM GMT+0
771a2fbb
🔄Changed
  • feat: gym claiming + gym-admin content tools (flagged off pending soft launch)
  • Pro users can claim their gym via two verification paths: post a generated
  • "Follow us on FullOut" share image (1080x1080 with a QR code to the gym
  • page) to the gym's Instagram and submit the post URL for admin review, or
  • receive a 6-digit code at an address on the gym's website domain for
  • instant auto-approval. Claims land in the existing admin verification

Files Changed

Created (20):
  • + src/app/api/admin/gym-claims/[id]/route.ts
  • + src/app/api/gyms/[id]/admins/[userId]/route.ts
  • + src/app/api/gyms/[id]/admins/route.ts
  • + src/app/api/gyms/[id]/admins/transfer-owner/route.ts
  • + src/app/api/gyms/[id]/claim/route.ts
  • + src/app/api/gyms/[id]/claim/share-image/route.tsx
  • + src/app/api/gyms/[id]/photos/route.ts
  • + src/app/api/teams/[id]/photos/route.ts
  • + src/app/gyms/[id]/claim/page.tsx
  • + src/app/gyms/[id]/manage/page.tsx
  • + src/components/admin/gym-claim-approval-actions.tsx
  • + src/components/gyms/bulletin-board.tsx
  • + src/components/gyms/entity-photo-gallery.tsx
  • + src/components/gyms/gym-admin-manager.tsx
  • + src/components/gyms/gym-claim-wizard.tsx
  • + src/components/gyms/gym-profile-editor.tsx
  • + src/components/teams/team-bio-editor.tsx
  • + src/lib/__tests__/bio-links.test.ts
  • + src/lib/__tests__/gym-claims.test.ts
  • + src/lib/bio-links.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/verifications/page.tsx
  • ~ src/app/api/admin/gym-claims/[id]/route.ts
  • ~ src/app/api/gyms/[id]/admins/[userId]/route.ts
  • ~ src/app/api/gyms/[id]/admins/route.ts
  • ~ src/app/api/gyms/[id]/admins/transfer-owner/route.ts
  • ~ src/app/api/gyms/[id]/claim/route.ts
  • ~ src/app/api/gyms/[id]/claim/share-image/route.tsx
  • ~ src/app/api/gyms/[id]/photos/route.ts
  • ~ src/app/api/gyms/[id]/route.ts
  • ~ src/app/api/teams/[id]/banner/finalize/route.ts
  • ~ src/app/api/teams/[id]/banner/sign/route.ts
  • ~ src/app/api/teams/[id]/photos/route.ts
  • ~ src/app/api/teams/[id]/route.ts
  • ~ src/app/api/videos/route.ts
  • ~ src/app/gyms/[id]/claim/page.tsx
  • ~ src/app/gyms/[id]/manage/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/admin/gym-claim-approval-actions.tsx

Version 0.2.517

feat: Pro profile activation for coaches and choreographers + choreographer orgs

July 4, 2026 at 12:14 PM GMT+0
e924fba3
🔄Changed
  • feat: Pro profile activation for coaches and choreographers + choreographer orgs
  • Pro-tier users can now activate public Coach and Choreographer pages from
  • Settings > Profile Pages (or their profile menu). Activation creates a page
  • linked to their Person; their /@username profile gains Coaching and
  • Choreography tabs (season stats + credits, same components as the standalone
  • pages) plus role badges. Deactivation hides the page but keeps all credits.

Files Changed

Created (11):
  • + scripts/setup/seed-choreographer-orgs.ts
  • + src/app/api/profile/choreographer-page/route.ts
  • + src/app/api/profile/coach-page/route.ts
  • + src/app/settings/profile-pages/page.tsx
  • + src/components/profile/profile-activation-cards.tsx
  • + src/components/profile/profile-choreography-section.tsx
  • + src/components/profile/profile-coaching-section.tsx
  • + src/components/profile/profile-role-badges.tsx
  • + src/lib/__tests__/coaching-roles.test.ts
  • + src/lib/coaching-roles.ts
  • + src/lib/profile-pages.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/setup/seed-choreographer-orgs.ts
  • ~ src/app/admin/coaches/[id]/page.tsx
  • ~ src/app/admin/verifications/page.tsx
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/coaches/[id]/credits/[creditId]/route.ts
  • ~ src/app/api/coaches/[id]/credits/route.ts
  • ~ src/app/api/coaches/route.ts
  • ~ src/app/api/profile/choreographer-page/route.ts
  • ~ src/app/api/profile/coach-page/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/choreographers/page.tsx
  • ~ src/app/coaches/[id]/page.tsx
  • ~ src/app/coaches/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/settings/profile-pages/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/admin/coach-credit-form.tsx
  • ~ src/components/coaches/coach-credits-section.tsx
  • ~ src/components/profile/profile-activation-cards.tsx

Version 0.2.516

feat: unified personalized search + discipline hub pages

July 4, 2026 at 11:54 AM GMT+0
e9ec2814
🔄Changed
  • feat: unified personalized search + discipline hub pages
  • Search: one shared SQL core (src/lib/search/unified-search.ts) now powers
  • both /discover and the navbar autocomplete. Removes the REGEXP_REPLACE
  • anti-pattern from /api/search (incident 2026-05-25), ports gym-abbreviation
  • expansion to /discover, and ranks results with a weighted score: followed
  • entities, gyms of followed teams, sibling teams, rivals from your teams

Files Changed

Created (16):
  • + scripts/debug/explain-search.ts
  • + src/app/cheer/page.tsx
  • + src/app/college/page.tsx
  • + src/app/dance/page.tsx
  • + src/app/school/page.tsx
  • + src/components/hub/discipline-hub.tsx
  • + src/components/hub/set-discipline-cookie.tsx
  • + src/lib/__tests__/discipline-cookie.test.ts
  • + src/lib/discipline-cookie.ts
  • + src/lib/hubs/__tests__/hub-config.test.ts
  • + src/lib/hubs/hub-config.ts
  • + src/lib/hubs/hub-data.ts
  • + src/lib/search/__tests__/boost-context.test.ts
  • + src/lib/search/__tests__/unified-search.test.ts
  • + src/lib/search/boost-context.ts
  • + src/lib/search/unified-search.ts
Modified (20):
  • ~ scripts/debug/explain-search.ts
  • ~ src/app/api/search/route.ts
  • ~ src/app/cheer/page.tsx
  • ~ src/app/college/page.tsx
  • ~ src/app/dance/page.tsx
  • ~ src/app/discover/page.tsx
  • ~ src/app/gyms/page.tsx
  • ~ src/app/school/page.tsx
  • ~ src/app/teams/page.tsx
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/components/discipline-chips.tsx
  • ~ src/components/hub/discipline-hub.tsx
  • ~ src/components/hub/set-discipline-cookie.tsx
  • ~ src/lib/__tests__/discipline-cookie.test.ts
  • ~ src/lib/discipline-cookie.ts
  • ~ src/lib/hubs/__tests__/hub-config.test.ts
  • ~ src/lib/hubs/hub-config.ts
  • ~ src/lib/hubs/hub-data.ts
  • ~ src/lib/nav-config.ts
  • ~ src/lib/search/__tests__/boost-context.test.ts

Version 0.2.515

feat: unified personalized search + discipline hub pages

July 4, 2026 at 11:52 AM GMT+0
0bc2be84
🔄Changed
  • feat: unified personalized search + discipline hub pages
  • Cheer Daily technology-partner integration (docs/cheer-daily-partner-feed-plan.md):
  • ApiKey/ApiKeyUsage/ApiInvoice models: hashed admin-issued keys (secret
  • fo_live_ / publishable fo_pk_), scopes, domain binding, per-key rate limits,
  • daily usage rollups, off-platform monthly invoicing (PENDING/INVOICED/PAID).
  • /api/v1 read endpoints (scores/recent, competitions, competitions/{id})

Version 0.2.513

Partner data API + embeds: keyed /api/v1, widgets, admin issuance + invoicing

July 4, 2026 at 11:51 AM GMT+0
edc3b929
🔄Changed
  • Partner data API + embeds: keyed /api/v1, widgets, admin issuance + invoicing
  • Cheer Daily technology-partner integration (docs/cheer-daily-partner-feed-plan.md):
  • ApiKey/ApiKeyUsage/ApiInvoice models: hashed admin-issued keys (secret
  • fo_live_ / publishable fo_pk_), scopes, domain binding, per-key rate limits,
  • daily usage rollups, off-platform monthly invoicing (PENDING/INVOICED/PAID).
  • /api/v1 read endpoints (scores/recent, competitions, competitions/{id})

Files Changed

Created (20):
  • + scripts/debug/check-apple-txn-dupes.ts
  • + scripts/debug/get-gated-slug.ts
  • + scripts/setup/create-api-key.ts
  • + src/app/admin/api-keys/page.tsx
  • + src/app/api/admin/api-invoices/route.ts
  • + src/app/api/admin/api-keys/[id]/route.ts
  • + src/app/api/admin/api-keys/route.ts
  • + src/app/api/v1/competitions/[id]/route.ts
  • + src/app/api/v1/competitions/route.ts
  • + src/app/api/v1/scores/recent/route.ts
  • + src/app/developers/page.tsx
  • + src/app/embed/events/route.ts
  • + src/app/embed/scoreboard/route.ts
  • + src/app/embed/ticker/route.ts
  • + src/components/admin/api-keys-manager.tsx
  • + src/lib/__tests__/api-key-utils.test.ts
  • + src/lib/api-key-utils.ts
  • + src/lib/api-keys.ts
  • + src/lib/api-v1.ts
  • + src/lib/competition-results.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/debug/check-apple-txn-dupes.ts
  • ~ scripts/debug/get-gated-slug.ts
  • ~ scripts/setup/create-api-key.ts
  • ~ src/app/admin/api-keys/page.tsx
  • ~ src/app/api/admin/api-invoices/route.ts
  • ~ src/app/api/admin/api-keys/[id]/route.ts
  • ~ src/app/api/admin/api-keys/route.ts
  • ~ src/app/api/live-scores/route.ts
  • ~ src/app/api/v1/competitions/[id]/route.ts
  • ~ src/app/api/v1/competitions/route.ts
  • ~ src/app/api/v1/scores/recent/route.ts
  • ~ src/app/developers/page.tsx
  • ~ src/app/embed/events/route.ts
  • ~ src/app/embed/scoreboard/route.ts
  • ~ src/app/embed/ticker/route.ts
  • ~ src/components/admin/api-keys-manager.tsx
  • ~ src/lib/__tests__/api-key-utils.test.ts
  • ~ src/lib/api-key-utils.ts
  • ~ src/lib/api-keys.ts

Version 0.2.512

Gated history visible to authorized viewers on team/gym profiles

July 4, 2026 at 10:15 AM GMT+0
a7147c02
🔒Security
  • Gated history visible to authorized viewers on team/gym profiles
  • Bug (reported with screenshots): a gatekeeper/admin drills from a gated
  • division scorecard into a team profile and sees "0 performances all
  • time" — e.g. Fame / World Class Allstars (AR), whose 9 performances are
  • all gated (Redline events + ASW). The division page widens access with
  • the base client after an access check, but the team/gym profile

Files Changed

Created (1):
  • + src/lib/gated-visibility.ts
Modified (6):
  • ~ src/app/api/gyms/[id]/performances/route.ts
  • ~ src/app/api/gyms/[id]/route.ts
  • ~ src/app/api/teams/[id]/route.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/lib/gated-visibility.ts

Version 0.2.511

Dedupe ASW duplicate gyms + harden import gym matcher

July 3, 2026 at 11:43 PM GMT+0
897bc88d
🔄Changed
  • Dedupe ASW duplicate gyms + harden import gym matcher
  • The ASW import's conservative matcher missed a small tail of duplicate
  • gyms (16 of 4,568 performances): the platform's "- <STATE>" location
  • suffixes ("Infinity Allstars - FL") aren't stripped by the variant
  • rules, and two same-name accounts in one concurrent chunk raced past
  • the in-memory index (PowerHouse Dance Academy x2 — gym name/slug are

Files Changed

Created (1):
  • + scripts/maintenance/merge-asw-duplicate-gyms.ts
Modified (2):
  • ~ scripts/import/import-asw.ts
  • ~ scripts/maintenance/merge-asw-duplicate-gyms.ts

Version 0.2.510

EP Program v1: rev-share settlement, origin tagging, EP/Broker/admin dashboards

July 3, 2026 at 11:29 PM GMT+0
e34c8342
Added
  • EP (Event Producer) Program: producers pay a per-EP monthly minimum and earn
  • rev share (default 20%, per-relationship editable) on subscriptions they bring;
  • credits net against the minimum monthly. Broker model: an EP tagged with a
  • broker earns that broker a 10% override as pure FullOut cost.
  • Durable first-touch origin tagging: free signups arriving via a partner/EP
  • link are stamped at registration and credit the EP when they convert later,
  • far past the 30-day cookie. Precedence: promo code > origin > cookie > hybrid.
  • Monthly settlement engine + cron (1st, 06:00 UTC, EP_SETTLEMENT_ENABLED gated,
  • idempotent): sweeps commissions into an append-only accrual ledger with rates
  • frozen at earn time, prorates minimums, writes broker overrides, and produces
  • per-period statements (EP owes / FullOut owes / zero).
  • Admin EP Tier dashboard (/admin/event-producers): program rollups, per-EP
  • console with editable terms + contact/billing CRM, settlement queue with
  • mark-invoiced/mark-paid/queue-payout (billing settles off-platform).
  • Producer EP dashboard (/event-producers/[slug]/program): negotiated terms,
  • minimum-offset progress, conversions by type, earned-vs-minimum and stacked
  • charts, per-subscriber rate card, promo links, origin funnel, and a broker
  • section with per-EP override earnings. All figures before tax and fees.
  • Payout generalization: WIRE/ACH/CRYPTO/OTHER methods with crypto settlement
  • audit fields (USD stays authoritative); payouts held until W-9 on file.
  • Redline rollout: Partner (slug redline, 20%, 36-month tail) + complimentary
  • EP subscription through 2029-07-03 per the signed term sheet.

Files Changed

Created (19):
  • + src/lib/origin-attribution.ts
  • + src/lib/ep-settlement.ts
  • + src/app/api/cron/ep-monthly-settlement/route.ts
  • + src/app/api/admin/event-producers/route.ts
  • + src/app/api/admin/event-producers/[id]/route.ts
  • + src/app/api/admin/event-producers/[id]/contacts/route.ts
  • + src/app/api/admin/event-producers/statements/[statementId]/route.ts
  • + src/app/api/admin/event-producers/run-close/route.ts
  • + src/app/admin/event-producers/page.tsx
  • + src/app/admin/event-producers/[id]/page.tsx
  • + src/app/admin/event-producers/settlements/page.tsx
  • + src/app/event-producers/[slug]/program/page.tsx
  • + src/components/admin/event-producers/ep-subscription-form.tsx
  • + src/components/admin/event-producers/ep-terms-form.tsx
  • + src/components/admin/event-producers/ep-contacts-card.tsx
  • + src/components/admin/event-producers/ep-statement-actions.tsx
  • + src/components/event-producers/ep-program-charts.tsx
  • + src/lib/__tests__/ep-settlement.test.ts
  • + scripts/setup/create-redline-ep-program.ts
Modified (5):
  • ~ prisma/schema.prisma
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/lib/partner-attribution.ts
  • ~ vercel.json

Version 0.2.508

Division age/size normalization + tolerant division history matching

July 3, 2026 at 10:52 PM GMT+0
9979484b
🔄Changed
  • Division age/size normalization + tolerant division history matching
  • The division-page history queries exact-match prior performances on
  • (level, ageCategory, sizeCategory), so spelling drift made gated-event
  • teams' history invisible: The Open platform's parseAge took the label's
  • first word (junk ages like "Level", "Small", "Youth-X-Small-A",
  • CheerAbilities-as-age), OPEN divisions carry their level in the label

Files Changed

Created (2):
  • + scripts/maintenance/normalize-open-division-fields.ts
  • + src/lib/division-fields.ts
Modified (7):
  • ~ scripts/import/import-asw.ts
  • ~ scripts/import/lib/open-division-parse.ts
  • ~ scripts/maintenance/normalize-open-division-fields.ts
  • ~ scripts/maintenance/repair-asw-division-links.ts
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/lib/division-fields.ts
  • ~ src/lib/prisma.ts

Version 0.2.507

Move ASW under The Open Championship Series producer (gated)

July 3, 2026 at 10:51 PM GMT+0
0e5822ca
🔄Changed
  • Move ASW under The Open Championship Series producer (gated)
  • ASW is The Open Championship Series' season-ending destination event, so
  • its 5 competitions (2022-2026) now belong to that producer instead of
  • Redline Championships. The Open producer is flipped to GATED (slug
  • "the-open") BEFORE any competitions point at it, and every Redline
  • EventProducerAccess grant is mirrored onto it so the same gatekeepers

Files Changed

Created (1):
  • + scripts/maintenance/move-asw-to-open-producer.ts
Modified (3):
  • ~ scripts/import/import-asw.ts
  • ~ scripts/maintenance/move-asw-to-open-producer.ts
  • ~ scripts/setup/grant-redline-access.ts

Version 0.2.505

Import Allstar World Championship historicals (gated) + division repair

July 3, 2026 at 1:57 PM GMT+0
58585180
🔄Changed
  • Import Allstar World Championship historicals (gated) + division repair
  • Load 5 seasons (2021-22..2025-26) of ASW finals, 4,568 performances
  • across 5 competitions, as CONFIDENTIAL gated data under the existing
  • Redline Championships producer so the same EventProducerAccess
  • gatekeepers apply with no new plumbing. New "Allstar World Championship"
  • series for browsing; the newest ASW event becomes The Open Championships

Files Changed

Created (11):
  • + scripts/debug/asw-progress.ts
  • + scripts/debug/audit-asw-gym-matches.ts
  • + scripts/debug/check-asw-division-links.ts
  • + scripts/debug/check-gated-schedules.ts
  • + scripts/debug/inspect-asw-sheets.ts
  • + scripts/debug/verify-asw-import.ts
  • + scripts/import/import-asw.ts
  • + scripts/import/lib/open-division-parse.ts
  • + scripts/maintenance/repair-asw-division-links.ts
  • + scripts/setup/create-kevin-pro.ts
  • + scripts/setup/grant-redline-access.ts
Modified (11):
  • ~ scripts/debug/asw-progress.ts
  • ~ scripts/debug/audit-asw-gym-matches.ts
  • ~ scripts/debug/check-asw-division-links.ts
  • ~ scripts/debug/check-gated-schedules.ts
  • ~ scripts/debug/inspect-asw-sheets.ts
  • ~ scripts/debug/verify-asw-import.ts
  • ~ scripts/import/import-asw.ts
  • ~ scripts/import/lib/open-division-parse.ts
  • ~ scripts/maintenance/repair-asw-division-links.ts
  • ~ scripts/setup/create-kevin-pro.ts
  • ~ scripts/setup/grant-redline-access.ts

Version 0.2.505

API rate limiting (infra, inert until configured) — protect public routes + Disk IO

July 3, 2026 at 5:00 AM GMT+0
pending
Added
  • Per-IP rate limiting on public /api data routes at the edge (Upstash Redis),
  • with a tighter cap on the Disk-IO-heavy /api/gyms/density and /api/search
  • endpoints. Closes the gap where a scraper with a real browser User-Agent
  • sails past the UA blocklist, and prevents crawler floods from exhausting the
  • Supabase Disk-IO budget (a past cause of site-wide 504s).
  • SAFE BY DEFAULT: completely inert unless UPSTASH_REDIS_REST_URL/TOKEN are set
  • AND RATE_LIMIT_MODE is 'monitor' or 'enforce'. Fail-open on any limiter error.
  • Pages and static assets are never rate-limited (zero page-latency impact).
  • First step of the API hardening + /api/v1 plan (docs/api-hardening-and-v1-plan.md).

Files Changed

Modified (5):
  • ~ src/lib/ratelimit.ts
  • ~ src/middleware.ts
  • ~ src/app/api/gyms/density/route.ts
  • ~ src/app/api/search/route.ts
  • ~ package.json

Version 0.2.504

Gating: close nested-include hole + gated-series browsing

July 3, 2026 at 1:55 PM GMT+0
a61a8ad0
🔄Changed
  • Gating: close nested-include hole + gated-series browsing
  • Prisma query extensions only fire on top-level operations, so gated
  • Performance/Competition/Score rows leaked through nested includes on
  • non-gated parents (teams directory, gym profiles, series pages, public
  • team/gym/coach APIs). Add a $allModels extension layer that walks every
  • read's include/select tree (DMMF-resolved relations) and injects the

Files Changed

Created (1):
  • + scripts/debug/verify-nested-gating.ts
Modified (4):
  • ~ scripts/debug/verify-nested-gating.ts
  • ~ src/app/competitions/series/[seriesSlug]/page.tsx
  • ~ src/app/competitions/series/page.tsx
  • ~ src/lib/prisma.ts

Version 0.2.503

teams/[id]: split heavy getTeam query + drop nested Person filter

July 2, 2026 at 2:08 PM GMT+0
b99cb7f1
🔄Changed
  • teams/[id]: split heavy getTeam query + drop nested Person filter
  • Harden the team page against intermittent 504s under PgBouncer contention.
  • Pull Performance out of the monster getTeam findFirst into a separate
  • getTeamPerformances() findMany, fetched in the same Promise.all so it
  • parallelizes with the base entity. Removes the 3-4 level nested include
  • (Performance -> Competition/Division/Score/Deduction) that CLAUDE.md flags.

Files Changed

Modified (1):
  • ~ src/app/teams/[id]/page.tsx

Version 0.2.502

Event producers index: allowlist to Varsity, Redline, The Open, USASF

July 1, 2026 at 6:53 PM GMT+0
bec74c39
🔄Changed
  • Event producers index: allowlist to Varsity, Redline, The Open, USASF
  • Restrict the public event-producers index to four producers, matched by
  • exact (case-insensitive) name so Varsity Brands is not swept in with
  • Varsity. Redline Championships stays subject to its GATED visibility
  • check, so it only appears for admins or granted viewers.
  • Claude-Session: https://claude.ai/code/session_01GyNpHJtXj4Dd1n3DQ9xgy6

Files Changed

Modified (1):
  • ~ src/app/event-producers/page.tsx

Version 0.2.496

Prospects contacts: show Instagram bio links

June 25, 2026 at 9:20 PM GMT+0
5d5560d0
🔄Changed
  • Prospects contacts: show Instagram bio links
  • The Show-contacts expand now lists the gym Instagram bio links (registration,
  • tryouts, Linktree, etc.) alongside website/IG/phone/email, deduped against the
  • primary website.

Files Changed

Modified (2):
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.495

Gym Instagram enrichment: verified logos, website, bio, bio-links

June 25, 2026 at 9:17 PM GMT+0
b2745b37
🔄Changed
  • Gym Instagram enrichment: verified logos, website, bio, bio-links
  • Add Gym.bioLinks (JSONB) for the gym's Instagram profile links.
  • enrich-gyms-instagram: for top gyms with a handle, hit IG's public
  • web_profile_info (via curl — Node fetch trips IG's Sec-Fetch WAF), VERIFY
  • the profile full_name matches the gym name, then fill logoUrl (hosted HD
  • profile pic), websiteUrl, description (bio), and bioLinks. Only the matched

Files Changed

Created (1):
  • + scripts/maintenance/enrich-gyms-instagram.ts
Modified (2):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/enrich-gyms-instagram.ts

Version 0.2.494

Redline event logos: host + display; gym enrichment tooling

June 25, 2026 at 9:02 PM GMT+0
a2bd5af8
🔄Changed
  • Redline event logos: host + display; gym enrichment tooling
  • Found logos for all 32 Redline events, rasterized SVGs to PNG, hosted on
  • Supabase (gym-assets/events/<id>/logo.png) and set Competition.photoUrl.
  • Producer event list now shows each event's logo; competition headers pick
  • it up automatically (photoUrl).
  • scripts/maintenance: host-logos (download -> sharp SVG rasterize -> Supabase

Files Changed

Created (2):
  • + scripts/maintenance/host-logos.ts
  • + scripts/maintenance/import-gym-contacts.ts
Modified (4):
  • ~ scripts/maintenance/host-logos.ts
  • ~ scripts/maintenance/import-gym-contacts.ts
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-events-list.tsx

Version 0.2.493

Producer events list: client Load-more pagination

June 25, 2026 at 8:16 PM GMT+0
3ae1f1ea
🔄Changed
  • Producer events list: client Load-more pagination
  • Replaces the fixed 60-event cap with a client ProducerEventsList that renders
  • 30 at a time with a "Load more" button. Server fetches up to 400 events
  • (covers a full season) with their result counts + disciplines; the footer
  • notes when older events require a season filter.

Files Changed

Created (1):
  • + src/components/competitions/producer-events-list.tsx
Modified (2):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-events-list.tsx

Version 0.2.492

Prospects tab: map-viewport table filter + expandable contact info

June 25, 2026 at 7:54 PM GMT+0
4f1a9324
🔄Changed
  • Prospects tab: map-viewport table filter + expandable contact info
  • "Match map view" toggle: the prospects table follows the visible map area
  • (pan/zoom updates the list). Map reports bounds via onBoundsChange.
  • "Show contacts" toggle: reveals website / Instagram / phone / email links
  • under each gym for outreach (data is sparse for now). Prospect rows now
  • carry websiteUrl/instagramHandle/phone/email from the gym record.

Files Changed

Modified (3):
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/components/competitions/prospects-map.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.491

Producer page: clarify events scope + make attendee intelligence single-season

June 25, 2026 at 7:46 PM GMT+0
ac9f1efe
🔄Changed
  • Producer page: clarify events scope + make attendee intelligence single-season
  • Attendee intelligence now always reflects ONE season (selected, or most
  • recent by default), labeled in its header ("... · 2025-2026 season") and
  • tab copy. Its scope (attendees/geography/retention/prospects + the prospect
  • map's event dots and distance) is computed from that one season, decoupled
  • from the events list. Removes the confusing mixed scope where the list

Files Changed

Modified (2):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-attendee-insights.tsx

Version 0.2.490

Fix prospects=0 for long-lived producers; match prospects-map height

June 25, 2026 at 7:40 PM GMT+0
99ab016b
🐛Fixed
  • Fix prospects=0 for long-lived producers; match prospects-map height
  • Prospect exclusion now uses gyms that attended in the CURRENT season only,
  • decoupled from the display scope (new attendedExcludeScopeIds arg). The
  • all-seasons view was excluding every gym that ever attended, which zeroed
  • out prospects for Varsity (27 seasons). Varsity now shows ~650, not 0.
  • Prospects-tab map height matched to the main event-locations map

Files Changed

Modified (3):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/prospects-map.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.489

Add Event Producers nav link, taller producer map, gym backfill scripts

June 25, 2026 at 7:27 PM GMT+0
3f02eb62
Added
  • Add Event Producers nav link, taller producer map, gym backfill scripts
  • nav-config: add "Event Producers" (/event-producers) to the bottom of the
  • Explore group (shared by desktop sidebar + mobile drawer).
  • Producer events map: taller (520px mobile / 640px desktop) for easier reading.
  • scripts/maintenance: reverse-geocode-gym-cities (backfill city/state from
  • coords) and import-gym-locations (geocode + write agent-found gym locations).

Files Changed

Created (2):
  • + scripts/maintenance/import-gym-locations.ts
  • + scripts/maintenance/reverse-geocode-gym-cities.ts
Modified (4):
  • ~ scripts/maintenance/import-gym-locations.ts
  • ~ scripts/maintenance/reverse-geocode-gym-cities.ts
  • ~ src/components/competitions/producer-events-map.tsx
  • ~ src/lib/nav-config.ts

Version 0.2.488

Prospects map: legend shows mapped-of-total counts

June 25, 2026 at 2:53 PM GMT+0
33ae9093
🔄Changed
  • Prospects map: legend shows mapped-of-total counts
  • Legend now reads "Attended (489 of 515)" / "Not attending (952 of 991)" so
  • the on-map dot count (gyms with resolvable coordinates) is clearly
  • distinguished from the true unique-gym total. Resolves the map-vs-stat-card
  • discrepancy the user hit.

Files Changed

Modified (1):
  • ~ src/components/competitions/prospects-map.tsx

Version 0.2.487

Rename Redline producer to Redline Championships

June 25, 2026 at 2:34 PM GMT+0
524a3b3e
🔄Changed
  • Rename Redline producer to Redline Championships
  • DB EventProducer.name updated (slug redline). Updated the hardcoded producer
  • name in the import/maintenance scripts so re-runs stay consistent, and
  • switched the debug lookups to find by slug (stable) instead of by name.

Files Changed

Modified (4):
  • ~ scripts/debug/redline-final-counts.ts
  • ~ scripts/debug/verify-redline-gating.ts
  • ~ scripts/import/import-redline-open.ts
  • ~ scripts/maintenance/purge-redline.ts

Version 0.2.486

Expand US_CITY_COORDS with 2,344 geocoded gym home cities

June 25, 2026 at 3:45 AM GMT+0
71203412
🔄Changed
  • Expand US_CITY_COORDS with 2,344 geocoded gym home cities
  • Ran scripts/maintenance/geocode-gym-cities.ts: 680 -> 3,024 cities. Lifts
  • map coverage of Redline attended gyms from 234/515 (45%) to 489/515 (95%);
  • Cordova, TN and other small-town gyms now plot. Fixes every map (producer
  • attendee/prospect maps + gym maps) since they all read this lookup.

Files Changed

Modified (1):
  • ~ src/lib/us-city-coords.ts

Version 0.2.485

Add gym-cities geocoder to widen map coordinate coverage

June 25, 2026 at 2:39 AM GMT+0
995bbdca
Added
  • Add gym-cities geocoder to widen map coordinate coverage
  • Geocodes distinct gym HOME (city, state) pairs missing from US_CITY_COORDS
  • via Nominatim and appends them, so attendee/prospect/gym maps can place the
  • ~55% of gyms that small-town home cities (e.g. Cordova, TN) left unmapped.
  • Filters to US states, flushes every 50 so a long run survives interruption.

Files Changed

Created (1):
  • + scripts/maintenance/geocode-gym-cities.ts
Modified (1):
  • ~ scripts/maintenance/geocode-gym-cities.ts

Version 0.2.484

Prospects map: separate overlapping city dots + layer show/hide toggles

June 25, 2026 at 2:19 AM GMT+0
cedecce6
🔄Changed
  • Prospects map: separate overlapping city dots + layer show/hide toggles
  • Smaller dot cap (16) and a wider triangle offset (event up, attended
  • lower-left, prospect lower-right) so a city with multiple layers shows
  • distinct dots instead of one perfectly covering another.
  • Legend is now interactive: tap Events / Attended / Not attending to show
  • or hide that layer. The click popup respects the toggles.

Files Changed

Modified (1):
  • ~ src/components/competitions/prospects-map.tsx

Version 0.2.483

Prospects: widen active window to this season + prior season

June 25, 2026 at 2:14 AM GMT+0
682af880
🔄Changed
  • Prospects: widen active window to this season + prior season
  • Non-attending prospects now include gyms that competed at a public
  • competition in the current OR previous season (not only this season), so
  • recently-active gyms that have not competed yet this season still appear.
  • Redline footprint goes 839 -> 991 prospects. ~0.9s.

Files Changed

Modified (2):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-attendee-insights.tsx

Version 0.2.482

Prospects map: unified city popup, clickable events, triangle dot layout

June 25, 2026 at 1:51 AM GMT+0
db437572
🔄Changed
  • Prospects map: unified city popup, clickable events, triangle dot layout
  • Clicking a city now queries all three layers and shows one popup with its
  • events (links to each competition), attended gyms, and non-attending gyms,
  • so overlapping dots are all reachable from a single click. Event dots are
  • clickable and link to their event(s). Events/attended/prospect dots are
  • offset into a small triangle so a shared city shows all three.

Files Changed

Modified (2):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/prospects-map.tsx

Version 0.2.481

Prospects map: draw event dots as the top layer

June 25, 2026 at 1:24 AM GMT+0
aa69b041
🔄Changed
  • Prospects map: draw event dots as the top layer

Files Changed

Modified (1):
  • ~ src/components/competitions/prospects-map.tsx

Version 0.2.480

Prospects map: capture all non-attending gyms; events as sized dark dots

June 25, 2026 at 1:13 AM GMT+0
a1458b8c
🔄Changed
  • Prospects map: capture all non-attending gyms; events as sized dark dots
  • Prospect cap raised 300 -> 3000 so the full non-attending universe shows
  • (incl. small/D2 gyms). Redline went from 300 to 839 prospects (811 mapped,
  • 426 city dots) with no real perf cost -- the aggregate scans the same data.
  • Event markers are now solid dark dots sized by how many events the city
  • hosts (instead of hollow rings), drawn beneath the gym layers so the green

Files Changed

Modified (3):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/prospects-map.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.479

Prospects map: aggregate gyms by city, size by count, fix occlusion

June 25, 2026 at 1:05 AM GMT+0
c86d5713
🔄Changed
  • Prospects map: aggregate gyms by city, size by count, fix occlusion
  • Gyms are now aggregated into one dot per city, sized by how many gyms are
  • there (area ~ count), instead of one fixed dot per gym stacking on itself.
  • Event markers are hollow rings sized to encircle the city's data dot, so
  • attended/prospect gyms in an event city (e.g. Frisco) are no longer hidden
  • under a filled event dot.

Files Changed

Modified (2):
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/components/competitions/prospects-map.tsx

Version 0.2.478

Prospects tab: filter-driven map (events / attended / not-attending)

June 25, 2026 at 12:47 AM GMT+0
32433a3f
🔄Changed
  • Prospects tab: filter-driven map (events / attended / not-attending)
  • New ProspectsMap: GeoJSON circle layers for event cities (dark), gyms
  • that attended (green), and non-attending prospects (red), plus always-on
  • state outlines, a legend with live counts, and click-to-popup (gym name
  • link + teams/perfs/distance).
  • The map is driven by the same filters as the table: state chips scope

Files Changed

Created (1):
  • + src/components/competitions/prospects-map.tsx
Modified (4):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/components/competitions/prospects-map.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.477

Maps: switch to light Voyager base + always-on state outlines

June 25, 2026 at 12:38 AM GMT+0
ce393da1
🔄Changed
  • Maps: switch to light Voyager base + always-on state outlines
  • New shared MAP_STYLE constant (src/lib/map-style.ts) = CARTO Voyager
  • (light, colorful, no API key). One place to restyle every map.
  • Producer events map: Voyager base, markers retuned for the light base
  • (white halo borders; blue "selected" state, since the old yellow was
  • invisible on light), and an always-on US state outline layer so borders

Files Changed

Created (1):
  • + src/lib/map-style.ts
Modified (4):
  • ~ src/components/competitions/gym-wins-map.tsx
  • ~ src/components/competitions/producer-events-map.tsx
  • ~ src/components/gyms/gyms-map.tsx
  • ~ src/lib/map-style.ts

Version 0.2.476

Producer attendee intelligence: fix mobile layout

June 24, 2026 at 11:45 PM GMT+0
bad63889
🔄Changed
  • Producer attendee intelligence: fix mobile layout
  • Tab strip was wrapping inside a fixed-height TabsList, so Retention and
  • Prospects rendered outside the box (overlapping text, untappable). Now a
  • 2x2 grid with auto height on mobile, normal inline-flex on >= sm.
  • Tables were too cramped on narrow screens (gym names crushed to "S.."):
  • hide the gym logo on mobile, tighten the # column and gap, and shrink the

Files Changed

Modified (1):
  • ~ src/components/competitions/producer-attendee-insights.tsx

Version 0.2.475

Producer attendee intelligence: collapsible, sortable, filterable + blast radius

June 24, 2026 at 10:22 PM GMT+0
a7ff0333
🔄Changed
  • Producer attendee intelligence: collapsible, sortable, filterable + blast radius
  • Whole "Attendee intelligence" section is now collapsible (collapsed by
  • default) via ProducerAttendeeSection; still PRO-gated.
  • Top gyms: sortable columns (Teams / Perfs / Events) + 25-per-page
  • pagination. Helper now returns up to 1000 attendees; geography and
  • retention still compute from the full attendee set.

Files Changed

Modified (3):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.474

Producer page: PRO attendee intelligence (gyms, geography, retention, prospects)

June 24, 2026 at 10:12 PM GMT+0
7d020a13
🔄Changed
  • Producer page: PRO attendee intelligence (gyms, geography, retention, prospects)
  • Adds a season-scoped "Attendee intelligence" section to the event
  • producer page, gated to the PRO tier (hasCompetitorIntelligence):
  • Top gyms: biggest customers ranked by teams brought, plus perfs and events
  • Geography: where attendees travel from, by home state
  • Retention: new vs returning vs churned (when a season is selected), plus

Files Changed

Created (2):
  • + src/components/competitions/producer-attendee-insights.tsx
  • + src/lib/producer-analytics.ts
Modified (3):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-attendee-insights.tsx
  • ~ src/lib/producer-analytics.ts

Version 0.2.473

Producer events map: clearer popup close button

June 24, 2026 at 8:45 PM GMT+0
44566e2f
🔄Changed
  • Producer events map: clearer popup close button
  • Disable the faint default MapLibre X (it overlapped the inner
  • scrollbar) and add a visible close button in a fixed card header,
  • above the independently-scrolling event list.

Files Changed

Modified (1):
  • ~ src/components/competitions/producer-events-map.tsx

Version 0.2.472

Producer events map: stronger dot-size scaling for low counts

June 24, 2026 at 8:43 PM GMT+0
0c268c52
🔄Changed
  • Producer events map: stronger dot-size scaling for low counts
  • sqrt(count)*7+4 instead of pow(count,0.65)*5 so 1 vs 2 vs 3 events
  • are clearly distinguishable (the old min floor collapsed them to the
  • same size).

Files Changed

Modified (1):
  • ~ src/components/competitions/producer-events-map.tsx

Version 0.2.471

Producer events map: proportional dot sizing instead of count bubbles

June 24, 2026 at 8:37 PM GMT+0
1ccf4b51
🔄Changed
  • Producer events map: proportional dot sizing instead of count bubbles
  • Bigger dot = more events in that city, matching the gyms map on
  • competition pages. Count still shows in the click popup; selected
  • city gets a highlight ring.

Files Changed

Modified (1):
  • ~ src/components/competitions/producer-events-map.tsx

Version 0.2.470

Team dedup: merge 341 duplicates + durable import chokepoint

June 24, 2026 at 8:30 PM GMT+0
98031c5d
🔄Changed
  • Team dedup: merge 341 duplicates + durable import chokepoint
  • Identity model for a team is (gym, discipline, name-core). The program
  • prefix ("Dance Athletics", "STUNT Athletics", "Cheer Athletics") is a
  • redundant echo of disciplineId, so it is stripped and discipline drives
  • the program label.
  • One-time cleanup:

Files Changed

Created (4):
  • + prisma/migrations/add_team_unique_name_gym_discipline.sql
  • + scripts/maintenance/apply-team-unique-index-discipline.ts
  • + scripts/maintenance/audit-team-dedup-by-discipline.ts
  • + scripts/maintenance/execute-team-dedup-by-discipline.ts
Modified (7):
  • ~ prisma/migrations/add_team_unique_name_gym_discipline.sql
  • ~ scripts/maintenance/apply-team-unique-index-discipline.ts
  • ~ scripts/maintenance/audit-team-dedup-by-discipline.ts
  • ~ scripts/maintenance/execute-team-dedup-by-discipline.ts
  • ~ scripts/maintenance/normalize-team-names.ts
  • ~ src/lib/import/team-matcher.ts
  • ~ src/lib/teams/normalize-team-name.ts

Version 0.2.470

Team dedup: merge 341 duplicates + durable import chokepoint (program prefixes, discipline-scoped)

June 24, 2026 at 5:00 AM GMT+0
41a1efea
🐛Fixed
  • Merged 341 duplicate teams (e.g. 'Dance Athletics - Comet Crew' into 'Comet Crew') where one physical team was imported under a program-prefixed or spacing-variant name; scoped to (gym, discipline) so cross-discipline same-name teams ('Comet Crew' Dance vs 'CometCats' Cheer) are never merged
  • Import team-matcher now strips named-program prefixes ('Dance Athletics', 'STUNT Athletics', 'Cheer Athletics') in addition to the gym name, so re-imports match the existing team instead of minting a new variant
  • Team matching (exact + fuzzy + cache key) is now scoped by disciplineId
  • Swapped the Team unique index from (lower(name), gymId) to (lower(name), gymId, disciplineId) so a gym may field same-named teams across disciplines

Files Changed

Created (4):
  • + scripts/maintenance/audit-team-dedup-by-discipline.ts
  • + scripts/maintenance/execute-team-dedup-by-discipline.ts
  • + prisma/migrations/add_team_unique_name_gym_discipline.sql
  • + scripts/maintenance/apply-team-unique-index-discipline.ts
Modified (3):
  • ~ src/lib/teams/normalize-team-name.ts
  • ~ src/lib/import/team-matcher.ts
  • ~ scripts/maintenance/normalize-team-names.ts

Version 0.2.469

Division detail page: gating-aware for confidential producer competitions

June 24, 2026 at 7:55 PM GMT+0
a13e5588
🔄Changed
  • Division detail page: gating-aware for confidential producer competitions
  • The division page fetched the competition under the default (gated) scope, so Redline division pages 404'd. Now reads via the base client with an explicit access check (admin or EventProducerAccess), and authorized viewers of gated data bypass the Elite tier gate (it's their own producer's data). Public competitions are unchanged.

Files Changed

Modified (1):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx

Version 0.2.468

Geocode competition venue cities into US_CITY_COORDS (+120 cities)

June 24, 2026 at 7:46 PM GMT+0
2d15d1b0
🔄Changed
  • Geocode competition venue cities into US_CITY_COORDS (+120 cities)
  • Adds 120 geocoded city/state pairs (Nominatim) used by competition venues, so ~384 more competitions place on the event-producer maps. 7 skipped: international (Canada/Japan) or placeholder/typo cities. Includes the reusable geocode script.

Files Changed

Created (1):
  • + scripts/maintenance/geocode-competition-cities.ts
Modified (2):
  • ~ scripts/maintenance/geocode-competition-cities.ts
  • ~ src/lib/us-city-coords.ts

Version 0.2.467

Event producer page: discipline badges on each event

June 24, 2026 at 7:34 PM GMT+0
f9a2674a
🔄Changed
  • Event producer page: discipline badges on each event
  • Shows the distinct disciplines at each listed event (derived from its divisions), e.g. 'All Star' + 'Dance'.

Files Changed

Modified (1):
  • ~ src/app/event-producers/[slug]/page.tsx

Version 0.2.466

Event producer page: season filter for events list, map, and stats

June 24, 2026 at 7:26 PM GMT+0
4ec78dc5
🔄Changed
  • Event producer page: season filter for events list, map, and stats
  • Adds a season dropdown (?season=) that filters the events list, the location map, and the stat counts. Hidden for single-season producers (Redline); shows 27 seasons for Varsity, 22 for USASF. Seasons computed July-June to match the team chart.

Files Changed

Created (1):
  • + src/components/competitions/producer-season-filter.tsx
Modified (2):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/components/competitions/producer-season-filter.tsx

Version 0.2.465

Event producer page: add Instagram link to header

June 24, 2026 at 7:18 PM GMT+0
498ad23b
🔄Changed
  • Event producer page: add Instagram link to header
  • Renamed the Worlds producer to USASF (its actual organizer) with logo + Instagram; the 22 'The Cheerleading Worlds' events remain tagged to it. Header now renders an Instagram link when instagramHandle is set.

Files Changed

Modified (1):
  • ~ src/app/event-producers/[slug]/page.tsx

Version 0.2.464

Producer badge: render logo at natural aspect with contrasting tile

June 24, 2026 at 7:06 PM GMT+0
a334c1a6
🔄Changed
  • Producer badge: render logo at natural aspect with contrasting tile
  • Horizontal logos (Worlds, Varsity) were squished into a square and dark logos were invisible on the dark badge. Use h-4 + auto width and a white/dark mini-tile per logo so all read cleanly.

Files Changed

Modified (1):
  • ~ src/components/competitions/producer-badge.tsx

Version 0.2.463

Producer logos: dark tile for white logos, light tile for dark logos

June 24, 2026 at 7:01 PM GMT+0
fbabb2a0
🔄Changed
  • Producer logos: dark tile for white logos, light tile for dark logos
  • Redline's logo is white (invisible on a light card); Varsity/Worlds are dark (invisible on a dark tile). Pick the tile background per logo so both render in light and dark themes.

Files Changed

Modified (3):
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/app/event-producers/page.tsx
  • ~ src/components/competitions/producer-badge.tsx

Version 0.2.462

Gating perf: filter raw queries on c.isGated, not p.isGated

June 24, 2026 at 6:41 PM GMT+0
b0f77306
🔄Changed
  • Gating perf: filter raw queries on c.isGated, not p.isGated
  • Filtering isGated on the ~340k-row Performance table added ~5-7s/query and pushed the heavy leaderboards page over its 30s limit (intermittent 504s). Gated performances all belong to gated competitions, so filtering on the already-joined Competition (c.isGated, ~32 gated of ~2k) prunes via the join and is ~7s faster. EXPLAIN-verified: 15.9s -> 9.0s.

Files Changed

Modified (7):
  • ~ src/app/api/gyms/density/route.ts
  • ~ src/app/api/leaderboards/[teamId]/breakdown/route.ts
  • ~ src/app/api/leaderboards/route.ts
  • ~ src/app/api/teams/[id]/competition-analysis/route.ts
  • ~ src/app/leaderboards/page.tsx
  • ~ src/lib/gym-efficiency-data.ts
  • ~ src/lib/teams/current-division.ts

Version 0.2.461

Event Producers: index page, event-location map, producer badges, Varsity/Worlds

June 24, 2026 at 6:25 PM GMT+0
e8b2a5bd
🔄Changed
  • Event Producers: index page, event-location map, producer badges, Varsity/Worlds
  • /event-producers index listing producers (Redline, Varsity, Worlds)
  • Producer page: event-location map (replaces teams map) with readable popup + click-out close; generalized stats/list to handle large producers (Varsity ~1,900 events); Redline logo
  • Competition pages: producer badge (logo, hover=name, click->producer); standard layout for all incl. Redline; base-client reveal with explicit gating check
  • Multi-line team chart split by scoring system; gating-context pinned to globalThis
  • Backfill scripts: Varsity/Worlds producers + scoringSystemTag on ~1,900 comps, Redline slugs + venue locations; import sets slugs

Files Changed

Created (6):
  • + scripts/maintenance/backfill-redline-locations.ts
  • + scripts/maintenance/backfill-redline-slugs.ts
  • + scripts/maintenance/backfill-scoring-systems.ts
  • + src/app/event-producers/page.tsx
  • + src/components/competitions/producer-badge.tsx
  • + src/components/competitions/producer-events-map.tsx
Modified (15):
  • ~ scripts/import/import-redline-open.ts
  • ~ scripts/maintenance/backfill-redline-locations.ts
  • ~ scripts/maintenance/backfill-redline-slugs.ts
  • ~ scripts/maintenance/backfill-scoring-systems.ts
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/app/event-producers/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/competitions/open-competition-scores.tsx
  • ~ src/components/competitions/producer-badge.tsx
  • ~ src/components/competitions/producer-events-map.tsx
  • ~ src/components/teams/team-ps-chart.tsx
  • ~ src/lib/gating-context.ts
  • ~ src/lib/us-city-coords.ts
  • ~ src/types/charts.ts

Version 0.2.460

Event Producer page: show full clickable events list

June 24, 2026 at 2:51 AM GMT+0
a7106ba8
🔄Changed
  • Event Producer page: show full clickable events list
  • Replace the 8-item card grid (no way to reach the rest) with a complete, clearly-clickable list of all the producer's events: date, location, result count, chevron.

Files Changed

Modified (1):
  • ~ src/app/event-producers/[slug]/page.tsx

Version 0.2.459

Add Event Producers + confidential data gating (Redline / The Open)

June 24, 2026 at 2:30 AM GMT+0
Added
  • Event Producer pages at /event-producers/[slug] with recent events, a competing-gyms map, and season stats.
  • Imported the Redline / The Open Championship Series 2025-26 results (32 events, 4,343 results) as the first Event Producer.
  • Dedicated Open Championship Series scorecard: Redline competition pages render Score / % of Max / Placement grouped by division, instead of the Varsity/Worlds difficulty-execution breakdown.
🔒Security
  • Confidential event-producer data is gated: hidden from public search, rankings, sitemap, and all pages via a Prisma read-hook chokepoint plus explicit filters on raw SQL. Visible only to admins and granted producer accounts.

Files Changed

Modified (8):
  • ~ prisma/schema.prisma
  • ~ src/lib/prisma.ts
  • ~ src/lib/gating-context.ts
  • ~ src/app/event-producers/[slug]/page.tsx
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/components/competitions/open-competition-scores.tsx
  • ~ scripts/import/import-redline-open.ts
  • ~ scripts/maintenance/purge-redline.ts

Version 0.2.458

SCORES: scorecards now show every captured breakdown column

June 14, 2026 at 5:00 AM GMT+0
🐛Fixed
  • SCORES: Scorecard tables/cards no longer show blank ("-") cells for categories whose values are actually in the database. The breakdown view previously trusted the scrape JSON blob alone, which on some events (e.g. Spirit Sports, The American) was a partial capture missing standing/running tumbling — even though the real tumbling scores were stored in the score columns the whole time. The view now merges the authoritative score columns with the scrape blob, surfacing ~9,000+ previously-hidden standing/running tumbling values across the database. Affects the team performance table, the competition/division scorecards.

Version 0.2.457

MOBILE: modals no longer overflow horizontally on phones

June 14, 2026 at 5:00 AM GMT+0
🐛Fixed
  • MOBILE: Dialogs no longer overflow off the right edge of the screen. Native date pickers and other form fields now shrink to fit narrow viewports (added min-width:0 to the shared Input, Textarea, and Select components), fixing the Edit/Add Experience modal where the Team field, date pickers, and action buttons were clipped. The fix applies app-wide, so every modal benefits.
  • PROFILE: The Edit Experience footer buttons (Delete / Cancel / Save Changes) now wrap gracefully instead of being cut off on small screens.

Version 0.2.456

ANALYZE: Scorecards moved to the bottom with a Cards/Table toggle

June 14, 2026 at 5:00 AM GMT+0
🔄Changed
  • ANALYZE: On a team's Analyze → Scoresheet tab, the scorecards now sit at the bottom of the tab (below the competitive analysis) and use the same Cards/Table toggle as the public team page — including the sortable Performances table with grouped Building/Tumbling/Performance breakdown columns and scoresheet PDF links.

Version 0.2.455

HEADER: profile picture now shows in the top-bar avatar

June 14, 2026 at 5:00 AM GMT+0
🐛Fixed
  • HEADER: The top-bar avatar now falls back to the account avatar when the active profile has no image set, so it shows your profile picture instead of an initial letter — matching the behavior already used elsewhere in the app. Backfilled affected legacy profiles.

Version 0.2.454

ANALYZE: Scoresheet tab now shows full team scorecards

June 14, 2026 at 5:00 AM GMT+0
Added
  • ANALYZE: The Scoresheet tab on a team's Analyze page now shows every routine's full scorecard for the selected season — placement, event/routine score, deductions, and the per-category score breakdown — the same scorecards available on the public team page. The existing competitive analysis remains below them.

Version 0.2.453

PROFILE: dialogs get a mobile side gutter; experience date fields no longer overflow

June 13, 2026 at 5:00 AM GMT+0
🐛Fixed
  • MOBILE: Dialogs no longer sit edge-to-edge on phones — every modal now keeps a 16px gutter on each side (shared DialogContent), while desktop widths are unchanged.
  • PROFILE: The Start/End Date fields in Add/Edit Experience no longer overflow their column on iOS Safari (native date inputs can now shrink to fit).

Version 0.2.452

PROFILE: experience role options — rename Team Parent to Team Rep, add Parent

June 13, 2026 at 5:00 AM GMT+0
🔄Changed
  • PROFILE: The "Team Parent" role option in Add/Edit Experience is now "Team Rep". Existing experience entries were migrated to the new label.
Added
  • PROFILE: Added "Parent" as a selectable role in Add/Edit Experience.

Version 0.2.451

SCORES: header-driven PDF parser fixes mis-mapped scorecard columns

June 11, 2026 at 5:00 AM GMT+0
b3edae14
🐛Fixed
  • SCORES: Scoresheet PDF parsing now reads the printed column headers instead of guessing the layout from the value count — sheets with unusual column subsets (e.g. toss-less L1 divisions) no longer land values in the wrong scorecard columns.
  • SCORES: Repaired 1,241 scorecard cells that the old positional parser had mis-mapped (512 corrected to the sheet's true value, 723 phantom values cleared, 6 gaps filled), concentrated in L1 divisions at The D2 Summit, The Youth Summit, and CHEERSPORT.
  • SCORES: Breakdown gap-fill recovered a further 3,528 scorecard values (3,339 from stored raw score data via a full-season sweep, 189 from stored PDFs re-parsed with the header-driven parser).

Version 0.2.450

SCORES: breakdown gap-fill toolkit + import pipeline no longer drops scorecard columns

June 10, 2026 at 5:00 AM GMT+0
🐛Fixed
  • SCORES: Re-importing an event can no longer wipe previously captured scorecard breakdown columns — a scrape that lacks breakdown data (e.g. a failed PDF merge upstream) now leaves existing values and rawScores.full_breakdown intact instead of nulling them.
  • SCORES: Live re-imports of unchanged divisions now still capture the division's scoresheet PDF — previously a division whose API scores never changed could permanently miss its PDF (and all execution/difficulty columns) if the scraper-side merge failed once.
  • SCORES: Scoresheet PDF merge now re-runs for already-stored PDFs whose first merge failed, and failed merges in the Python scraper are retried once and surfaced as a per-division status instead of being silently swallowed.
  • SCORES: Performance.hasPdfScores now means 'a scoresheet PDF exists for the division' and pdfParsed means 'breakdown data was captured' — the flags were previously both set from API breakdown presence and never reflected PDF state.
Added
  • SCORES: DivisionScoreStatus tracking table records per-(competition, division, round) breakdown completeness, merge failures, and fill sources — gaps are now observable instead of requiring ad-hoc audits.
  • SCORES: score-gap-fill-loop maintenance script fills missing breakdown columns from rawScores JSON, stored scrape payloads, and stored scoresheet PDFs (null-only writes with per-field validation).
  • SCORES: rescrape-gap-competitions maintenance script re-scrapes competitions with missing breakdowns without firing user notifications.
  • SCORES: PDF harvest backfill now covers all season competitions (the old hasPdfScores gate excluded exactly the gapped divisions), recovers event ids from ScrapeJob rows, and preserves unmatched-division PDFs in storage before Varsity deletes them.

Files Changed

Modified (10):
  • ~ src/lib/import/index.ts
  • ~ src/lib/import/pdf-breakdown-sync.ts
  • ~ src/lib/import/score-mapper.ts
  • ~ src/lib/import/types.ts
  • ~ python-scraper/scraper/varsity_api_scraper.py
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/score-gap-fill-loop.ts
  • ~ scripts/maintenance/rescrape-gap-competitions.ts
  • ~ scripts/maintenance/backfill-scoresheet-pdfs.ts
  • ~ scripts/maintenance/rebuild-breakdowns-from-scoresheet-pdfs.ts

Version 0.2.449

BILLING: payment-failure grace period + iOS subscription safety

June 10, 2026 at 5:00 AM GMT+0
🔄Changed
  • BILLING: A single failed payment no longer instantly removes access. Subscribers keep their tier through Stripe's retry window (PAST_DUE) and only drop to Free when the subscription actually cancels. Restored access for customers already affected.
🐛Fixed
  • BILLING (iOS): Unknown RevenueCat webhook event types no longer force a subscription to 'active' — unhandled events are now a no-op.
  • BILLING (iOS): Added an ownership guard so a RevenueCat event can't modify a subscription belonging to a different account.

Files Changed

Modified (3):
  • ~ src/lib/subscription-resolver.ts
  • ~ src/lib/apple-iap-config.ts
  • ~ src/app/api/webhooks/revenuecat/route.ts

Version 0.2.448

BILLING: fix accounts that couldn't log in after checkout + subscription robustness

June 10, 2026 at 5:00 AM GMT+0
🐛Fixed
  • BILLING: Accounts created via checkout while logged out had no password or username and could not be logged into. They are now fully provisioned (username, profile) and sent a 'set your password' email; affected existing users were remediated.
  • BILLING: Subscriptions on a legacy/renamed Stripe price id were silently dropped (leaving a paying customer with no tier); tier is now resolved from the price amount as a fallback.
  • BILLING: Cancel/pause/resume could fail to find the account when the session email had mixed casing (now normalized).
🔄Changed
  • BILLING: Unknown Stripe subscription statuses now fail closed (no access) instead of defaulting to active.

Files Changed

Modified (7):
  • ~ src/lib/account-claim.ts
  • ~ src/lib/price-tier.ts
  • ~ src/lib/stripe.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/api/stripe/cancel/route.ts
  • ~ src/app/api/stripe/pause/route.ts
  • ~ src/app/api/stripe/resume/route.ts

Version 0.2.447

Fix Supabase egress blowout: cache reference-data loaders

June 7, 2026 at 11:15 PM GMT+0
b7e47fb5
🐛Fixed
  • Fix Supabase egress blowout: cache reference-data loaders
  • Public pages were re-loading entire reference tables on every render. teams/[id] pulled all ~8,400 active divisions per view (783k calls, 6.58 billion rows in pg_stat_statements) and the team list pages loaded every active team just to derive the distinct list of gym states. With crawler traffic this drove Supabase egress to 288 GB, past the 275 GB quota.
  • Route active-divisions, active-disciplines, gym-name, gym-state lists and division filter facets through a cached reference-data module (Next Data Cache, 1h revalidate) so each payload leaves Supabase about once an hour instead of once per request.
  • Wire teams/[id], /teams, /[username]/teams and the smart-group builder to the cached helpers; the builder and list filters now use cached facets instead of whole-table scans.
  • Add scripts/debug/egress-diagnostics.ts for future read-only egress triage.

Files Changed

Created (2):
  • + scripts/debug/egress-diagnostics.ts
  • + src/lib/reference-data.ts
Modified (6):
  • ~ scripts/debug/egress-diagnostics.ts
  • ~ src/app/[username]/teams/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/app/teams/page.tsx
  • ~ src/lib/reference-data.ts
  • ~ src/lib/smart-groups.ts

Version 0.2.446

Surface first-month-free promo framing for free and new subscribers

June 6, 2026 at 7:52 PM GMT+0
b5858c3f
Added
  • Surface first-month-free promo framing for free and new subscribers
  • A 100% off, one-month promo (PROTRIAL) on a monthly Pro signup now shows the same first-N-days-free, then renews at the full rate framing as a trial, so free and brand-new users see the taste-then-renew offer clearly instead of a misleading $0/month button.
  • The card is still collected at checkout and the subscription renews at full price after the free month.

Files Changed

Modified (1):
  • ~ src/app/subscribe/subscribe-page-client.tsx

Version 0.2.445

Add promo codes to in-app upgrades + PROTRIAL (first month of Pro free)

June 6, 2026 at 4:49 PM GMT+0
f53cd29c
Added
  • Add promo codes to in-app upgrades + PROTRIAL (first month of Pro free)
  • Existing subscribers can now apply a promo code when upgrading in-app; change-plan validates it (tier, usability, one-per-user) and attaches the matching Stripe coupon.
  • Promo upgrades switch immediately with no proration charge today and let the coupon discount the next full invoice, restricted to monthly billing so a free month cannot zero a whole year.
  • PROTRIAL gives an Elite member their first month of Pro free via /subscribe?plan=pro&promo=PROTRIAL; seed it with scripts/maintenance/create-protrial-promo.ts.
  • In-app upgrade redemptions are recorded directly since no checkout webhook fires; shared coupon-creation and redemption helpers keep checkout and upgrade paths in sync.
  • Subscribe page also shows contextual upgrade messaging based on which feature paywall the user came from.

Files Changed

Created (2):
  • + scripts/maintenance/create-protrial-promo.ts
  • + src/lib/stripe-coupons.ts
Modified (7):
  • ~ scripts/health/check-promo-stripe-mapping.ts
  • ~ scripts/maintenance/create-protrial-promo.ts
  • ~ src/app/api/stripe/change-plan/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/lib/promo-resolver.ts
  • ~ src/lib/stripe-coupons.ts

Version 0.2.444

Update tier seed users to FREE/ELITE/PRO and preserve passwords

June 6, 2026 at 4:49 PM GMT+0
797a5740
🔄Changed
  • Update tier seed users to FREE/ELITE/PRO and preserve passwords
  • Canonical test accounts now map to the real FREE/ELITE/PRO tiers plus admin.
  • Seed no longer resets passwords on update, preserving existing admin/elite logins.

Files Changed

Modified (1):
  • ~ scripts/setup/create-tier-users.ts

Version 0.2.443

Fix ghost sessions + land onboarding on /home

June 6, 2026 at 4:49 PM GMT+0
3c84f954
🐛Fixed
  • Fix ghost sessions + land onboarding on /home
  • Throw from the session callback when a JWT's backing User row is gone so NextAuth clears the cookie instead of looping a phantom identity at onboarding.
  • Thrown outside the try, so a transient DB error never logs out a valid user.
  • Route post-onboarding redirects to /home instead of the legacy /feed.

Files Changed

Modified (3):
  • ~ src/app/onboarding/profile/page.tsx
  • ~ src/components/onboarding/username-onboarding-form.tsx
  • ~ src/lib/auth.ts

Version 0.2.442

@ Affiliate generator: config-driven company fields + Alondra Flores docs

June 5, 2026 at 9:12 PM GMT+0
7c086d68
🔄Changed
  • @ Affiliate generator: config-driven company fields + Alondra Flores docs
  • Affiliate generator: config-driven company fields + Alondra Flores docs
  • Convert every previously hand-edited legal field in the affiliate
  • agreement into config values, with company-wide constants merged from a
  • new company-defaults.json so they are set once and inherited by every
  • partner.

Version 0.2.441

@ Pricing accuracy + in-app plan upgrades/downgrades

June 5, 2026 at 8:05 PM GMT+0
47f33c95
🔄Changed
  • @ Pricing accuracy + in-app plan upgrades/downgrades
  • Pricing accuracy + in-app plan upgrades/downgrades
  • Tier-gate accuracy:
  • Division detail pages were marketed as Elite but gate on
  • hasCompetitorIntelligence (Pro-only). Moved to Pro; Elite keeps
  • benchmarks + percentile rankings. /pricing comparison row now derives

Files Changed

Created (3):
  • + scripts/maintenance/cleanup-plan-change-test-data.ts
  • + scripts/maintenance/test-plan-change.ts
  • + src/app/api/stripe/change-plan/route.ts
Modified (6):
  • ~ scripts/maintenance/cleanup-plan-change-test-data.ts
  • ~ scripts/maintenance/test-plan-change.ts
  • ~ src/app/api/stripe/change-plan/route.ts
  • ~ src/app/pricing/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/lib/pricing-plans.ts

Version 0.2.440

In-app plan upgrades/downgrades (no bounce to Stripe portal)

June 5, 2026 at 5:00 AM GMT+0
96fccbed
Added
  • Existing subscribers can now change plans in-app instead of being sent
  • to the hosted Stripe portal (which didn't have plan-switching enabled).
  • New POST /api/stripe/change-plan: upgrades switch immediately with
  • proration and charge the difference now (payment_behavior
  • error_if_incomplete, so access is never granted on a declined card);
  • downgrades are scheduled for the end of the paid period via a Stripe
  • Subscription Schedule, so the member keeps what they paid for and gets
  • no prorated credit.
  • On /subscribe, the 'Upgrade to Pro' / 'Switch to Elite' button opens a
  • confirmation dialog explaining the charge/timing, then applies the change
  • and refreshes the session so gated features unlock without a re-login.
  • A 'Manage billing or cancel instead' link still routes to the Stripe
  • portal for payment-method and cancellation.
  • Apple/iOS subscriptions are detected and the user is told to manage them
  • in the app store rather than failing silently.

Files Changed

Modified (2):
  • ~ src/app/api/stripe/change-plan/route.ts
  • ~ src/app/subscribe/subscribe-page-client.tsx

Version 0.2.437

ANALYZE: fix mobile tab/filter layout on gym + single-team (F22)

June 2, 2026 at 2:59 AM GMT+0
373abffb
🔄Changed
  • ANALYZE: fix mobile tab/filter layout on gym + single-team (F22)
  • On phones the 5-tab TabsList (fixed h-10, grid-cols-2) wrapped to 3 rows and
  • overflowed its fixed height, colliding with the content heading below it. And
  • the gym dashboard's season/level/age selects overflowed the right edge.
  • TabsList -> grid-cols-3 sm:grid-cols-5 with h-auto + gap, so tabs wrap to a
  • clean 2-row block on mobile and stay a single row on desktop (no overlap).

Files Changed

Modified (2):
  • ~ src/components/gym-analysis/gym-dashboard.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx

Version 0.2.436

ANALYZE: mobile group-save parity, density drill-down, mobile header

June 2, 2026 at 2:55 AM GMT+0
df02343e
🔄Changed
  • ANALYZE: mobile group-save parity, density drill-down, mobile header
  • Value-focused pass over the previously-deferred polish items:
  • Mobile save-as-group (parity): the "Select Teams" sheet now has a
  • "Save as group" button next to "Deselect all", so phone users can turn an
  • ad-hoc selection into a group. Previously this only existed on desktop.
  • Density map drill-down (F20): expanding a metro row links each gym to its

Files Changed

Modified (4):
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/components/density/density-page-client.tsx
  • ~ src/components/density/metro-rankings.tsx
  • ~ src/components/my-teams/mobile-context-bar.tsx

Version 0.2.435

ANALYZE: SYS-1 — canonicalize single-entity surfaces

June 2, 2026 at 12:39 AM GMT+0
3b4123fb
🔄Changed
  • ANALYZE: SYS-1 — canonicalize single-entity surfaces
  • Every team / whole-gym entry point now lands on its one canonical standalone
  • route instead of the duplicate ?mode= tab view:
  • team card -> /analyze/team/[slug] (gym + group cards already did this)
  • hub "Deep analysis" links (single team, edge, pressure) -> standalone team
  • old ?mode=team&team=X and ?mode=gym&gym=X deep links 301 to the standalone

Files Changed

Modified (3):
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/components/analyze/analyze-hub.tsx
  • ~ src/components/analyze/team-card.tsx

Version 0.2.434

ANALYZE: SYS-3 — URL-persisted, shareable analysis state

June 2, 2026 at 12:35 AM GMT+0
329a27ac
🔄Changed
  • ANALYZE: SYS-3 — URL-persisted, shareable analysis state
  • Season, score metric, event window, smoothing, the Worlds toggle, and the
  • density map's season/radius/layer now live in the URL, so an analysis is
  • shareable and survives refresh and back/forward.
  • New hook src/lib/use-url-state.ts writes via the native History API
  • (window.history.replaceState) rather than router.replace, so updating a

Files Changed

Created (1):
  • + src/lib/use-url-state.ts
Modified (5):
  • ~ src/components/density/density-page-client.tsx
  • ~ src/components/my-teams/group-detail-client.tsx
  • ~ src/components/my-teams/my-teams-client.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/lib/use-url-state.ts

Version 0.2.433

ANALYZE: unify group selection/creation, signpost gating, fix UX inconsistencies

June 2, 2026 at 12:22 AM GMT+0
d7b28831
🔄Changed
  • ANALYZE: unify group selection/creation, signpost gating, fix UX inconsistencies
  • Implements the high-confidence findings from the /analyze UX audit
  • (docs/audits/analyze-ux-audit.md):
  • SYS-2 (core ask: ad-hoc selection -> save as group):
  • "Save as group" now lives in the analysis selection bar and saves the
  • currently-checked teams, so any ad-hoc selection becomes a group

Files Changed

Created (2):
  • + src/lib/analyze-trend.ts
  • + src/lib/smart-group-format.ts
Modified (14):
  • ~ src/app/[username]/analyze/group/[id]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/team/[slug]/page.tsx
  • ~ src/app/api/follow-groups/[id]/route.ts
  • ~ src/components/analyze/group-card.tsx
  • ~ src/components/analyze/gym-card.tsx
  • ~ src/components/analyze/headlines.tsx
  • ~ src/components/analyze/smart-group-builder.tsx
  • ~ src/components/analyze/team-card.tsx
  • ~ src/components/my-teams/group-detail-client.tsx
  • ~ src/components/my-teams/my-teams-client.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/lib/analyze-trend.ts
  • ~ src/lib/smart-group-format.ts

Version 0.2.432

COMPETITION: Divisions tab — expand Disciplines by default (Levels and Age Groups stay collapsed)

May 29, 2026 at 10:44 PM GMT+0
68d6c365
🔄Changed
  • COMPETITION: Divisions tab — expand Disciplines by default (Levels and Age Groups stay collapsed)
  • So users land on a useful overview instead of two collapsed D1/D2 headers.

Files Changed

Modified (1):
  • ~ src/components/competitions/divisions-tab.tsx

Version 0.2.431

COMPETITION: My-Follows team rows link to division; Divisions tab regrouped as Discipline > Level > Age

May 29, 2026 at 10:28 PM GMT+0
034fa54f
🔄Changed
  • COMPETITION: My-Follows team rows link to division; Divisions tab regrouped as Discipline > Level > Age
  • Top "My Teams & Gyms" card now treats the team row as one click target
  • that opens that team's division at this competition (was: team profile).
  • Bottom Divisions tab replaces the flat Level grouping with three nested
  • collapsible layers (Discipline > Level > Age Group), all collapsed by
  • default. Disciplines sort by sortOrder; ages use canonical cheer order.

Files Changed

Modified (5):
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/components/competitions/competition-tabs.tsx
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/components/competitions/my-follows-at-competition.tsx
  • ~ src/lib/discipline-utils.ts

Version 0.2.430

COMPETITION: My-Follows team rows link to division; Divisions tab regrouped as Discipline > Level > Age

May 29, 2026 at 5:00 AM GMT+0
5d25198d
🔄Changed
  • Top 'My Teams & Gyms' card: clicking a team row now opens that team's division at this competition (was: team profile).
  • Bottom Divisions tab: replaced flat Level grouping with three nested collapsible layers (Discipline > Level > Age Group). All layers collapsed by default for easier navigation on large events.
  • Disciplines sort by Discipline.sortOrder; ages sort by canonical cheer order (Tiny, Mini, Youth, Junior, Senior, Open, Adult, Other).

Files Changed

Modified (5):
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/components/competitions/my-follows-at-competition.tsx
  • ~ src/components/competitions/competition-tabs.tsx
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/lib/discipline-utils.ts

Version 0.2.429

ADMIN: split Paid vs Granted in analytics; Paid Users / Paid Mix exclude comps

May 28, 2026 at 4:23 PM GMT+0
1d394c20
🔄Changed
  • ADMIN: split Paid vs Granted in analytics; Paid Users / Paid Mix exclude comps
  • Paid now counts only users with an ACTIVE/TRIALING Subscription row.
  • New 'Granted Premium' card counts paid-tier users without a sub
  • (admin-comped). Paid Mix description clarifies real payers vs free.

Files Changed

Modified (3):
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/app/api/admin/analytics/users/route.ts
  • ~ src/types/analytics.ts

Version 0.2.428

SKILL: add affiliate-contract generator + Hailey Smith contracts

May 28, 2026 at 4:18 PM GMT+0
8355d3ff
🔄Changed
  • SKILL: add affiliate-contract generator + Hailey Smith contracts
  • Templates the locked legal boilerplate (commissions, tail, arbitration,
  • ROFR) so future partner contracts can't drift word-by-word. generate.py
  • script + .md/.html templates + intake flow with optional web research on
  • provided partner links. Supports affiliate-only (4 files) or
  • affiliate-and-curriculum (6 files with per-student pricing math).

Version 0.2.427

ADMIN: add MRR / ARR / New MRR / Active Subs to analytics dashboard

May 28, 2026 at 4:12 PM GMT+0
c5fe4644
Added
  • ADMIN: add MRR / ARR / New MRR / Active Subs to analytics dashboard
  • Sums active+trialing Subscription rows, normalizing annual plans to
  • monthly via the Stripe price-ID lookup (with period-length fallback for
  • IAP). New MRR is filtered to subs created in the selected timeframe.

Files Changed

Created (1):
  • + src/lib/mrr.ts
Modified (2):
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/lib/mrr.ts

Version 0.2.426

CHANGELOG: bump for v0.2.425 (rebase reconciliation)

May 28, 2026 at 2:53 PM GMT+0
f8bc3f63
🔄Changed
  • CHANGELOG: bump for v0.2.425 (rebase reconciliation)

Version 0.2.425

ADMIN: add Source column to user mgmt (Paid vs Granted vs Free)

May 28, 2026 at 2:53 PM GMT+0
3533703c
🔄Changed
  • ADMIN: add Source column to user mgmt (Paid vs Granted vs Free)
  • Distinguishes real paying Stripe/Apple/Google subs from admin-comped
  • premium access. Adds Source column + filter; Paid badge shows platform.

Files Changed

Modified (2):
  • ~ src/app/admin/users/page.tsx
  • ~ src/app/admin/users/users-filter.tsx

Version 0.2.424

ADMIN: add Source column to user mgmt (Paid vs Granted vs Free)

May 28, 2026 at 2:53 PM GMT+0
a4dda85a
🔄Changed
  • ADMIN: add Source column to user mgmt (Paid vs Granted vs Free)
  • Distinguishes real paying Stripe/Apple/Google subs from admin-comped
  • premium access. Adds Source column + filter; Paid badge shows platform.

Files Changed

Modified (2):
  • ~ src/app/admin/users/page.tsx
  • ~ src/app/admin/users/users-filter.tsx

Version 0.2.423

CHANGELOG: backfill v0.2.422 entry for KlaviyoOnsite hotfix

May 27, 2026 at 11:29 PM GMT+0
61a21263
🔄Changed
  • CHANGELOG: backfill v0.2.422 entry for KlaviyoOnsite hotfix
  • The auto-changelog post-commit hook ran during the prior rebase but the
  • rebase swallowed the bump commit. This commits the staged version bump +
  • changelog entry that the hook produced, so the changelog matches reality.

Version 0.2.422

HOTFIX: move KlaviyoOnsite inside Providers so useSession has its provider

May 27, 2026 at 3:16 PM GMT+0
8584720d
🔄Changed
  • HOTFIX: move KlaviyoOnsite inside Providers so useSession has its provider
  • Previous commit mounted <KlaviyoOnsite /> in <head>, above the <Providers>
  • wrapper. The KlaviyoIdentify child calls useSession(), which throws during
  • SSR when there's no SessionProvider ancestor. Result: every page hit prod
  • with TypeError "Cannot destructure property 'data' of useSession() as it is
  • undefined" and the homepage was 500ing.

Files Changed

Modified (1):
  • ~ src/app/layout.tsx

Version 0.2.421

HOTFIX: move KlaviyoOnsite inside Providers so useSession has its provider

May 27, 2026 at 3:16 PM GMT+0
80e10275
🔄Changed
  • HOTFIX: move KlaviyoOnsite inside Providers so useSession has its provider
  • Previous commit mounted <KlaviyoOnsite /> in <head>, above the <Providers>
  • wrapper. The KlaviyoIdentify child calls useSession(), which throws during
  • SSR when there's no SessionProvider ancestor. Result: every page hit prod
  • with TypeError "Cannot destructure property 'data' of useSession() as it is
  • undefined" and the homepage was 500ing.

Files Changed

Modified (1):
  • ~ src/app/layout.tsx

Version 0.2.420

KLAVIYO: install client-side onsite snippet + identify-on-login

May 27, 2026 at 3:05 PM GMT+0
46e4d2e8
🔄Changed
  • KLAVIYO: install client-side onsite snippet + identify-on-login
  • The server-side Klaviyo integration (Profiles + Events APIs in src/lib/klaviyo.ts)
  • covers signup/subscribe/conversion events. It does NOT cover anything that
  • needs a browser session:
  • "Active on Site" metric (Welcome Flow dashboard showed 0% for every email)
  • Browse-abandonment flows (pricing page, etc.)

Files Changed

Created (1):
  • + src/components/analytics/klaviyo-onsite.tsx
Modified (2):
  • ~ src/app/layout.tsx
  • ~ src/components/analytics/klaviyo-onsite.tsx

Version 0.2.419

KLAVIYO: install client-side onsite snippet + identify-on-login

May 27, 2026 at 2:41 PM GMT+0
3d367bc
🔄Changed
  • Adds the client-side klaviyo.js snippet (loaded via next/script, strategy=afterInteractive) plus a useSession-driven identify call that pushes ['identify', { $email, $first_name, $last_name, username }] to window._learnq once the user is authenticated.
  • Server-side integration in src/lib/klaviyo.ts is unchanged. This adds the browser piece that was missing: 'Active on Site' metric (Welcome Flow dashboard showed 0% for every email because of this), browse-abandonment flows, onsite signup forms, and anonymous-to-identified profile stitching after login.
  • New env var NEXT_PUBLIC_KLAVIYO_COMPANY_ID (=SYKEPR). Set in Vercel Production + Development; component renders nothing when unset.
  • Bonus: drops 6 Klaviyo-paste-ready welcome email HTMLs under email/klaviyo-ready/ with relative assets/ paths rewritten to absolute https://fullout.energy/email/ URLs.

Files Changed

Created (7):
  • + src/components/analytics/klaviyo-onsite.tsx
  • + email/klaviyo-ready/welcome-1-welcome-promo.html
  • + email/klaviyo-ready/welcome-2-find-team.html
  • + email/klaviyo-ready/welcome-3-plan-day.html
  • + email/klaviyo-ready/welcome-4-profile.html
  • + email/klaviyo-ready/welcome-4-refer-variant.html
  • + email/klaviyo-ready/welcome-5-free-months.html
Modified (2):
  • ~ src/app/layout.tsx
  • ~ .env.example

Version 0.2.417

FIX: harden Klaviyo subscribe path + add live-trace debug tooling

May 26, 2026 at 4:57 PM GMT+0
26f1cbe
🐛Fixed
  • FIX: harden Klaviyo subscribe path + add live-trace debug tooling
  • The signup -> Klaviyo flow was working correctly for recent users (verified
  • beccaihenson@gmail.com, efrazier082013@icloud.com, ashlynncadenas12062011@gmail.com
  • are all SUBSCRIBED on list UzU3v3 with the Account Created event recorded).
  • Welcome flow not firing turned out to be a Klaviyo-side issue
  • (flow-values-report returns 0 recipients in 30 days despite events landing),

Files Changed

Created (9):
  • + scripts/debug/check-klaviyo-list-membership.ts
  • + scripts/debug/check-klaviyo-recent-users.ts
  • + scripts/debug/flow-analytics.ts
  • + scripts/debug/inspect-klaviyo-flows.ts
  • + scripts/debug/inspect-welcome-flow.ts
  • + scripts/debug/probe-klaviyo-subscribe.ts
  • + scripts/debug/test-welcome-flow-trigger.ts
  • + scripts/debug/trace-klaviyo-profile.ts
  • + src/lib/__tests__/klaviyo.test.ts
Modified (11):
  • ~ scripts/debug/check-klaviyo-list-membership.ts
  • ~ scripts/debug/check-klaviyo-recent-users.ts
  • ~ scripts/debug/flow-analytics.ts
  • ~ scripts/debug/inspect-klaviyo-flows.ts
  • ~ scripts/debug/inspect-welcome-flow.ts
  • ~ scripts/debug/probe-klaviyo-subscribe.ts
  • ~ scripts/debug/test-welcome-flow-trigger.ts
  • ~ scripts/debug/trace-klaviyo-profile.ts
  • ~ src/app/api/auth/register/route.ts
  • ~ src/lib/__tests__/klaviyo.test.ts
  • ~ src/lib/klaviyo.ts

Version 0.2.416

FIX: harden Klaviyo subscribe path + add live-trace debug tooling

May 26, 2026 at 4:52 PM GMT+0
5b134f9
🐛Fixed
  • Verified the signup -> Klaviyo path is working correctly for recent users (beccaihenson@gmail.com, efrazier082013@icloud.com, ashlynncadenas12062011@gmail.com are all SUBSCRIBED on list UzU3v3 with the Account Created event recorded).
  • Welcome flow not firing is a Klaviyo-side issue (flow-values-report returns 0 recipients in 30 days despite events landing), not a code issue. Most likely sender-domain auth or flow live-mode toggle.
  • subscribeEmailToKlaviyoList no longer bails when KLAVIYO_LIST_ID is unset; consent still flips, list-add is optional.
  • Bulk-subscribe HTTP failures now return ok:false instead of console.warn + fake success. Register route logs the actual error string and status.
  • Adds custom_source: 'FullOut Signup' so opt-in provenance is recorded.
  • Does NOT send consented_at -- Klaviyo rejects it as 'Invalid consent timestamp' on bulk-create-jobs (verified against live API).
  • Adds 8 debug scripts in scripts/debug/ for tracing future Klaviyo issues, plus 5 unit tests pinning the new behavior.

Files Changed

Created (9):
  • + src/lib/__tests__/klaviyo.test.ts
  • + scripts/debug/probe-klaviyo-subscribe.ts
  • + scripts/debug/check-klaviyo-recent-users.ts
  • + scripts/debug/check-klaviyo-list-membership.ts
  • + scripts/debug/trace-klaviyo-profile.ts
  • + scripts/debug/inspect-klaviyo-flows.ts
  • + scripts/debug/inspect-welcome-flow.ts
  • + scripts/debug/flow-analytics.ts
  • + scripts/debug/test-welcome-flow-trigger.ts
Modified (2):
  • ~ src/lib/klaviyo.ts
  • ~ src/app/api/auth/register/route.ts

Version 0.2.415

FOLLOWS: surface Follow Requests in nav with pending-count badge

May 26, 2026 at 5:10 PM GMT+0
8cd71b7f
Added
  • Follow Requests now lives in the sidebar (More > Follow Requests) on desktop and the mobile drawer, with a red pending-count badge polled every 3 minutes. Previously /follow-requests was an orphan URL nobody could find without typing it.
  • Mobile bottom-nav 'Me' tab badge now combines unread notifications + pending follow requests so users see one signal for 'something to act on'.
  • New cheap count endpoint at /api/follow-requests/pending-count returns just the integer so the badge poll doesn't pull the full request list.
  • NavLeaf.badge accepts 'notifications' | 'follow-requests' so future surfaces can plug in their own count source; the literal `true` value remains as a back-compat alias for notifications.

Files Changed

Created (2):
  • + src/app/api/follow-requests/pending-count/route.ts
  • + src/hooks/use-follow-request-count.ts
Modified (5):
  • ~ src/lib/nav-config.ts
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/dashboard/nav-group-item.tsx
  • ~ src/components/navbar.tsx
  • ~ src/components/app-shell.tsx

Version 0.2.414

PRIVACY: retire ONLY_ME tier from UI, stop 404'ing locked profiles

May 26, 2026 at 4:55 PM GMT+0
ed99a715
🔄Changed
  • Locked profiles no longer return 404. ONLY_ME and PEOPLE_I_FOLLOW now both render the discovery stub (name + photo + Follow Request button) to signed-in viewers. Matches how Instagram/Twitter handle protected accounts and unlocks the social-discovery hook the followers feature was built around.
  • Privacy dialog drops the 'Only me' option and now offers three tiers: Everyone, FullOut users, Approved followers only. Existing ONLY_ME users keep their setting until they re-edit (or until the migration script runs).
  • Removed the /api/follows ONLY_ME hard-block. Locked profiles now route through the same PENDING follow-request flow as PEOPLE_I_FOLLOW, regardless of whether they're on the legacy tier.
  • Admin isPublic=false now maps to PEOPLE_I_FOLLOW (was ONLY_ME) so new admin actions stay on the new tier.
  • Added scripts/maintenance/migrate-only-me-to-people-i-follow.ts for the eventual data backfill before dropping the enum value. Dry-run by default.

Files Changed

Created (1):
  • + scripts/maintenance/migrate-only-me-to-people-i-follow.ts
Modified (5):
  • ~ src/lib/profile-visibility.ts
  • ~ src/components/profile/profile-privacy-dialog.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/app/api/follows/route.ts
  • ~ src/app/api/person/[id]/route.ts

Version 0.2.413

FIX: follow-request approval now actually grants profile access

May 26, 2026 at 4:35 PM GMT+0
f153beeb
🐛Fixed
  • Approving a follow request on /follow-requests was a no-op for visibility because canViewProfile only checked one direction (Follow{owner->viewer}). Approving on /follow-requests flips the OPPOSITE Follow{viewer->owner} row to APPROVED, so the requester remained on the stub view forever.
  • canViewProfile now accepts either direction as a grant: the owner-grants-by-following path AND the viewer-requested-then-approved path.
  • visibleProfileFilter and filterVisiblePersons honor both paths too, so search results and follower lists surface profiles you've been approved on.

Files Changed

Modified (6):
  • ~ src/lib/profile-visibility.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/[username]/followers/page.tsx
  • ~ src/app/people/[username]/following/page.tsx
  • ~ src/app/api/person/follow-list/route.ts
  • ~ src/app/api/pdf/profile/[username]/route.tsx

Version 0.2.412

FOLLOWS: clickable follower/following lists for teams, gyms, profiles

May 26, 2026 at 4:18 PM GMT+0
2bc4be80
Added
  • Follower counts on team, gym, and athlete profile pages are now clickable and route to dedicated /followers and /following pages.
  • Mutuals section pinned at the top: 'Followed by people you follow' so browsing a team's followers becomes a discovery hook for new accounts.
  • Tab nav between Followers and Following on every entity (Teams/Gyms show an empty Following state since they don't follow accounts).
  • Privacy: private Persons (visibility != EVERYONE/FULLOUT_USERS) are filtered from follower lists via the existing canViewProfile helper; locked profiles redirect /@user/followers back to the gated profile page.
  • Middleware /@username rewrite preserves subpaths so /@user/followers reaches /people/user/followers.

Files Changed

Modified (14):
  • ~ src/lib/follow-list-data.ts
  • ~ src/components/follows/follow-list-view.tsx
  • ~ src/app/teams/[id]/followers/page.tsx
  • ~ src/app/teams/[id]/following/page.tsx
  • ~ src/app/gyms/[id]/followers/page.tsx
  • ~ src/app/gyms/[id]/following/page.tsx
  • ~ src/app/people/[username]/followers/page.tsx
  • ~ src/app/people/[username]/following/page.tsx
  • ~ src/components/teams/team-stats-strip.tsx
  • ~ src/components/gyms/gym-season-kpis.tsx
  • ~ src/components/profile/simple-profile-avatar.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/middleware.ts

Version 0.2.411

DOCS: capture trigram-index lesson from /discover 504 incident

May 25, 2026 at 10:54 PM GMT+0
002d695
🔄Changed
  • DOCS: capture trigram-index lesson from /discover 504 incident
  • Adds a "Wrapping an indexed column in a function defeats the index"
  • section under Database & Query Performance, with the two rules learned
  • from incident 2026-05-25: keep the bare indexed expression in the WHERE
  • clause, and grow the index set when growing the search scope.

Version 0.2.410

PERF: fix /discover 504 by removing seq-scan-forcing REGEXP_REPLACE fallback

May 25, 2026 at 5:25 PM GMT+0
b3dcd67
🔄Changed
  • PERF: fix /discover 504 by removing seq-scan-forcing REGEXP_REPLACE fallback
  • The /discover?q=<term> page was hitting the 30s function timeout on common
  • terms like "graham" because every raw query had this fallback clause:
  • REGEXP_REPLACE(LOWER(name), '[\s.''-]', '', 'g') ILIKE '%term%'
  • The REGEXP_REPLACE wrapping makes the expression non-indexable, so Postgres
  • seq-scanned every row of Gym, Team, Person, CoachProfile, Choreographer,

Files Changed

Created (2):
  • + scripts/debug/diagnose-discover-slow-query.ts
  • + scripts/maintenance/add-discover-search-indexes.ts
Modified (3):
  • ~ scripts/debug/diagnose-discover-slow-query.ts
  • ~ scripts/maintenance/add-discover-search-indexes.ts
  • ~ src/app/discover/page.tsx

Version 0.2.409

FEEDBACK: fix stale TeamDivision label + merge mis-attributed Chicago teams

May 25, 2026 at 5:00 PM GMT+0
7fa3dcd
🔄Changed
  • FEEDBACK: fix stale TeamDivision label + merge mis-attributed Chicago teams
  • User feedback batch (2026-05-22):
  • Team profile page was preferring a sparsely-populated TeamDivision row
  • over the most recent performance, so a 2016 L3 row would label a team
  • that has competed only in L1 since 2023 as "L3". Audit found 1,788
  • teams hit by this. Now the latest performance wins; TeamDivision is

Files Changed

Created (7):
  • + scripts/debug/audit-team-division-staleness.ts
  • + scripts/debug/check-chicago-perf-overlap.ts
  • + scripts/debug/merge-chicago-teams-dry-run.ts
  • + scripts/debug/sunshine-girls-all-perfs.ts
  • + scripts/debug/verify-claim-submissions.ts
  • + scripts/maintenance/merge-chicago-misattributed-teams.ts
  • + scripts/maintenance/update-indiana-invasion-gym.ts
Modified (8):
  • ~ scripts/debug/audit-team-division-staleness.ts
  • ~ scripts/debug/check-chicago-perf-overlap.ts
  • ~ scripts/debug/merge-chicago-teams-dry-run.ts
  • ~ scripts/debug/sunshine-girls-all-perfs.ts
  • ~ scripts/debug/verify-claim-submissions.ts
  • ~ scripts/maintenance/merge-chicago-misattributed-teams.ts
  • ~ scripts/maintenance/update-indiana-invasion-gym.ts
  • ~ src/app/teams/[id]/page.tsx

Version 0.2.408

FEEDBACK: wire Send Feedback into desktop sidebar + email alert on new submissions

May 22, 2026 at 3:33 PM GMT+0
7b125ec
Added
  • FEEDBACK: wire Send Feedback into desktop sidebar + email alert on new submissions
  • Two related changes so the feedback queue actually gets used and you
  • hear about new submissions without checking the admin panel.
  • 1. Desktop sidebar Send Feedback button
  • sidebar-nav.tsx now renders a Send Feedback action just above the
  • Collapse toggle. Styled to match the muted Collapse/Logout utilities

Files Changed

Modified (3):
  • ~ src/app/api/feedback/route.ts
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/lib/admin-alerts.ts

Version 0.2.407

FIX: exclude heavy /public asset dirs from serverless function bundles

May 19, 2026 at 8:55 PM GMT+0
adfdddf
🐛Fixed
  • FIX: exclude heavy /public asset dirs from serverless function bundles
  • Vercel's file tracer was pulling public/ads/_source, public/email/halftones,
  • public/email/hero-*.png, public/images/hero, and other large static asset
  • directories into every serverless function bundle. After the 2026-05-19
  • BRAND asset additions (~56 MB of new halftone + ads source images), function
  • bundles exceeded Vercel's 250 MB serverless size limit and the deploy was

Version 0.2.406

BRAND: halftone library + minimum-font rails for social and ads

May 19, 2026 at 5:32 PM GMT+0
c97793b
🔄Changed
  • BRAND: halftone library + minimum-font rails for social and ads
  • Halftone imagery library:
  • Copied 15 halftones from public/images/scorecards/backgrounds/
  • (Group 100-114, the brand's photographic vocabulary) into two
  • creative pipelines with clean filenames:
  • public/email/halftones/halftone-01.png .. halftone-15.png

Version 0.2.405

BRAND: surface-agnostic style guide export for Claude.ai Projects

May 19, 2026 at 5:00 PM GMT+0
dbe6973
🔄Changed
  • BRAND: surface-agnostic style guide export for Claude.ai Projects
  • Adds brand/EXPORT-claude-project.md — a single self-contained markdown
  • file that bundles only the brand and style fundamentals (colors, type
  • system, voice rules, no-em-dash, no-exclamation, verb-first CTAs,
  • section-marker pattern, layout system, imagery vocabulary, promo code
  • conventions, surface-agnostic checklist) WITHOUT any newsletter-

Version 0.2.404

ANALYTICS: server-side Meta Conversions API for Lead, Purchase, Subscribe

May 19, 2026 at 4:56 PM GMT+0
e6e45b4
🔄Changed
  • ANALYTICS: server-side Meta Conversions API for Lead, Purchase, Subscribe
  • Adds src/lib/fb-capi.ts — typed CAPI helper that POSTs to Meta's
  • graph.facebook.com/v21.0/{PIXEL_ID}/events endpoint with SHA-256-hashed
  • customer identifiers per Meta's spec. No-op when META_CAPI_ACCESS_TOKEN
  • is unset so the code path is safe to ship before the token arrives.
  • Wired into:

Files Changed

Created (1):
  • + src/lib/fb-capi.ts
Modified (8):
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/home/page.tsx
  • ~ src/app/pricing/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/components/analytics/pixel-page-event.tsx
  • ~ src/lib/fb-capi.ts
  • ~ src/lib/fb-pixel.ts

Version 0.2.403

NEWSLETTERS: self-contained export for Claude.ai Projects

May 19, 2026 at 4:48 PM GMT+0
54381f0
🔄Changed
  • NEWSLETTERS: self-contained export for Claude.ai Projects
  • Adds newsletters/EXPORT-claude-project.md — a single self-contained
  • markdown file that bundles the brand fundamentals (colors, type system,
  • voice rules, no-em-dash, no-exclamation, verb-first CTAs) plus the
  • newsletter-specific workflow (subject A/B, preview text, body structure,
  • CTA conventions, promo code naming, Klaviyo template registry, send

Version 0.2.402

ADS: UTM tracking convention + per-brief campaign slugs

May 19, 2026 at 3:51 AM GMT+0
4ce0908
🔄Changed
  • ADS: UTM tracking convention + per-brief campaign slugs
  • Adds a single source-of-truth doc at ads/system/utm-conventions.md
  • that defines the UTM scheme for every Meta ad URL:
  • utm_source=meta (covers FB + IG)
  • utm_medium=cpc (paid clicks)
  • utm_campaign=<brief slug>

Version 0.2.401

BRAND: top-level brand system + Meta ads aligned to email design language

May 19, 2026 at 3:49 AM GMT+0
0402cb7
🔄Changed
  • BRAND: top-level brand system + Meta ads aligned to email design language
  • Sets up parallel design-system folders so future surfaces (newsletters,
  • ads, future TikTok/Reels copy) extend the same brand fundamentals
  • instead of reinventing tokens. Pattern matches the existing email/
  • folder: a CLAUDE.md auto-load at the root of each surface, a system/
  • subfolder with rules, briefs/ for per-campaign content, output where

Files Changed

Modified (2):
  • ~ scripts/generate-meta-ads-v2.ts
  • ~ scripts/generate-meta-ads.ts

Version 0.2.400

TOOLING: Klaviyo template font patcher + HTML clone workaround

May 19, 2026 at 3:30 AM GMT+0
adb7efc
🔄Changed
  • TOOLING: Klaviyo template font patcher + HTML clone workaround
  • Three scripts to fix the recurring problem of Gmail stripping custom
  • webfonts from DnD templates and falling back to serif:
  • patch-uxvgn8-template.ts: walks a DnD template definition, rewrites
  • fontFamily fields and inline font-family CSS to a web-safe fallback
  • stack. Saves before/after JSON for inspection. (Note: Klaviyo's

Files Changed

Created (3):
  • + scripts/maintenance/clone-uxvgn8-as-html.ts
  • + scripts/maintenance/patch-uxvgn8-html.ts
  • + scripts/maintenance/patch-uxvgn8-template.ts
Modified (3):
  • ~ scripts/maintenance/clone-uxvgn8-as-html.ts
  • ~ scripts/maintenance/patch-uxvgn8-html.ts
  • ~ scripts/maintenance/patch-uxvgn8-template.ts

Version 0.2.399

ANALYTICS: wire Meta Pixel conversion events + Stripe success URL plumbing

May 19, 2026 at 3:11 AM GMT+0
11b94e6
🔄Changed
  • ANALYTICS: wire Meta Pixel conversion events + Stripe success URL plumbing
  • Fires the standard Meta events ad campaigns optimize against:
  • Lead + CompleteRegistration signup success (before redirect to /welcome)
  • Search home-search query, fires when results return
  • ViewContent team / gym / competition / athlete detail pages
  • via new <PixelPageEvent> client component

Files Changed

Created (1):
  • + src/components/analytics/pixel-page-event.tsx
Modified (12):
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/home/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/pricing/page.tsx
  • ~ src/app/privacy/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/app/subscribe/subscribe-form.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/analytics/pixel-page-event.tsx
  • ~ src/components/home-search.tsx

Version 0.2.398

ANALYTICS: install Meta Pixel base + PageView on App Router soft-nav

May 19, 2026 at 2:40 AM GMT+0
e048ce6
🔄Changed
  • ANALYTICS: install Meta Pixel base + PageView on App Router soft-nav
  • Adds src/lib/fb-pixel.ts (typed trackPixel/trackPixelCustom helper that
  • no-ops without window.fbq or NEXT_PUBLIC_FB_PIXEL_ID) and
  • src/components/analytics/meta-pixel.tsx (base script + route-change
  • PageView listener using usePathname + useSearchParams so soft
  • navigations register beyond the initial load).

Files Changed

Created (2):
  • + src/components/analytics/meta-pixel.tsx
  • + src/lib/fb-pixel.ts
Modified (3):
  • ~ src/app/layout.tsx
  • ~ src/components/analytics/meta-pixel.tsx
  • ~ src/lib/fb-pixel.ts

Version 0.2.397

FIX: make subscribeEmailToKlaviyoList idempotent on 409

May 18, 2026 at 10:31 PM GMT+0
2e93b00
🐛Fixed
  • FIX: make subscribeEmailToKlaviyoList idempotent on 409
  • Profile-create returns 409 if a profile with that email already exists.
  • Previously the function bailed out with an error in that case, so any
  • retry or repeat signup attempt skipped the consent-flip step. Tolerating
  • 409 lets the bulk-subscribe step still run (it keys off email, not
  • profile ID), so the function is safe to call multiple times for the

Files Changed

Modified (1):
  • ~ src/lib/klaviyo.ts

Version 0.2.396

ADS: real NCA 2026 L6 Coed top 3 + gym logo support in meta ad gen

May 18, 2026 at 10:26 PM GMT+0
0dff184
🔄Changed
  • ADS: real NCA 2026 L6 Coed top 3 + gym logo support in meta ad gen
  • generate-meta-ads scripts now bake the actual NCA 2026 International
  • Open Coed Large podium (Electric / Wildcats / Double O) into the
  • scoreboard mockup, with optional gym logo files in public/ads/_source/
  • (stingrays, cheer-athletics, top-gun). Falls back to a branded
  • monogram tile so the script never breaks when a logo is missing.

Files Changed

Modified (2):
  • ~ scripts/generate-meta-ads-v2.ts
  • ~ scripts/generate-meta-ads.ts

Version 0.2.395

FIX: Klaviyo signups now flip email-marketing consent at the chokepoint

May 18, 2026 at 10:26 PM GMT+0
79cccf5
🐛Fixed
  • FIX: Klaviyo signups now flip email-marketing consent at the chokepoint
  • subscribeEmailToKlaviyoList was adding profiles via the relationships
  • endpoint, which leaves email-marketing consent at "Never subscribed".
  • Klaviyo then skipped every recipient at send time and surfaced "Email
  • Syntax Error" in campaign reports.
  • Switched to the profile-subscription-bulk-create-jobs endpoint, which

Files Changed

Created (2):
  • + scripts/maintenance/backfill-klaviyo-consent.ts
  • + scripts/maintenance/verify-font-patch.py
Modified (3):
  • ~ scripts/maintenance/backfill-klaviyo-consent.ts
  • ~ scripts/maintenance/verify-font-patch.py
  • ~ src/lib/klaviyo.ts

Version 0.2.394

FIX: stop Live tab from showing stale scores when no comp is active

May 18, 2026 at 10:25 PM GMT+0
1b379e7
🐛Fixed
  • FIX: stop Live tab from showing stale scores when no comp is active
  • Three-layer durable fix for the issue where the Live tab kept showing
  • D2 Summit 2026 results 5-7 days after the event ended.
  • 1. scoreChangedAt trigger now tolerance-aware
  • The Postgres trigger that maintains Performance.scoreChangedAt
  • previously fired on any IS DISTINCT FROM diff. PDF re-parse and

Files Changed

Created (8):
  • + scripts/debug/check-current-active-comps.ts
  • + scripts/debug/check-live-feed-d2.ts
  • + scripts/debug/diagnose-d2-trailing-bumps.ts
  • + scripts/debug/smoke-test-live-feed-gate.ts
  • + scripts/debug/verify-score-trigger-tolerance.ts
  • + scripts/debug/verify-trigger-installed.ts
  • + scripts/maintenance/backfill-d2-summit-trailing-bumps.ts
  • + src/lib/live-feed-filter.ts
Modified (11):
  • ~ scripts/debug/check-current-active-comps.ts
  • ~ scripts/debug/check-live-feed-d2.ts
  • ~ scripts/debug/diagnose-d2-trailing-bumps.ts
  • ~ scripts/debug/smoke-test-live-feed-gate.ts
  • ~ scripts/debug/verify-score-trigger-tolerance.ts
  • ~ scripts/debug/verify-trigger-installed.ts
  • ~ scripts/maintenance/backfill-d2-summit-trailing-bumps.ts
  • ~ scripts/maintenance/install-score-changed-at-triggers.ts
  • ~ src/app/api/live-scores/route.ts
  • ~ src/app/live/page.tsx
  • ~ src/lib/live-feed-filter.ts

Version 0.2.393

FIX: /profile redirect preserves querystring + Skills-launch newsletter URL

May 18, 2026 at 9:39 PM GMT+0
56a4fbc
🐛Fixed
  • FIX: /profile redirect preserves querystring + Skills-launch newsletter URL
  • The /profile route bounces logged-in users to /@<username> for their
  • own profile page, but the redirect was dropping the querystring. That
  • meant deep-links like /profile?tab=skills couldn't land users on the
  • right tab, since the redirect went to /@username (default tab).
  • Now searchParams flow through the redirect, so /profile?tab=skills

Files Changed

Modified (1):
  • ~ src/app/profile/page.tsx

Version 0.2.392

TOOLING: Klaviyo DnD template font patcher

May 18, 2026 at 9:12 PM GMT+0
301e1d7
🔄Changed
  • TOOLING: Klaviyo DnD template font patcher
  • Adds scripts/maintenance/patch-klaviyo-fonts.py — fetches each DnD
  • template, walks the JSON for every fontFamily reference (top-level
  • styles + nested block styles + inline HTML in text/table content),
  • swaps CSS fallback stacks for the bare registered family name so
  • Klaviyo's editor recognizes our custom-uploaded Bebas Neue / JetBrains

Files Changed

Created (1):
  • + scripts/maintenance/patch-klaviyo-fonts.py
Modified (1):
  • ~ scripts/maintenance/patch-klaviyo-fonts.py

Version 0.2.391

TOOLING: add transactional email smoke-test script

May 18, 2026 at 8:01 PM GMT+0
79fccae
🔄Changed
  • TOOLING: add transactional email smoke-test script
  • scripts/debug/smoke-test-emails.ts fires every Resend transactional
  • template (password reset, account deletion, feedback reply, parental
  • consent, score posted, performance soon, 3 payout types, verification,
  • email change) to joseph.rodgers+smoke-<name>@gmail.com aliases. Reuse
  • after any template edit to confirm the HTML still renders.

Files Changed

Created (1):
  • + scripts/debug/smoke-test-emails.ts
Modified (1):
  • ~ scripts/debug/smoke-test-emails.ts

Version 0.2.390

CHANGED: open athlete Skills tab to any signed-in viewer

May 18, 2026 at 7:56 PM GMT+0
4fe5312
🔄Changed
  • CHANGED: open athlete Skills tab to any signed-in viewer
  • Gate moves from paid tier to signed-in. Prep (free) accounts now see
  • the chip tree with Verified / Under-review badges. Profile-level
  • privacy still enforced upstream by getProfileAccess (locked profiles
  • still render the stub). Anonymous viewers get a sign-in CTA card with
  • corrected /login link (the prior card pointed at /signin, which is not

Files Changed

Modified (3):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/people/person-skills-manager.tsx
  • ~ src/components/people/skills-locked-card.tsx

Version 0.2.389

FIX: durable env-var cleaner + referral URL change in 3 Welcome emails

May 16, 2026 at 8:40 PM GMT+0
ab0d65a
🐛Fixed
  • FIX: durable env-var cleaner + referral URL change in 3 Welcome emails
  • Two changes batched:
  • 1. New src/lib/env.ts with cleanEnv(key) — single chokepoint that strips
  • both real trailing whitespace AND literal "\n"/"\r" sequences left
  • behind by shell-quoting in .env files. Adopted in stripe.ts (replaces
  • the local trim helper from the 2026-05-15 fix), klaviyo.ts (read

Files Changed

Created (2):
  • + scripts/debug/patch-klaviyo-templates.ts
  • + src/lib/env.ts
Modified (5):
  • ~ scripts/debug/patch-klaviyo-templates.ts
  • ~ src/lib/env.ts
  • ~ src/lib/klaviyo.ts
  • ~ src/lib/resend.ts
  • ~ src/lib/stripe.ts

Version 0.2.388

EMAIL: Roll out FullOut email design system across all customer touchpoints

May 16, 2026 at 5:54 PM GMT+0
491b24b
🔄Changed
  • EMAIL: Roll out FullOut email design system across all customer touchpoints
  • Migrates every customer-facing email to the dark-locked design system
  • the user dropped into email/ — Bebas Neue + JetBrains Mono, #000000 outer
  • / #0E1116 inner, pink #EE2B8C accent, [ section markers ] in mono caps,
  • table-based layout with VML fallbacks. Replaces the generic pink/purple
  • gradient + table aesthetic that read like generic SaaS welcome.

Files Changed

Created (1):
  • + src/lib/emails/password-reset-email.ts
Modified (8):
  • ~ src/app/api/admin/users/[id]/route.ts
  • ~ src/app/api/auth/forgot-password/route.ts
  • ~ src/app/api/user/delete/route.ts
  • ~ src/lib/email-verification.ts
  • ~ src/lib/email.ts
  • ~ src/lib/emails/feedback-reply-email.ts
  • ~ src/lib/emails/password-reset-email.ts
  • ~ src/lib/parent-consent.ts

Version 0.2.387

ADMIN: Daily Active Users chart + paginated Recent Users

May 16, 2026 at 1:09 PM GMT+0
47d3b7b
🔄Changed
  • ADMIN: Daily Active Users chart + paginated Recent Users
  • Adds a Daily Active Users chart to /admin/analytics that mirrors Daily
  • Signups (same time period selector + compare-with-previous toggle).
  • Backed by new UserDailyActivity table — one row per user per UTC day —
  • upserted from the JWT callback in src/lib/auth.ts, throttled to a single
  • write per user per day via token.lastDauDate. No historical backfill;

Files Changed

Created (1):
  • + src/components/admin/analytics/daily-active-users-chart.tsx
Modified (7):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/app/api/admin/analytics/users/route.ts
  • ~ src/components/admin/analytics/daily-active-users-chart.tsx
  • ~ src/lib/auth.ts
  • ~ src/types/analytics.ts
  • ~ src/types/next-auth.d.ts

Version 0.2.385

CHANGED: open athlete Skills tab to any signed-in viewer

May 16, 2026 at 4:30 AM GMT+0
d7e295d
🔄Changed
  • Athlete profile Skills tab is now visible to any signed-in account
  • (Prep / Elite / Pro), not Elite/Pro only. Profile-level privacy is
  • still enforced — locked profiles still render the discoverability
  • stub. Anonymous viewers now see a Sign in / Create account CTA
  • card with corrected /login link (previous card linked to /signin,
  • which is not a route). The paid-tier gate moves down to viewing
  • the verification video proof itself; the chip tree, USP rubric
  • view, and Verified / Under-review badges are open to free tier.

Files Changed

Modified (3):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/people/person-skills-manager.tsx
  • ~ src/components/people/skills-locked-card.tsx

Version 0.2.384

DOCS: architecture map — single-page HTML view + agent-consumable JSON

May 16, 2026 at 3:45 AM GMT+0
051a937
🔄Changed
  • DOCS: architecture map — single-page HTML view + agent-consumable JSON
  • Generated docs/architecture.json (source of truth for future agents) and
  • docs/architecture.html (human view, single file, no deps). Captures the full
  • shape of the app: stack, services, all routes (pages + API), 79 Prisma
  • models grouped by cluster, auth and tier model, middleware responsibilities,
  • deployment topology, 5 past production incidents with durable rules,

Version 0.2.383

FIX: resolve promo code string for Klaviyo Subscription Created event

May 15, 2026 at 7:06 PM GMT+0
52d5c21
🐛Fixed
  • FIX: resolve promo code string for Klaviyo Subscription Created event
  • trackSubscriptionCreated was reading subscription.metadata.promoCode but
  • checkout-session metadata only stamps promoCodeId (the database PK), not
  • the code string. Result: every Subscription Created event landed with
  • promoCode: undefined.
  • Look up the actual code from PromoCode (or PartnerPromoCode when

Files Changed

Modified (1):
  • ~ src/app/api/stripe/webhook/route.ts

Version 0.2.382

FIX: trim Stripe env vars at the chokepoint to survive trailing whitespace

May 15, 2026 at 6:37 PM GMT+0
333b468
🐛Fixed
  • FIX: trim Stripe env vars at the chokepoint to survive trailing whitespace
  • Incident 2026-05-15: STRIPE_ELITE_MONTHLY_PRICE_ID in production had a
  • trailing newline (likely a copy/paste artifact when set via the Vercel
  • dashboard). Every Elite checkout 500'd with:
  • "No such price: 'price_1SugN1RhGgI2ppy90SdFFybj\n'"
  • Adds a single env() helper in src/lib/stripe.ts that .trim()s every read

Files Changed

Modified (1):
  • ~ src/lib/stripe.ts

Version 0.2.381

MARKETING: Klaviyo Welcome flow rebuild — Account Created + Subscription Created events

May 15, 2026 at 6:14 PM GMT+0
6a72ffb
Added
  • MARKETING: Klaviyo Welcome flow rebuild — Account Created + Subscription Created events
  • Wires the two events the new Welcome flow runs on:
  • trackAccountCreated fires from /api/auth/register so the flow can be
  • metric-triggered instead of "Added to List" (unlocks conditional splits
  • and was the root cause of the Email #2 cohort skip on the old flow).
  • trackSubscriptionCreated fires from the Stripe webhook gated on the

Files Changed

Modified (3):
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/lib/klaviyo.ts

Version 0.2.380

PERF/SEC: Supabase egress reduction — bot blocking, image CDN, sitemap trim

May 15, 2026 at 5:20 PM GMT+0
cf7d8f5
🔄Changed
  • PERF/SEC: Supabase egress reduction — bot blocking, image CDN, sitemap trim
  • Site was bleeding ~70 GB/day on Supabase egress (159/250 GB used in the
  • current billing window) driven by raw <img> tags shipping full-resolution
  • Supabase Storage URLs on every public render and a 32k-URL sitemap inviting
  • scrapers. This change moves image bytes onto Vercel's image CDN (Supabase
  • becomes a warm-cache origin), shrinks the sitemap surface, and 403s known

Files Changed

Modified (12):
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/coaches/route.ts
  • ~ src/app/api/score-maximums/[id]/route.ts
  • ~ src/app/sitemap.ts
  • ~ src/components/discover/sortable-tables.tsx
  • ~ src/components/hub/competition-card.tsx
  • ~ src/components/hub/content-block.tsx
  • ~ src/components/hub/featured-gyms.tsx
  • ~ src/components/hub/score-ticker.tsx
  • ~ src/components/ui/avatar.tsx
  • ~ src/components/ui/initials-avatar.tsx
  • ~ src/middleware.ts

Version 0.2.379

PERF/SECURITY: Supabase egress reduction — bot blocking, image CDN, sitemap trim

May 15, 2026 at 3:00 PM GMT+0
80898cc
Added
  • MIDDLEWARE: edge-level User-Agent blocklist returns 403 for 30+ known AI training and aggressive scraping crawlers (GPTBot, ClaudeBot, CCBot, PerplexityBot, Bytespider, AhrefsBot, SemrushBot, DataForSeoBot, PetalBot, scrapy/python-requests/Go-http-client signatures, etc.) before any page render or DB query. Pairs with the expanded robots.txt for polite bots.
  • ROBOTS: rewrote public/robots.txt with real sitemap URL (was placeholder), expanded blocklist (AI training + aggressive SEO + generic scrapers), Disallow /api/ + admin/dashboard/settings paths, Disallow search query strings, Crawl-delay: 10 for everyone else.
  • IMAGES: routed shadcn AvatarImage src through /_next/image so every avatar render across 30+ callsites is served via Vercel image CDN — Supabase Storage is hit once per unique resolution then cached for 30 days. AvatarFallback coordination is preserved via Radix primitive.
  • IMAGES: converted raw <img> to next/image in hub competition-card, featured-gyms, score-ticker, content-block (4 instances), discover sortable-tables, and initials-avatar. CDN-cached avif/webp variants served instead of full-res Supabase originals.
  • API: cache-control headers added to /api/choreographers, /api/coaches, /api/score-maximums/[id] list/detail GETs (public, s-maxage=120-600, stale-while-revalidate).
🔄Changed
  • SITEMAP: trimmed from ~32,000 URLs to ~5,000 — competitions filtered to last 18 months only; gym/team caps lowered to 1500/2000. Drastically reduces the URL surface crawlers can iterate, especially OG-image unfurls.
  • next.config.js: added minimumCacheTTL of 30 days for optimized images on Vercel CDN; allowlisted lh3.googleusercontent.com (Google OAuth avatars) and unavatar.io (social-card fallback) in remotePatterns.
🔒Security
  • Reduced exposure to AI-training crawlers and SEO scrapers that ignore robots.txt — blocked at the edge by middleware UA inspection, costing them a 403 response with no DB or Supabase fetch.

Files Changed

Modified (14):
  • ~ next.config.js
  • ~ public/robots.txt
  • ~ src/app/api/choreographers/route.ts
  • ~ src/app/api/coaches/route.ts
  • ~ src/app/api/score-maximums/[id]/route.ts
  • ~ src/app/sitemap.ts
  • ~ src/components/discover/sortable-tables.tsx
  • ~ src/components/hub/competition-card.tsx
  • ~ src/components/hub/content-block.tsx
  • ~ src/components/hub/featured-gyms.tsx
  • ~ src/components/hub/score-ticker.tsx
  • ~ src/components/ui/avatar.tsx
  • ~ src/components/ui/initials-avatar.tsx
  • ~ src/middleware.ts

Version 0.2.378

SKILLS: paid verification unlocks, Elite/Pro viewing gate, bundle pricing, partner attribution

May 15, 2026 at 3:39 AM GMT+0
097d146
Added
  • SKILLS: $199 flat per skill level to unlock verification submission. Athletes pick which levels they want to verify and pay one-time via Stripe Checkout (mode: payment). Self-reporting stays free; the paid gate is on creating a new SkillVerificationAttempt.
  • SKILLS: bundle pricing tuned server-side via BUNDLE_PRICING table in src/lib/skill-level-pricing.ts — 1 level $199, 2 levels $179 ea, 3+ levels $159 ea, 5+ levels $129 ea. No Stripe dashboard changes; checkout uses price_data with the computed amount.
  • SKILLS: multi-level dialog with live pricing preview (/api/skills/level-unlock/preview) — shows the bundle savings before checkout and validates promo codes inline.
  • SKILLS: multi-level display invariant — skills that appear in multiple rubric levels now render under every level on the profile, and a VERIFIED badge follows the PersonSkill so verification done once shows verified in every level bucket.
  • SKILLS: Elite/Pro viewing gate — non-paying viewers (anonymous + FREE tier) see a paywall card instead of the skills tree. Owner + admin always see their own. Drives subscription value.
  • PROMO: PromoCode + PartnerPromoCode gain productType (SUBSCRIPTION | SKILL_LEVEL_UNLOCK) and applicableSkillLevels[]. Admin promo form gets a Product selector that swaps the scoping UI between tiers and skill levels. Skill-scoped promos must cover EVERY level in the buyer's cart or are rejected with an explicit message.
  • PARTNER: per-partner toggle for skill-unlock commission — admin partner detail page gains a 'Skill Unlock Commission' card with on/off + flat $ per level. One PartnerCommission EARNED row per unlocked level (matches refund-clawback granularity). Default OFF.
  • PARTNER: partner detail page now shows a 'Skill Unlock Conversions' section listing attributed purchases (athlete, levels, net, status, date) plus aggregate revenue.
  • ADMIN: new /admin/skill-unlocks browse page — top-line stats (net revenue, levels sold, refund rate) + 100 most recent purchases with promo + partner attribution + refund state. Linked from admin home Business section.
  • ADMIN: /admin/analytics adds 'Skill Unlock Revenue' and 'Levels Sold' metric cards, windowed by the selected timeframe.
  • DB: new models SkillLevelPurchase (one row per Stripe transaction) and SkillLevelUnlock (one row per durable entitlement). Partner gains skillUnlockCommissionEnabled + skillUnlockCommissionCents. PartnerCommission gains skillLevelUnlockId. PromoCode + PartnerPromoCode gain productType + applicableSkillLevels. New enum PromoProductType. Additive migration via prisma db push.
🔄Changed
  • SKILLS: verify-skill page server-side guard — locked → redirect to profile with ?unlockNeeded=<levels> so the dialog auto-opens preseeded with the required levels.
  • SKILLS: POST /api/person/[id]/skills/[personSkillId]/verification returns 402 Payment Required when the skill's levels aren't unlocked (admin bypass). /api/verification/[attemptId]/media re-checks for defense in depth.
  • STRIPE: webhook handles metadata.type=skill_level_unlock on checkout.session.completed (creates SkillLevelPurchase + N SkillLevelUnlock rows + redemption + partner commissions). charge.refunded now also revokes skill unlocks and clawbacks partner commissions within the clawback window. V1: full-charge refunds only — partials logged.

Files Changed

Modified (24):
  • ~ prisma/schema.prisma
  • ~ src/lib/skill-level-pricing.ts
  • ~ src/lib/skill-level-unlocks.ts
  • ~ src/lib/promo-resolver.ts
  • ~ src/app/api/skills/level-unlock/checkout/route.ts
  • ~ src/app/api/skills/level-unlock/preview/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/api/person/[id]/skills/[personSkillId]/verification/route.ts
  • ~ src/app/api/verification/[attemptId]/media/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/[username]/skills/[personSkillId]/verify/page.tsx
  • ~ src/components/people/person-skills-manager.tsx
  • ~ src/components/people/unlock-levels-dialog.tsx
  • ~ src/components/people/skills-locked-card.tsx
  • ~ src/components/admin/promo-code-form.tsx
  • ~ src/components/admin/partners/skill-unlock-commission-editor.tsx
  • ~ src/app/api/admin/promo-codes/route.ts
  • ~ src/app/api/admin/promo-codes/[id]/route.ts
  • ~ src/app/admin/promo-codes/page.tsx
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/app/admin/partners/[id]/page.tsx
  • ~ src/app/api/admin/partners/[id]/route.ts
  • ~ src/app/admin/skill-unlocks/page.tsx
  • ~ src/app/admin/page.tsx

Version 0.2.376

SCORECARDS: per-column min/max filters on expanded breakdown

May 14, 2026 at 2:26 PM GMT+0
1f99cb0
🔄Changed
  • SCORECARDS: per-column min/max filters on expanded breakdown
  • Adds Excel-style numeric column filters to the gym scorecards page. When
  • the full breakdown is expanded, every score column (RS, DED, Final, and
  • each breakdown column) gets a funnel icon next to the sort arrow that
  • opens a min/max popover. Active filters tint the icon pink and feed the
  • sidebar filter badge.

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.376

SCORECARDS: per-column min/max filters on expanded breakdown

May 14, 2026 at 5:00 AM GMT+0
3f63874
Added
  • Per-column min/max value filters on the gym scorecards page (RS, DED, Final, and every breakdown column) when the full breakdown is expanded. Click the funnel icon next to a column's sort arrow to set numeric bounds; active filters tint the icon pink and count toward the sidebar filter badge.
  • ScorecardConfig now persists columnFilters so saved scorecards remember per-column numeric ranges.

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.375

ANALYZE: refactor — shared helpers, split compare route, hub perf

May 14, 2026 at 3:07 AM GMT+0
1d51fca
🔄Changed
  • ANALYZE: refactor — shared helpers, split compare route, hub perf
  • Fixes the team detail page leaking raw Prisma Decimal Score fields to the
  • client and consolidates duplicated logic (toPlainScore, season cutoff,
  • auth guard) into src/lib/analyze-helpers.ts so every analyze sub-page
  • shares one definition.
  • Splits the gym-compare branch out of the monolithic /analyze page into

Files Changed

Created (2):
  • + src/app/[username]/analyze/compare/page.tsx
  • + src/lib/analyze-helpers.ts
Modified (15):
  • ~ src/app/[username]/analyze/compare/page.tsx
  • ~ src/app/[username]/analyze/density/page.tsx
  • ~ src/app/[username]/analyze/error.tsx
  • ~ src/app/[username]/analyze/group/[id]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/[username]/analyze/team/[slug]/page.tsx
  • ~ src/components/analyze/analyze-hub.tsx
  • ~ src/components/analyze/headlines.tsx
  • ~ src/components/analyze/team-card.tsx
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/gym-analysis/gym-comparison.tsx
  • ~ src/lib/analyze-helpers.ts
  • ~ src/lib/smart-groups.ts

Version 0.2.374

ANALYZE: refactor — shared helpers, split compare route, hub perf

May 14, 2026 at 8:06 AM GMT+0
f9bf928
🐛Fixed
  • ANALYZE: team detail page was passing raw Prisma Decimal Score fields to the client; now serialized via toPlainScore.
  • ANALYZE: smart-group queries now scope to active disciplines, so dropped disciplines no longer pollute filter dimensions or membership.
  • ANALYZE: smart-group resolver no longer materializes a giant competition ID IN list; uses Performance.createdAt directly within the season window.
🔄Changed
  • ANALYZE: gym comparison moved from /analyze?mode=gym-compare to its own route /analyze/compare. Old URLs server-redirect.
  • ANALYZE: hub dashboard precomputes per-team / per-gym / per-group performance buckets in one pass, eliminating O(N*M) re-filtering across cards.
  • ANALYZE: free-tier users hitting the compare route now redirect to /analyze?upgrade=gym-compare instead of silently bouncing.
  • ANALYZE: compare-gyms picker on the hub now re-syncs when the followed-gyms list changes.
Added
  • src/lib/analyze-helpers.ts: shared toPlainScore, seasonScopeStart, and requireAnalyzeAccess (auth guard) used by every analyze sub-page.
🗑️Removed
  • ANALYZE: dead 'upcoming' headline kind (was typed but never emitted).

Files Changed

Created (2):
  • + src/lib/analyze-helpers.ts
  • + src/app/[username]/analyze/compare/page.tsx
Modified (13):
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/[username]/analyze/density/page.tsx
  • ~ src/app/[username]/analyze/error.tsx
  • ~ src/app/[username]/analyze/group/[id]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • ~ src/app/[username]/analyze/team/[slug]/page.tsx
  • ~ src/components/analyze/analyze-hub.tsx
  • ~ src/components/analyze/headlines.tsx
  • ~ src/components/analyze/team-card.tsx
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/gym-analysis/gym-comparison.tsx
  • ~ src/lib/smart-groups.ts

Version 0.2.373

DEBUG: D2 scrape inspection scripts

May 14, 2026 at 2:53 AM GMT+0
377e85a
🐛Fixed
  • DEBUG: D2 scrape inspection scripts
  • One-off Prisma scripts for diagnosing D2 scrape jobs, performance
  • scoreChangedAt bumps, Summit scoresheet rows, and recent ScrapeJob
  • touches. Useful for spot-checking live-monitor harvest behavior
  • locally.

Files Changed

Created (5):
  • + scripts/debug/check-d2-recent-bumps.ts
  • + scripts/debug/check-d2-scrape-status.ts
  • + scripts/debug/check-d2-summit-scoresheets.ts
  • + scripts/debug/check-d2-times.ts
  • + scripts/debug/check-recent-touches.ts
Modified (5):
  • ~ scripts/debug/check-d2-recent-bumps.ts
  • ~ scripts/debug/check-d2-scrape-status.ts
  • ~ scripts/debug/check-d2-summit-scoresheets.ts
  • ~ scripts/debug/check-d2-times.ts
  • ~ scripts/debug/check-recent-touches.ts

Version 0.2.372

DOCS: add John Knowles partnership drafts

May 14, 2026 at 2:53 AM GMT+0
5c0e6d3
🔄Changed
  • DOCS: add John Knowles partnership drafts
  • Adds term sheet, affiliate agreement, curriculum proposal, and outreach
  • email under docs/contracts/john-knowles/, mirroring the per-partner
  • folder pattern established for Let's Talk Cheer.

Version 0.2.371

DOCS: reorganize LTC contract files under per-partner subdirectory

May 14, 2026 at 2:51 AM GMT+0
32270b8
🔄Changed
  • DOCS: reorganize LTC contract files under per-partner subdirectory
  • Moves the four fullout-ltc-* contract files into
  • docs/contracts/lets-talk-cheer/ so each partner's paperwork lives in
  • its own folder. Sets up the same pattern for future partner contracts.

Version 0.2.370

PARTNER: cookie attribution is first-touch (matches contract §4.4)

May 13, 2026 at 11:45 PM GMT+0
d321882
🔄Changed
  • PARTNER: cookie attribution is first-touch (matches contract §4.4)
  • Previous commit set the partner cookie last-touch (overwriting on every
  • new `?p=` click). The partner referral agreement
  • (src/docs/partner-referral-agreement.md §4.4) specifies first-touch:
  • the first Partner link clicked within the Cookie Window receives
  • credit; subsequent clicks do not transfer attribution to a different

Files Changed

Created (1):
  • + src/lib/__tests__/partner-cookie.test.ts
Modified (4):
  • ~ src/app/api/partner/track/route.ts
  • ~ src/lib/__tests__/partner-cookie.test.ts
  • ~ src/lib/partner-cookie.ts
  • ~ src/middleware.ts

Version 0.2.369

PARTNER+LTC: one-step TIER_FLAT setup + Let's Talk Cheer contracts

May 13, 2026 at 11:09 PM GMT+0
4b5ab4c
🔄Changed
  • PARTNER+LTC: one-step TIER_FLAT setup + Let's Talk Cheer contracts
  • Admin Add Partner now exposes the four per-tier rate inputs inline when
  • commission type is TIER_FLAT, with an "Apply FullOut x LTC defaults"
  • preset (fills $1/$6/$10/$60 and bumps min payout to $100). Save creates
  • the Partner row and the four PartnerCommissionRate rows in one flow, so
  • configuring a new TIER_FLAT partner no longer requires a detail-page

Files Changed

Modified (2):
  • ~ src/components/admin/partner-form.tsx
  • ~ src/components/admin/partners/commission-rate-editor.tsx

Version 0.2.368

PARTNER: real 30-day attribution cookies (replaces localStorage)

May 13, 2026 at 10:34 PM GMT+0
330eeeb
🔄Changed
  • PARTNER: real 30-day attribution cookies (replaces localStorage)
  • Replaces the localStorage-scoped partner code path with a real
  • `fo_partner` cookie set by Edge middleware on any URL carrying `?p=`.
  • Cookie is the authoritative source from middleware -> create-checkout
  • > Stripe metadata -> webhook. localStorage path on /subscribe retired.
  • Cookie chokepoint (`src/lib/partner-cookie.ts`): shared name, default

Files Changed

Created (2):
  • + src/components/partner/partner-click-tracker.tsx
  • + src/lib/partner-cookie.ts
Modified (9):
  • ~ src/app/api/partner/track/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/layout.tsx
  • ~ src/app/subscribe/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/components/admin/partner-form.tsx
  • ~ src/components/partner/partner-click-tracker.tsx
  • ~ src/lib/partner-cookie.ts
  • ~ src/middleware.ts

Version 0.2.367

BRAND: tighten brand page, drop lockup and symbol sections

May 13, 2026 at 10:32 PM GMT+0
a4dba1e
🔄Changed
  • BRAND: tighten brand page, drop lockup and symbol sections
  • Removes the partner-facing lockup and footprint-symbol sections; those
  • marks are reserved for internal use on team shoe-color graphics, not
  • partner co-marketing. Replaces the cascade with a wordmark-only
  • reference showing the correct variant per background (pink, dark,
  • light). Updates the brand contact to team@fullout.energy.

Files Changed

Modified (1):
  • ~ src/app/brand/page.tsx

Version 0.2.366

BRAND: tighten brand page — drop lockup/symbol sections, add wordmark-on-backgrounds reference

May 13, 2026 at 10:29 PM GMT+0
6d2b7d5
🔄Changed
  • BRAND: tighten brand page — drop lockup/symbol sections, add wordmark-on-backgrounds reference
  • Removes the partner-facing lockup and footprint-symbol sections; those
  • marks are reserved for internal use on team shoe-color graphics, not
  • partner co-marketing. Replaces the cascade with a wordmark-only
  • reference showing the correct variant per background (pink / dark /
  • light). Updates the brand contact to team@fullout.energy.

Files Changed

Modified (1):
  • ~ src/app/brand/page.tsx

Version 0.2.364

BRAND: public brand guidelines page at /brand with downloadable assets

May 13, 2026 at 10:16 PM GMT+0
bceb3b2
🔄Changed
  • BRAND: public brand guidelines page at /brand with downloadable assets
  • Adds a partner-facing brand guidelines page covering usage rights, logo
  • downloads (wordmark, lockup, symbol, app icons), color palette,
  • typography, voice and tone, and don'ts. Referenced from partner
  • agreements.

Files Changed

Created (1):
  • + src/app/brand/page.tsx
Modified (1):
  • ~ src/app/brand/page.tsx

Version 0.2.363

ANALYZE: Smart Groups — filter-based, auto-updating watchlists

May 13, 2026 at 11:19 PM GMT+0
5123289
Added
  • ANALYZE: new Smart Groups — saved filter queries (Level, Age category, State, scope to followed-teams or followed-gyms) that resolve to a live list of teams every time you open the group. As new teams compete in the same division or new gyms get added, the group grows automatically. No re-pinning required.
  • ANALYZE: Smart Group builder dialog launched from the hub's My Groups section. Filter chips for Levels, Age categories, and States; checkboxes to scope to your followed teams or gyms. Live preview shows how many teams match before you save.
  • ANALYZE: /analyze/group/[id] handles both flavors transparently. TEAM_GROUP uses hand-picked FollowGroupItem rows; SMART_GROUP runs resolveSmartGroupTeams() at request time. Group hero shows a 'Smart group' badge so users know which type they're looking at.
  • API: POST /api/follow-groups now accepts type=SMART_GROUP with a filterQuery payload. POST /api/smart-groups/preview returns a live match count for the builder dialog. GET /api/smart-groups/dimensions returns the available level / age / state values for populating the builder dropdowns.
  • DB: FollowGroup.filterQuery (JSON, nullable) + new SMART_GROUP enum value. Additive migration pushed via prisma db push.

Files Changed

Modified (9):
  • ~ prisma/schema.prisma
  • ~ src/lib/smart-groups.ts
  • ~ src/app/api/follow-groups/route.ts
  • ~ src/app/api/smart-groups/preview/route.ts
  • ~ src/app/api/smart-groups/dimensions/route.ts
  • ~ src/components/analyze/smart-group-builder.tsx
  • ~ src/components/analyze/analyze-hub.tsx
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/[username]/analyze/group/[id]/page.tsx

Version 0.2.362

ANALYZE: tabbed drill-downs for team, gym, and group

May 13, 2026 at 10:55 PM GMT+0
e23458f
🔄Changed
  • ANALYZE: Single Team drill-down is now tabbed. Header and KPI strip stay always-visible. Tabs: Overview (score trend + recent results) · Edge (vs division peers) · Pressure (Prelims→Finals) · Scoresheet (per-event breakdown) · Breakdown (category vs division avg). Long scroll gone; each tab is a focused view.
  • ANALYZE: Whole Gym drill-down is now tabbed. Header and KPI strip stay always-visible. Tabs: Overview (team rankings) · Teams (per-field trends) · Categories (gym-wide averages bar chart) · Deductions (deduction patterns) · Consistency (volatility ranking).
  • ANALYZE: Group drill-down /analyze/group/[id] is now a real page instead of a redirect. Server-fetches the group + its members + last-2-season performances and renders a focused header above the existing AnalysisPanel (which already has Overview / Trends / Deep Dive / Recent tabs). Hub group cards link directly to this page now.

Files Changed

Modified (5):
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/components/gym-analysis/gym-dashboard.tsx
  • ~ src/components/my-teams/group-detail-client.tsx
  • ~ src/app/[username]/analyze/group/[id]/page.tsx
  • ~ src/components/analyze/group-card.tsx

Version 0.2.360

ANALYZE: rebuild landing as structured hub (briefing + watchlists + tools)

May 13, 2026 at 9:10 PM GMT+0
be7faa4
🔄Changed
  • ANALYZE: replaced the configurable widget grid landing with an opinionated hub. Top to bottom: Headlines (most-recent result, biggest mover, weakest watched category) → My Teams (card grid with avg / latest / trend / division badge, filterable by Level + Age, sortable) → My Gyms (cards with avg + trend across followed teams, plus an inline two-gym compare picker) → My Groups (cards with group avg + trend) → Deep analysis links (single team, compare teams, compare gyms, edge finder, pressure splits, density map).
  • ANALYZE: every entity card is a click-through to its drill-down page. No more 'assemble your own dashboard' — the value is on the page when you land.
  • ANALYZE: widget code (DashboardClient + widgets/*) remains in the repo and is still functional for the Phase 5 saved-dashboard model and the shared /dashboards/[slug] route, but it is no longer the landing page. Will be revisited later as either a 'power view' route or repurposed as 'hub configurations'.

Files Changed

Modified (7):
  • ~ src/components/analyze/analyze-hub.tsx
  • ~ src/components/analyze/headlines.tsx
  • ~ src/components/analyze/team-card.tsx
  • ~ src/components/analyze/gym-card.tsx
  • ~ src/components/analyze/group-card.tsx
  • ~ src/components/analyze/hub-types.ts
  • ~ src/app/[username]/analyze/page.tsx

Version 0.2.359

ANALYZE FIX: Pressure Splits crash when a round is missing

May 13, 2026 at 5:55 AM GMT+0
94aa32a
🐛Fixed
  • ANALYZE: Single Team page crashed with 'Cannot read properties of undefined (reading avg)' when a team had Prelims + Finals but no Semi-Finals (or any other missing round). Pairwise-delta guards used optional chaining (`semis?.avg !== null`) which is true for undefined and then dereferenced semis!.avg!. Rewrote the section to build the visible pairs from data and only emit deltas where both ends exist.

Files Changed

Modified (1):
  • ~ src/components/my-teams/clutch-splits.tsx

Version 0.2.358

ANALYZE: Pressure / Clutch splits — finals vs prelims choke detection

May 13, 2026 at 5:34 AM GMT+0
42bc6ce
Added
  • ANALYZE: new Pressure Splits view on the Single Team page. Groups every routine by round (Prelims / Wild Card / Semi-Finals / Finals) and surfaces per-round averages, score range, and deduction frequency. Computes pairwise deltas (Prelims→Semis, Semis→Finals, Prelims→Finals) so a coach can see at a glance whether a team builds momentum or loses it when the lights come on.
  • ANALYZE: 'Closes strong' / 'Bleeds in Finals' / 'Steady under pressure' verdict badge — Prelims→Finals delta of >+0.3 / <-0.5 / in-between. Color-coded so it pops on the page.
  • ANALYZE: new Pressure Splits dashboard widget (Pro tier) — compact bar chart of average final by round with the verdict inline. Filterable to one team or a group of teams.

Files Changed

Modified (6):
  • ~ src/components/my-teams/clutch-splits.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/components/dashboard/widgets/pressure-splits-widget.tsx
  • ~ src/components/dashboard/types.ts
  • ~ src/components/dashboard/widget-registry.tsx
  • ~ src/components/dashboard/dashboard-grid.tsx

Version 0.2.357

ANALYZE: division benchmarks in KPI widgets + Division Snapshot

May 13, 2026 at 5:29 AM GMT+0
69a3f98
Added
  • ANALYZE: KPI widgets configured for a single team now optionally show a division benchmark line — '+1.4 vs div · 78th pct' — so the headline number always answers 'compared to what?'. Available on avgScore / seasonHigh / momentum metrics. Configurable via the widget settings sheet.
  • ANALYZE: new Division Snapshot widget — histogram of every team's average final score in the same Division (level + age category) for the season, with the configured team highlighted in pink and labeled 'You'. The 'where do we rank?' question answered at a glance, in one widget.
  • API: /api/analytics/edge-finder now also returns peerTeamAverages[] — the per-team averages used to render Division Snapshot histograms (and available to any future widget that wants the raw division distribution).

Files Changed

Modified (8):
  • ~ src/lib/analytics/edge-finder.ts
  • ~ src/components/my-teams/edge-finder.tsx
  • ~ src/components/dashboard/types.ts
  • ~ src/components/dashboard/widgets/kpi-widget.tsx
  • ~ src/components/dashboard/widgets/division-snapshot-widget.tsx
  • ~ src/components/dashboard/widget-registry.tsx
  • ~ src/components/dashboard/dashboard-grid.tsx
  • ~ src/components/dashboard/widget-config-sheet.tsx

Version 0.2.356

ANALYZE: server-side saved dashboards + Pro-to-Pro sharing

May 13, 2026 at 4:57 AM GMT+0
bf4359d
Added
  • ANALYZE: dashboards are now persisted to the server (new Dashboard Prisma model). Multi-dashboard support — create, switch, duplicate, rename, delete. Each user can keep separate saved layouts (e.g. one for L5 Senior watchlist, one for the gym's national-level teams).
  • ANALYZE: Pro users can toggle a dashboard to 'Shared' and copy a /dashboards/{slug} link. Other Pro users who open the link see the saved widget layout rendered against THEIR followed-team data (widgets are saved layouts, not snapshots). FREE/ELITE viewers see an upgrade prompt; FREE/ELITE owners can't toggle sharing on.
  • ANALYZE: dashboard dropdown menu replaces the static 'Analyze' header. Click the dashboard name to switch / create / rename / duplicate / share / delete.
  • ANALYZE: 'Save the current active group as a new group' shortcut added to the active-group context bar.
  • ANALYZE: localStorage→server migration runs on first authenticated load — existing user dashboards get ported up to the server transparently.
🔄Changed
  • Prisma schema: added Dashboard model (id, slug, userId, name, widgets JSON, isShared, activeGroupId). Pushed to production via `prisma db push`.

Files Changed

Modified (7):
  • ~ prisma/schema.prisma
  • ~ src/app/api/dashboards/route.ts
  • ~ src/app/api/dashboards/[slug]/route.ts
  • ~ src/lib/dashboards-api.ts
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/dashboard/shared-dashboard-view.tsx
  • ~ src/app/dashboards/[slug]/page.tsx

Version 0.2.355

ANALYZE: elevate custom groups — active-group context + save-as-group

May 13, 2026 at 4:49 AM GMT+0
c76b721
Added
  • ANALYZE: new active-group context selector in the dashboard landing header — pick a saved group and every widget on the dashboard auto-filters to that group's teams. Persists across sessions via localStorage. Shows a badge so the active context is always visible.
  • ANALYZE: 'Save as group' button on ad-hoc ?teams= comparisons. Open any multi-team URL, see the analysis, then one click to persist it as a named custom group and jump straight into the saved view.
  • API: POST /api/follow-groups now accepts an optional teamIds: string[] payload and bulk-creates the FollowGroupItem rows in the same transaction, so the dashboard 'Save as group' flow is a single round-trip. Server validates that the user follows every team being added and caps at the tier's maxGroupSize.

Files Changed

Modified (5):
  • ~ src/app/api/follow-groups/route.ts
  • ~ src/components/follows/save-as-group-button.tsx
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/my-teams/my-teams-client.tsx
  • ~ src/app/[username]/analyze/page.tsx

Version 0.2.354

ANALYZE: Compare Gyms — side-by-side multi-gym analytics (Pro)

May 13, 2026 at 4:43 AM GMT+0
453d259
Added
  • ANALYZE: new Compare Gyms mode (Pro) — pick 2–4 followed gyms and see a side-by-side breakdown: per-gym KPI columns (avg final, deductions, std-dev, best/worst category, top deduction type), a Category Profile radar overlaying all gyms, a deduction-by-type comparison bar chart, and a head-to-head section listing every time teams from two or more gyms met in the same Division at the same Competition.
  • ANALYZE: URL contract /analyze?mode=gym-compare&gyms=slug1,slug2,slug3 — bookmarkable, shareable.
  • ANALYZE: 'Compare Gyms' quick-nav card on the dashboard landing (appears when the user follows 2+ gyms).
  • ANALYZE: 'Compare with [other gym]' button added to the standalone gym view header for one-click side-by-side.

Files Changed

Modified (5):
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/components/gym-analysis/gym-comparison.tsx
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/my-teams/my-teams-client.tsx

Version 0.2.353

ANALYZE: Edge Finder — Moneyball-style division gap analysis

May 13, 2026 at 4:38 AM GMT+0
653a2eb
Added
  • ANALYZE: new Edge Finder view that shows category-by-category how a team performs vs every other team in the same Division (level + age category) for a given season. Surfaces where a team over-indexes (their 'edge') and where they bleed points (sorted by leverage = |gap| × division stddev, so highest-impact fixes float to the top).
  • ANALYZE: Edge Finder is embedded in the Single Team analysis tab and also available as a new dashboard widget. Elite tier minimum (uses division benchmarks).
  • API: new GET /api/analytics/edge-finder?teamId=...&season=...[&divisionId=...] returning per-category teamAvg, divisionAvg, stddev, gap, percentile, and leverage. Auto-picks the team's primary division for the season when divisionId is omitted.
  • lib: new src/lib/analytics/edge-finder.ts with EDGE_FINDER_FIELDS, getTeamPrimaryDivision, getEdgeFinderResult.

Files Changed

Modified (8):
  • ~ src/lib/analytics/edge-finder.ts
  • ~ src/app/api/analytics/edge-finder/route.ts
  • ~ src/components/my-teams/edge-finder.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/components/dashboard/widgets/edge-finder-widget.tsx
  • ~ src/components/dashboard/widget-registry.tsx
  • ~ src/components/dashboard/types.ts
  • ~ src/components/dashboard/dashboard-grid.tsx

Version 0.2.352

ANALYZE: repair broken KPI math, deduction pie, and chart tooltips

May 13, 2026 at 4:32 AM GMT+0
4280d45
🐛Fixed
  • ANALYZE: Deduction Rate KPI now averages totalDeductions instead of returning the average final score (was a copy/paste bug). Trend arrow inverts color so rising deductions show red.
  • ANALYZE: Consistency KPI now reports the actual std-dev value (e.g. 'σ 0.42 — Good') instead of a categorical word with a misleading 'Stable' trend arrow. Rating colored by quality.
  • ANALYZE: Deduction Breakdown pie chart no longer silently falls back to Building/Tumbling/Performance score points when no deductions exist — those are points earned, not points lost. Empty state now reads 'No deductions logged'. Deduction type names humanized.
  • ANALYZE: Score-trend line chart tooltip now shows competition name, full date, and round (was just 'Feb 29' with no context). X-axis labels include the year when the dataset spans multiple seasons.

Files Changed

Modified (3):
  • ~ src/components/dashboard/widgets/kpi-widget.tsx
  • ~ src/components/dashboard/widgets/pie-chart-widget.tsx
  • ~ src/components/dashboard/widgets/line-chart-widget.tsx

Version 0.2.351

SCORECARD: gate CSV export to PRO + clarify pricing label

May 12, 2026 at 2:55 AM GMT+0
43dc8eb
🔄Changed
  • SCORECARD: gate CSV export to PRO + clarify pricing label
  • CompetitionPerformances now takes canExportCsv; the button only
  • renders when true. Defense-in-depth — the Scorecard tab itself was
  • already PRO-gated, but the button is now self-gated so it can't
  • leak if the tab gate is ever loosened.
  • CompetitionTabs passes canExportCsv = isAdmin || tier === "PRO".

Files Changed

Modified (3):
  • ~ src/app/pricing/page.tsx
  • ~ src/components/competitions/competition-performances.tsx
  • ~ src/components/competitions/competition-tabs.tsx

Version 0.2.350

SCORECARD: sort/filter every column, sub-sub-group, CSV export

May 11, 2026 at 11:10 PM GMT+0
b34af2c
🔄Changed
  • SCORECARD: sort/filter every column, sub-sub-group, CSV export
  • Refactor the competition Scorecard table to a single internal column
  • registry (ColumnDef[]) that drives the header, body cells, sort
  • accessors, and CSV export. Visual output preserved.
  • Every column is now sortable, including the score-detail columns
  • (Stunt D/E, Pyr D/E, Toss D/E, etc.) that previously had no sort

Files Changed

Modified (1):
  • ~ src/components/competitions/competition-performances.tsx

Version 0.2.349

SCORECARD: sort/filter every column, sub-sub-group, CSV export of current view

May 11, 2026 at 5:00 AM GMT+0
6b400d0
Added
  • Every column on the competition Scorecard is now sortable, including the score-detail columns (Stunt D/E, Pyr D/E, Toss D/E, etc.) that previously had no sort affordance.
  • Per-column filters on every Scorecard header. Click the filter icon next to a header to open a popover: numeric columns get min/max inputs (e.g. Total >= 95); string columns get a 'contains' input plus a multi-select of every distinct value in the current data. Active filters show a dot on the header.
  • Sub-sub-group dropdown on the Scorecard. Combines with Group by + Sub-group by to render a 3-level collapsible tree (e.g. Level > Age > Size). Disabled until Sub-group by is set.
  • Export CSV button on the Scorecard toolbar. The CSV reflects exactly what's on screen — same active sort, sidebar filters, column filters, and visible breakdown columns. When grouped, the Group / Sub-group / Sub-sub-group labels are prepended as leading columns on every row.
🔄Changed
  • Scorecard table is now driven by a single internal column registry instead of hardcoded JSX per cell. No visual change — this unblocks the new sort/filter behavior above.

Files Changed

Modified (3):
  • ~ src/components/competitions/competition-performances.tsx
  • ~ package.json
  • ~ CHANGELOG.json

Version 0.2.348

PROFILE: punctuation-tolerant gym/team search + remove Social Links from Highlights tab

May 8, 2026 at 5:00 AM GMT+0
93022fb
🔄Changed
  • Gym and team search (used by the experience editor on the profile) now normalizes punctuation in the query and matches each token independently. Typing 'cheer athletics frisco' now finds 'Cheer Athletics - Frisco' without the user needing to add the dash.
🗑️Removed
  • The 'Social Links' section (VideoManager with the paste-a-link form) is no longer rendered on the profile Highlights tab. The Highlights tab now shows only the user's pinned highlight posts. EmbeddedVideo data and the VideoManager component remain available wherever else they're used.

Files Changed

Modified (6):
  • ~ src/app/api/gyms/route.ts
  • ~ src/app/api/teams/route.ts
  • ~ src/components/profile/profile-highlights-tab.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ package.json
  • ~ CHANGELOG.json

Version 0.2.347

FEED: new Global tab + author team/gym byline on every media post

May 8, 2026 at 5:00 AM GMT+0
4c7e9de
Added
  • New Global feed at /global — reverse-chronological firehose of every public PersonPhoto + ProfileVideo upload across the platform. Guest-accessible (no login required) so new visitors can discover athletes before they pick anyone to follow.
  • Third tab between For You and Hub in the feed tab nav, on /home, /global, and /news.
🔄Changed
  • Photo and video posts in the For You feed (and the new Global feed) now display the author's current team and gym under their name, sourced from the most recent ongoing PersonExperience. Mirrors the team · gym pattern already used by performance cards.
  • FeedList component accepts an apiPath prop so /global can paginate against /api/feed/global while /home keeps using /api/feed.

Files Changed

Modified (10):
  • ~ src/app/api/feed/route.ts
  • ~ src/app/home/page.tsx
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/feed-tabs-nav.tsx
  • ~ src/app/api/feed/global/route.ts
  • ~ src/app/global/page.tsx
  • ~ src/lib/feed/current-team-byline.ts
  • ~ src/lib/feed/global-feed.ts
  • ~ package.json
  • ~ CHANGELOG.json

Version 0.2.346

DATA: backfill Worlds 2026 Prelims + Semi-Finals scores (was Finals-only)

May 8, 2026 at 5:00 AM GMT+0
56c07e9
Added
  • Worlds 2026 Prelims scores — 71 performances across 5 wild-card divisions
  • Worlds 2026 Semi-Finals scores — 488 performances across all 29 divisions
  • /competitions/cheerleading-worlds-2026 now shows the full Prelims → Semi-Finals → Finals progression for every team that competed
🔄Changed
  • scripts/import/scrape-worlds-2026-results.ts and import-worlds-2026-results.ts now take a --round flag (prelims | semi-finals | finals); finals remains the default for backward compat

Files Changed

Modified (2):
  • ~ scripts/import/scrape-worlds-2026-results.ts
  • ~ scripts/import/import-worlds-2026-results.ts

Version 0.2.345

PRIVACY: 4-tier profile visibility (Only me / People I follow / FullOut users / Everyone)

May 8, 2026 at 6:27 PM GMT+0
b843885
🔄Changed
  • PRIVACY: 4-tier profile visibility (Only me / People I follow / FullOut users / Everyone)
  • Replaces binary Person.isPublic with a Person.visibility enum and applies
  • the chokepoint helper across every surface that lists or links to a Person:
  • profile page (including SEO metadata + OG image), team rosters, gym rosters,
  • /people directory, search APIs, follower/following lists, PDF export, and
  • the discover/PCL/athlete-spotlight content surfaces.

Files Changed

Created (4):
  • + scripts/debug/test-profile-visibility.ts
  • + scripts/maintenance/backfill-profile-visibility.ts
  • + src/components/profile/profile-privacy-dialog.tsx
  • + src/lib/profile-visibility.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/debug/test-profile-visibility.ts
  • ~ scripts/maintenance/backfill-profile-visibility.ts
  • ~ src/app/[username]/people/page.tsx
  • ~ src/app/api/pdf/profile/[username]/route.tsx
  • ~ src/app/api/people/search/route.ts
  • ~ src/app/api/person/[id]/route.ts
  • ~ src/app/api/person/follow-list/route.ts
  • ~ src/app/api/search/route.ts
  • ~ src/app/discover/page.tsx
  • ~ src/app/gyms/[id]/athletes/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/pcl/page.tsx
  • ~ src/app/people/[username]/opengraph-image.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/page.tsx
  • ~ src/app/teams/[id]/athletes/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/components/profile/profile-privacy-dialog.tsx

Version 0.2.344

PROFILE: 4-tier privacy controls (Only me, People I follow, FullOut users, Everyone)

May 7, 2026 at 5:00 AM GMT+0
bdd54ce
Added
  • PROFILE: 4-tier privacy controls in the profile overflow menu — Only me, People I follow, FullOut users, Everyone (default)
  • Profile visibility filter applied across team rosters, gym rosters, /people directory, search, follower/following lists, OG image, and PDF export
  • Private profiles return noindex metadata and a generic OG image (no name/photo/team leak via SEO)
🔄Changed
  • Replaced binary Person.isPublic with a Person.visibility enum (ProfileVisibility). Legacy isPublic stays in sync until removed in a follow-up migration.
  • 'People I follow' tier semantics: following someone consents to letting them see your profile (owner-controlled circle).

Files Changed

Modified (22):
  • ~ prisma/schema.prisma
  • ~ src/lib/profile-visibility.ts
  • ~ src/components/profile/profile-privacy-dialog.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/[username]/opengraph-image.tsx
  • ~ src/app/people/page.tsx
  • ~ src/app/[username]/people/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/app/teams/[id]/athletes/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/gyms/[id]/athletes/page.tsx
  • ~ src/app/discover/page.tsx
  • ~ src/app/pcl/page.tsx
  • ~ src/app/api/search/route.ts
  • ~ src/app/api/people/search/route.ts
  • ~ src/app/api/person/follow-list/route.ts
  • ~ src/app/api/person/[id]/route.ts
  • ~ src/app/api/pdf/profile/[username]/route.tsx
  • ~ src/lib/content/athlete-spotlight.ts
  • ~ scripts/maintenance/backfill-profile-visibility.ts
  • ~ scripts/debug/test-profile-visibility.ts

Version 0.2.343

NAV: align expanded/collapsed sidebar shape; move Post button above Collapse

May 8, 2026 at 5:34 PM GMT+0
3bc5bdc
🔄Changed
  • NAV: align expanded/collapsed sidebar shape; move Post button above Collapse
  • Groups in the desktop sidebar no longer persist their open/close state to
  • localStorage — they default to closed and only auto-open when a child
  • route is active. This makes the expanded sidebar's default structure
  • match the icon-only collapsed sidebar (same 9 top-level rows).
  • Also moves the Post CTA from the top of the nav to directly above the

Files Changed

Modified (2):
  • ~ src/components/dashboard/nav-group-item.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.342

NAV: add Post button to desktop sidebar

May 8, 2026 at 4:52 PM GMT+0
fcb3c02
🔄Changed
  • NAV: add Post button to desktop sidebar
  • Mirrors the mobile bottom-nav "+" pill. Wires up the existing onPostClick
  • prop (already passed by app-shell) so the sidebar opens the same
  • PostDialog the desktop shell already had plumbed.

Files Changed

Modified (1):
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.341

NAV: stop Profile from highlighting on My Stuff routes

May 7, 2026 at 2:41 PM GMT+0
a353f54
🔄Changed
  • NAV: stop Profile from highlighting on My Stuff routes
  • Profile's match list included bare /${username}, which prefix-matched
  • every /${username}/* My Stuff route (My Teams, My People, etc.) and
  • lit Profile up alongside the active item. The bare path isn't a real
  • route — Profile lives at /@${username} — so the matcher entry was
  • dead weight that happened to break the active state.

Files Changed

Modified (1):
  • ~ src/lib/nav-config.ts

Version 0.2.340

NAV: fix bottom nav floating mid-screen in iOS PWA — portal to body + force composite layer

May 7, 2026 at 2:37 PM GMT+0
1a0ef5e
🔄Changed
  • NAV: fix bottom nav floating mid-screen in iOS PWA — portal to body + force composite layer
  • Portal MobileBottomNav directly to document.body so no React-tree ancestor
  • can ever introduce a transform that breaks position:fixed. Sibling-rendering
  • (commit 6cdc484) relied on Providers never introducing transformed DOM —
  • fragile contract. Portal makes the chokepoint enforcement durable.
  • Add transform: translateZ(0) on the fixed wrapper to force a GPU composite

Files Changed

Modified (1):
  • ~ src/components/app-shell.tsx

Version 0.2.339

PAYOUTS: escape apostrophe in Awaiting review description

May 7, 2026 at 12:09 AM GMT+0
9e8314e
🔄Changed
  • PAYOUTS: escape apostrophe in Awaiting review description
  • Vercel build was failing on react/no-unescaped-entities.

Files Changed

Modified (1):
  • ~ src/app/admin/partners/payouts/page.tsx

Version 0.2.338

SCHEDULE: import 2026 D2 Summit performance order from Varsity PDF

May 7, 2026 at 12:08 AM GMT+0
a7655df
🔄Changed
  • SCHEDULE: import 2026 D2 Summit performance order from Varsity PDF
  • Imports 1324 entries (905 confirmed teams + 419 TBD finals slots) across
  • 3 days and 5 venues at ESPN Wide World of Sports. 89% triple-matched
  • auto-imported, 50 flagged for review, real unmatched teams under 20.
  • Multi-track block-schedule layout: lines can carry 1-2 division markers
  • (e.g., "L4 SCM #2 L4 SS-A #1 Titan Elite - Immortals") — disambiguated

Files Changed

Created (3):
  • + scripts/debug/decode-d2-divisions.ts
  • + scripts/debug/verify-flex-meaning.ts
  • + scripts/import/import-d2-summit-2026-schedule.ts
Modified (3):
  • ~ scripts/debug/decode-d2-divisions.ts
  • ~ scripts/debug/verify-flex-meaning.ts
  • ~ scripts/import/import-d2-summit-2026-schedule.ts

Version 0.2.337

PARTNERS: lookup by email OR username in Add Partner form

May 6, 2026 at 11:58 PM GMT+0
4b07faa
🔄Changed
  • PARTNERS: lookup by email OR username in Add Partner form
  • The /api/admin/users search already covered username, but the endpoint's
  • select omitted it — so the form's slug-from-username fallback (line 64)
  • silently never fired. Adds username to the select and surfaces it in the
  • form: relabeled input, Enter-to-search, and an exact-match preference so
  • a partial query like 'joe' no longer grabs whichever joe* was created

Files Changed

Modified (2):
  • ~ src/app/api/admin/users/route.ts
  • ~ src/components/admin/partner-form.tsx

Version 0.2.336

DEBUG: check out scripts from recent investigations

May 6, 2026 at 11:47 PM GMT+0
c383a41
🐛Fixed
  • DEBUG: check out scripts from recent investigations
  • Adds the one-off investigation + maintenance scripts that have been
  • sitting untracked for a while:
  • scripts/health/check-partner-system.ts — health check for the
  • partner/affiliate system end-to-end.
  • scripts/debug/check-d2-summit.ts, check-summit-finals-detail.ts,

Files Changed

Created (9):
  • + scripts/debug/check-d2-summit.ts
  • + scripts/debug/check-novacats-logos.ts
  • + scripts/debug/check-summit-finals-detail.ts
  • + scripts/debug/check-summit-finals-gap.ts
  • + scripts/debug/check-woodlands-elite.ts
  • + scripts/debug/check-woodlands-logos.ts
  • + scripts/debug/find-babygraham.ts
  • + scripts/debug/fix-sot-city.ts
  • + scripts/health/check-partner-system.ts
Modified (9):
  • ~ scripts/debug/check-d2-summit.ts
  • ~ scripts/debug/check-novacats-logos.ts
  • ~ scripts/debug/check-summit-finals-detail.ts
  • ~ scripts/debug/check-summit-finals-gap.ts
  • ~ scripts/debug/check-woodlands-elite.ts
  • ~ scripts/debug/check-woodlands-logos.ts
  • ~ scripts/debug/find-babygraham.ts
  • ~ scripts/debug/fix-sot-city.ts
  • ~ scripts/health/check-partner-system.ts

Version 0.2.335

OG: refresh subtitle to lead with concrete benefits

May 6, 2026 at 11:47 PM GMT+0
775b632
🔄Changed
  • OG: refresh subtitle to lead with concrete benefits
  • Replaces the abstract "Competitive cheerleading, organized." with a
  • benefits-led line: live scores, season history, free athlete profiles.
  • Same image, sharper hook for link previews.

Files Changed

Modified (1):
  • ~ src/app/opengraph-image.tsx

Version 0.2.334

PAYOUTS: partner-requested payouts with admin queue, email + in-app alerts

May 6, 2026 at 11:35 PM GMT+0
b35b9b6
🔄Changed
  • PAYOUTS: partner-requested payouts with admin queue, email + in-app alerts
  • End-to-end affiliate payout request flow.
  • PARTNER SIDE (settings → affiliate)
  • "Request payout" button on the Pending card, gated on
  • available balance >= partner.payoutMinimumCents and disabled when an
  • in-flight request already exists (one at a time).

Files Changed

Created (5):
  • + src/app/admin/partners/payouts/page.tsx
  • + src/app/api/admin/partners/payouts/[payoutId]/mark-paid/route.ts
  • + src/app/api/admin/partners/payouts/[payoutId]/reject/route.ts
  • + src/app/api/partner/dashboard/payouts/request/route.ts
  • + src/components/admin/partners/payout-queue-client.tsx
Modified (11):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/partners/page.tsx
  • ~ src/app/admin/partners/payouts/page.tsx
  • ~ src/app/api/admin/partners/payouts/[payoutId]/mark-paid/route.ts
  • ~ src/app/api/admin/partners/payouts/[payoutId]/reject/route.ts
  • ~ src/app/api/partner/dashboard/payouts/request/route.ts
  • ~ src/app/api/partner/dashboard/stats/route.ts
  • ~ src/components/admin/partners/payout-queue-client.tsx
  • ~ src/components/partner/partner-dashboard.tsx
  • ~ src/lib/email.ts
  • ~ src/lib/notifications.ts

Version 0.2.333

BADGES: fix Elite tooltip label — was reading "Prep subscriber"

May 6, 2026 at 11:00 PM GMT+0
0005f53
🔄Changed
  • BADGES: fix Elite tooltip label — was reading "Prep subscriber"

Files Changed

Modified (1):
  • ~ src/components/profile/tier-verification-badge.tsx

Version 0.2.332

UI: cleaner division detail rows — drop medal emojis, surface gym name

May 6, 2026 at 10:46 PM GMT+0
c460c98
🔄Changed
  • UI: cleaner division detail rows — drop medal emojis, surface gym name
  • Replaces 🥇🥈🥉/#N placement glyphs with consistent #N for top-3 too.
  • Emoji rendering varies wildly across platforms and looked decorative
  • next to the otherwise dense, tabular score rows.
  • Adds the gym name (linked to the gym page) under team name on each
  • score row, hidden on mobile (`hidden sm:inline`) to avoid crowding

Files Changed

Modified (1):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx

Version 0.2.331

UI: align mobile bottom-nav Post button with icon+label rhythm

May 6, 2026 at 10:46 PM GMT+0
9b9decf
🔄Changed
  • UI: align mobile bottom-nav Post button with icon+label rhythm
  • The center compose button was a popped-up 44px FAB (-mt-5, no label),
  • which broke the rhythm of the surrounding icon+label nav items. Now it
  • matches its siblings: column layout, 28px pink badge with Plus icon
  • above a "Post" label, so the whole row reads as five aligned objects
  • instead of "four nav items + a floating button."

Files Changed

Modified (1):
  • ~ src/components/app-shell.tsx

Version 0.2.330

BADGES: refresh tier verification colors — Pro = brand pink, Elite = soft cyan

May 6, 2026 at 10:45 PM GMT+0
79fe001
🔄Changed
  • BADGES: refresh tier verification colors — Pro = brand pink, Elite = soft cyan
  • Tier checkmark badge moves to the brand palette: Pro fills with hero pink
  • (#EE2B8C / --primary) + white check; Elite fills with soft cyan (#91E5E5)
  • + deep-teal check (#0F4C4C) for tonal cohesion. Replaces the old generic
  • blue + yellow.
  • Also moves the PRO row in `tierColors` from hardcoded pink-* Tailwind

Files Changed

Modified (2):
  • ~ src/components/profile/tier-verification-badge.tsx
  • ~ src/lib/design-tokens.ts

Version 0.2.329

URLS: route person search results to /people/<username>, not opaque ID

May 6, 2026 at 10:44 PM GMT+0
c188cc7
🔄Changed
  • URLS: route person search results to /people/<username>, not opaque ID
  • Search results now carry the username as `slug` so consumers can build
  • the human-readable /people/<username> URL. The dynamic route accepts
  • either shape, but the username path was 404'ing for follows because the
  • fallback used Person.id directly.

Files Changed

Modified (2):
  • ~ src/app/api/search/route.ts
  • ~ src/components/home-search.tsx

Version 0.2.328

SKILLS+VERIFY: by-level visualization, click-to-add, pink hero, 20s video cap

May 6, 2026 at 10:42 PM GMT+0
3a89f32
🔄Changed
  • SKILLS+VERIFY: by-level visualization, click-to-add, pink hero, 20s video cap
  • Skills tab on profiles is now organized by USP level (1, 2, 3, 4, 4.2, 5,
  • 6-Junior, 6-Worlds) instead of category. Each level is a collapsible card
  • showing claimed/total + a pink progress bar; collapsed by default so the
  • landscape is browsable without overwhelming the page.
  • Every rubric skill renders (claimed + unclaimed), so viewers can see what

Files Changed

Created (1):
  • + scripts/debug/seed-fullout-skills.ts
Modified (7):
  • ~ scripts/debug/seed-fullout-skills.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/[username]/skills/[personSkillId]/verify/page.tsx
  • ~ src/components/pdf/profile-pdf-document.tsx
  • ~ src/components/people/person-skills-manager.tsx
  • ~ src/components/showcase/showcase-profile-view.tsx
  • ~ src/components/verification/verification-upload-client.tsx

Version 0.2.326

SUBSCRIBE+CANCEL+TRIAL: trial-end Klaviyo event, Resume button, banked months UI, cancellation banner

May 6, 2026 at 10:11 PM GMT+0
5828d4b
🔄Changed
  • SUBSCRIBE+CANCEL+TRIAL: trial-end Klaviyo event, Resume button, banked months UI, cancellation banner
  • Trial-ending notification (the actual bug)
  • Webhook now handles customer.subscription.trial_will_end. Stripe fires
  • this 3 days before trial_end automatically; we forward to Klaviyo as a
  • "Trial Ending" event with tier, end date, charge amount, and cadence so
  • a Klaviyo flow can send "your card will be charged on {date}" with a

Files Changed

Created (3):
  • + src/app/api/stripe/resume/route.ts
  • + src/components/subscription/cancellation-banner.tsx
  • + src/components/subscription/resume-inline-button.tsx
Modified (11):
  • ~ src/app/api/stripe/resume/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/layout.tsx
  • ~ src/app/settings/page.tsx
  • ~ src/app/subscribe/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/subscription-actions.tsx
  • ~ src/components/subscription/cancellation-banner.tsx
  • ~ src/components/subscription/resume-inline-button.tsx
  • ~ src/lib/klaviyo.ts

Version 0.2.325

PROMO: clearer admin form copy + Stripe coupon-mapping unit tests

May 6, 2026 at 9:50 PM GMT+0
69f6e5c
🔄Changed
  • PROMO: clearer admin form copy + Stripe coupon-mapping unit tests
  • Rewrites the Create/Edit Promo Code dialog so non-engineers can read it:
  • Three preset buttons (1 month free, free forever, 50% off 3 months)
  • Duration field relabeled with an inline cheat-sheet (1 / 6 / blank)
  • Live "What the user gets" preview that mirrors the Stripe coupon shape
  • Extracts buildStripeCouponParams() into src/lib/promo-coupon-mapping.ts

Files Changed

Created (3):
  • + scripts/health/check-promo-stripe-mapping.ts
  • + src/lib/__tests__/promo-coupon-mapping.test.ts
  • + src/lib/promo-coupon-mapping.ts
Modified (5):
  • ~ scripts/health/check-promo-stripe-mapping.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/components/admin/promo-code-form.tsx
  • ~ src/lib/__tests__/promo-coupon-mapping.test.ts
  • ~ src/lib/promo-coupon-mapping.ts

Version 0.2.324

FIX: don't bounce off /login when ?switch or ?add and useSession is stale

May 6, 2026 at 9:45 PM GMT+0
a0b234a
🐛Fixed
  • FIX: don't bounce off /login when ?switch or ?add and useSession is stale
  • Account switcher fall-back ended on a blank page: signOut sometimes can't
  • clear the session cookie (e.g. COOKIE_DOMAIN drift), so useSession still
  • reports "authenticated" on /login. The form returned null and redirected
  • to /home, which redirected back to /login — a loop that rendered blank.
  • Always show the form on the explicit switch/add flows so a fresh sign-in

Files Changed

Modified (1):
  • ~ src/app/login/page.tsx

Version 0.2.323

CHORE: gitignore /og-previews/ — local design-review PNG dumps

May 6, 2026 at 9:29 PM GMT+0
dd309a6
🔄Changed
  • CHORE: gitignore /og-previews/ — local design-review PNG dumps
  • Generated by curling the OG image routes from prod for visual QA;
  • shouldn't ship in the repo.

Version 0.2.322

SUBSCRIBE+CANCEL: surface referrer profile + trial copy on subscribe; cancel at period end

May 6, 2026 at 9:28 PM GMT+0
29490e5
🔄Changed
  • SUBSCRIBE+CANCEL: surface referrer profile + trial copy on subscribe; cancel at period end
  • Subscribe page
  • Show the referrer's avatar, name, and profile link in the green
  • callout when arriving via a ?ref= URL. /api/referral/validate now
  • returns name/username/image instead of hardcoded "A friend".
  • Mirror the server-side REFERRAL coupon client-side so the Order

Files Changed

Modified (7):
  • ~ src/app/api/referral/validate/route.ts
  • ~ src/app/api/stripe/cancel/route.ts
  • ~ src/app/api/user/delete/route.ts
  • ~ src/app/settings/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/components/settings/billing-management.tsx
  • ~ src/components/settings/subscription-actions.tsx

Version 0.2.321

ADJUST: bump OG card text sizes/weights + load real Inter font

May 6, 2026 at 9:05 PM GMT+0
c3776d5
🔄Changed
  • ADJUST: bump OG card text sizes/weights + load real Inter font
  • Per design feedback that the OG cards looked thin/small:
  • Load Inter from Google Fonts at render time (subsetted to only the
  • glyphs each card uses, ~80% bandwidth saving) and pass to
  • ImageResponse so fontWeight 700-900 actually renders heavy. Without
  • this Satori falls back to its built-in font where every weight looks

Files Changed

Modified (5):
  • ~ src/app/gyms/[id]/opengraph-image.tsx
  • ~ src/app/opengraph-image.tsx
  • ~ src/app/people/[username]/opengraph-image.tsx
  • ~ src/app/teams/[id]/opengraph-image.tsx
  • ~ src/lib/og-shared.tsx

Version 0.2.320

FIX: team KPI strip overlapping sidebar + truncating labels at lg

May 6, 2026 at 9:01 PM GMT+0
7aa4a70
🐛Fixed
  • FIX: team KPI strip overlapping sidebar + truncating labels at lg
  • Switched the strip to a 3-col grid at lg (5-col at xl) and removed the
  • mobile edge-bleed margins once the sidebar layout activates, so the
  • cards stay inside the left column instead of crashing into the Athletes
  • sidebar. Trimmed cell padding to px-3 at lg so "PERFORMANCES" fits.

Files Changed

Modified (1):
  • ~ src/components/teams/team-stats-strip.tsx

Version 0.2.319

FIX: inline FullOut logo as base64 so OG entity routes actually find it

May 6, 2026 at 8:07 PM GMT+0
ec772c1
🐛Fixed
  • FIX: inline FullOut logo as base64 so OG entity routes actually find it
  • outputFileTracingIncludes globs with bracketed dynamic segments like
  • [id] don't reliably bundle public/ assets — minimatch treats brackets
  • as character classes. The brand /opengraph-image route worked because
  • its key was a simple path; /teams/[id]/opengraph-image kept ENOENT'ing.
  • Inline the 84KB PNG as a base64 data URI in src/lib/og-logo.ts. The

Files Changed

Created (1):
  • + src/lib/og-logo.ts
Modified (2):
  • ~ src/lib/og-logo.ts
  • ~ src/lib/og-shared.tsx

Version 0.2.318

FIX: bundle public/Logos with OG image routes via outputFileTracingIncludes

May 6, 2026 at 7:59 PM GMT+0
cf7fa16
🐛Fixed
  • FIX: bundle public/Logos with OG image routes via outputFileTracingIncludes
  • The redesigned OG cards read the FullOut logo PNG with fs.readFile, but
  • the public/ directory isn't auto-traced into Vercel's serverless bundles.
  • Result: ENOENT on every entity OG render. Following the existing pattern
  • in this config (already used for /api/admin/.../scorecards and the cron
  • content routes) to explicitly include public/Logos for the four OG routes.

Version 0.2.317

ADJUST: bigger FullOut logo + Build Your Legacy tagline + higher contrast on OG cards

May 6, 2026 at 7:53 PM GMT+0
02a54b5
🔄Changed
  • ADJUST: bigger FullOut logo + Build Your Legacy tagline + higher contrast on OG cards
  • Per design feedback:
  • Replace the small text wordmark with the actual FullOut logo PNG
  • (read once per cold start from public/Logos and embedded as a base64
  • data URI so the renderer doesn't depend on a reachable host)
  • Add the "Build Your Legacy" tagline directly under the logo on every

Files Changed

Modified (5):
  • ~ src/app/gyms/[id]/opengraph-image.tsx
  • ~ src/app/opengraph-image.tsx
  • ~ src/app/people/[username]/opengraph-image.tsx
  • ~ src/app/teams/[id]/opengraph-image.tsx
  • ~ src/lib/og-shared.tsx

Version 0.2.316

FIX: drop explicit openGraph.images so file-based OG cards take effect

May 6, 2026 at 7:36 PM GMT+0
45a4dc1
🐛Fixed
  • FIX: drop explicit openGraph.images so file-based OG cards take effect
  • The new src/app/opengraph-image.tsx (brand) and
  • src/app/people/[username]/opengraph-image.tsx (profile) cards weren't
  • showing up because both pages set openGraph.images explicitly in their
  • generateMetadata, which beats the file-based metadata convention.
  • Removing the explicit array lets Next.js auto-attach the rendered PNGs.

Files Changed

Modified (2):
  • ~ src/app/page.tsx
  • ~ src/app/people/[username]/page.tsx

Version 0.2.315

ADD: branded opengraph-image cards for profiles, gyms, teams + brand fallback

May 6, 2026 at 7:29 PM GMT+0
0230b40
Added
  • ADD: branded opengraph-image cards for profiles, gyms, teams + brand fallback
  • Drops the one-off /build-your-legacy OG image and replaces it with a
  • cascading set:
  • src/app/opengraph-image.tsx — brand fallback (FullOut · Build Your
  • Legacy) used by every route that doesn't override it
  • src/app/people/[username]/opengraph-image.tsx — avatar + name + handle

Files Changed

Created (5):
  • + src/app/gyms/[id]/opengraph-image.tsx
  • + src/app/opengraph-image.tsx
  • + src/app/people/[username]/opengraph-image.tsx
  • + src/app/teams/[id]/opengraph-image.tsx
  • + src/lib/og-shared.tsx
Modified (6):
  • ~ src/app/build-your-legacy/opengraph-image.tsx
  • ~ src/app/gyms/[id]/opengraph-image.tsx
  • ~ src/app/opengraph-image.tsx
  • ~ src/app/people/[username]/opengraph-image.tsx
  • ~ src/app/teams/[id]/opengraph-image.tsx
  • ~ src/lib/og-shared.tsx

Version 0.2.314

ADD: opengraph-image.tsx for /build-your-legacy

May 6, 2026 at 7:12 PM GMT+0
47b0f05
Added
  • ADD: opengraph-image.tsx for /build-your-legacy
  • 1200x630 PNG generated from JSX via next/og, pulling the featured athlete
  • (currently @babygraham) from the DB. Auto-attached to the page via
  • Next.js metadata file convention, so any platform that scrapes the URL
  • (Slack, iMessage, Twitter, Discord, LinkedIn) shows a rich preview.
  • Cached for 1h. Directly downloadable at

Files Changed

Created (1):
  • + src/app/build-your-legacy/opengraph-image.tsx
Modified (1):
  • ~ src/app/build-your-legacy/opengraph-image.tsx

Version 0.2.313

FIX: escape apostrophes in referral admin + card so prod build passes

May 6, 2026 at 5:36 PM GMT+0
8472f37
🐛Fixed
  • FIX: escape apostrophes in referral admin + card so prod build passes
  • ESLint react/no-unescaped-entities was failing the build, blocking the
  • SKILLS+VERIFY deploy that fixes the prod 500s on every user page.

Files Changed

Modified (2):
  • ~ src/app/admin/referrals/page.tsx
  • ~ src/components/settings/referral-card.tsx

Version 0.2.312

SKILLS+VERIFY: rebuild skills system on USP rubric + ship FullOut Verified Phase 1+2

May 6, 2026 at 5:27 PM GMT+0
d557426
🔄Changed
  • SKILLS+VERIFY: rebuild skills system on USP rubric + ship FullOut Verified Phase 1+2
  • Replaces the hand-curated 77-skill catalog with a versioned-rubric foundation
  • so atomic skills survive when scoring orgs republish levels season-to-season.
  • Atomic skills are durable (Back Handspring is always Back Handspring); the
  • level/tier they earn at lives in LevelRubricEntry per (ScoringSystem × season),
  • so when USP shifts a skill in 2027-2028 we add new mapping rows without

Files Changed

Created (13):
  • + scripts/debug/check-rubric-dupes.ts
  • + scripts/import/import-usp-rubric.ts
  • + src/app/admin/verification-queue/page.tsx
  • + src/app/api/admin/verifiers/route.ts
  • + src/app/api/person/[id]/skills/[personSkillId]/verification/route.ts
  • + src/app/api/skills/route.ts
  • + src/app/api/verification/[attemptId]/decision/route.ts
  • + src/app/api/verification/[attemptId]/media/route.ts
  • + src/app/api/verification/[attemptId]/submit/route.ts
  • + src/app/people/[username]/skills/[personSkillId]/verify/page.tsx
  • + src/components/admin/verification-queue-client.tsx
  • + src/components/verification/verification-upload-client.tsx
  • + src/lib/verification.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/debug/check-rubric-dupes.ts
  • ~ scripts/import/import-usp-rubric.ts
  • ~ src/app/admin/page.tsx
  • ~ src/app/admin/verification-queue/page.tsx
  • ~ src/app/api/admin/verifiers/route.ts
  • ~ src/app/api/pdf/profile/[username]/route.tsx
  • ~ src/app/api/person/[id]/skills/[personSkillId]/route.ts
  • ~ src/app/api/person/[id]/skills/[personSkillId]/verification/route.ts
  • ~ src/app/api/person/[id]/skills/route.ts
  • ~ src/app/api/skills/route.ts
  • ~ src/app/api/verification/[attemptId]/decision/route.ts
  • ~ src/app/api/verification/[attemptId]/media/route.ts
  • ~ src/app/api/verification/[attemptId]/submit/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/[username]/skills/[personSkillId]/verify/page.tsx
  • ~ src/components/admin/verification-queue-client.tsx
  • ~ src/components/pdf/profile-pdf-document.tsx
  • ~ src/components/people/person-skills-manager.tsx
  • ~ src/components/showcase/showcase-profile-view.tsx

Version 0.2.311

AFFILIATE+REFERRAL: namespace campaign URLs, stackable referral months for everyone

May 6, 2026 at 5:01 PM GMT+0
bb98c0f
🔄Changed
  • AFFILIATE+REFERRAL: namespace campaign URLs, stackable referral months for everyone
  • Partner program
  • PartnerCampaign.code: drop global @unique, add @@unique([partnerId, code]).
  • Campaign URLs now live under the partner slug (?p=joe-rodgers/test-1)
  • so two partners can't collide on the same root code. Validate, track,
  • checkout, webhook, OG-metadata, referral, and admin paths all parse

Files Changed

Created (3):
  • + scripts/maintenance/build-partner-banners.ts
  • + src/app/admin/referrals/page.tsx
  • + src/lib/partner-code.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/build-partner-banners.ts
  • ~ src/app/admin/referrals/page.tsx
  • ~ src/app/api/admin/partners/[id]/campaigns/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/route.ts
  • ~ src/app/api/partner/dashboard/stats/route.ts
  • ~ src/app/api/partner/track/route.ts
  • ~ src/app/api/partner/validate/route.ts
  • ~ src/app/api/referral/apply/route.ts
  • ~ src/app/api/referral/route.ts
  • ~ src/app/api/referral/stats/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/settings/page.tsx
  • ~ src/app/subscribe/page.tsx
  • ~ src/components/partner/partner-banners.tsx
  • ~ src/components/partner/partner-campaigns.tsx
  • ~ src/components/partner/partner-dashboard.tsx
  • ~ src/components/settings/referral-card.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.310

FIX: desktop sidebar avatar disappearing in md-to-lg viewport range

May 6, 2026 at 3:20 PM GMT+0
547393f
🐛Fixed
  • FIX: desktop sidebar avatar disappearing in md-to-lg viewport range
  • Sidebar grid is 72px wide below lg even when expanded, but the avatar
  • block was using sidebarCollapsed alone to switch between small avatar
  • and full profile card — and the full card was gated on `hidden lg:block`.
  • Result: at md (768-1023px) with sidebar expanded, neither variant
  • rendered. Always render the small avatar when the sidebar column is

Files Changed

Modified (1):
  • ~ src/components/app-shell.tsx

Version 0.2.309

LEGAL: Children's Privacy Policy + COPPA-compliant signup with verifiable parental consent

May 6, 2026 at 3:14 PM GMT+0
2ada1fd
🔄Changed
  • LEGAL: Children's Privacy Policy + COPPA-compliant signup with verifiable parental consent
  • The previous flow had a self-attestation checkbox at upload time that does not
  • satisfy 16 CFR § 312.5(b) — under-13 PII was collectable based on the child
  • clicking 'my parent approves'. This commit closes that gap on the front end and
  • fills the entire § 312.4(d) notice obligation.
  • Front-end:

Files Changed

Created (6):
  • + src/app/api/auth/parent-consent/[token]/route.ts
  • + src/app/awaiting-parent-consent/page.tsx
  • + src/app/childrens-privacy/page.tsx
  • + src/app/parent-consent/[token]/page.tsx
  • + src/app/parent-consent/[token]/parent-consent-form.tsx
  • + src/lib/parent-consent.ts
Modified (12):
  • ~ prisma/schema.prisma
  • ~ src/app/api/auth/parent-consent/[token]/route.ts
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/awaiting-parent-consent/page.tsx
  • ~ src/app/childrens-privacy/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/app/parent-consent/[token]/page.tsx
  • ~ src/app/parent-consent/[token]/parent-consent-form.tsx
  • ~ src/app/privacy/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/app/terms/page.tsx
  • ~ src/lib/parent-consent.ts

Version 0.2.308

LEGAL: Children's Privacy Policy + COPPA-compliant signup with verifiable parental consent

May 6, 2026 at 3:30 PM GMT+0
66f6428
Added
  • Children's Privacy Policy at /childrens-privacy covering all 16 CFR § 312.4(d) notice elements: operator identification (FullOut LLC), what we collect from children, how we use it, third-party disclosure categories, written retention policy, persistent identifier handling, parental rights, and contact info.
  • Date-of-birth field on signup with under-13 branching: when the entered DOB indicates the user is under 13, the form asks for a parent or guardian's email instead of creating an account immediately, and the submit button reads 'Send approval request'.
  • Parental consent magic-link flow: under-13 signups create a ParentConsentRequest row instead of a User; the parent receives an email at the address they provided with a 7-day signed link to /parent-consent/[token] where they review the data practices, confirm parental status, accept the policy, and approve. On approval the User+Profile+Person are created in a single transaction with parentalConsentAt set and isPublic=false (private by default for under-13).
  • Awaiting-approval landing page at /awaiting-parent-consent for the child to see after they submit.
  • Footer 'Children's Privacy' link in src/app/layout.tsx between Privacy and Terms.
🔄Changed
  • Privacy Policy fully rewritten to be COPPA-honest: identifies FullOut LLC as the operator with full mailing address, phone, and team@fullout.energy email; replaces the prior 'we do not knowingly collect from children under 13' line (which was inaccurate given Mini/Youth profiles) with a pointer to the Children's Privacy Policy; documents specific service-provider categories (Vercel, Supabase, Mux, Stripe, Resend, Google Analytics); adds a written retention policy (active data while account exists, 30-day deletion, 90-day backup overwrite, 24-month log retention).
  • Terms of Service updated with age requirements (must be 13+ to self-register; under-13 profiles must be parent-created with verifiable consent), FullOut LLC entity block, and references to both privacy policies.
  • Register API now requires birthDate; for 13+ accounts the birthDate is stored on the Person record (previously not captured at signup).
🔒Security
  • Under-13 signups never create a User row until verifiable parental consent is recorded — the child's hashed password is held in ParentConsentRequest until approval and discarded if expired or denied.
  • Parent consent links expire in 7 days; expired links surface a clear error page rather than silently failing.
  • Re-using an already-approved or already-denied consent link shows a final-state page instead of letting it be replayed.

Files Changed

Modified (13):
  • ~ package.json
  • ~ prisma/schema.prisma
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/layout.tsx
  • ~ src/app/privacy/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/app/terms/page.tsx
  • ~ src/app/childrens-privacy/page.tsx
  • ~ src/app/awaiting-parent-consent/page.tsx
  • ~ src/app/parent-consent/[token]/page.tsx
  • ~ src/app/parent-consent/[token]/parent-consent-form.tsx
  • ~ src/app/api/auth/parent-consent/[token]/route.ts
  • ~ src/lib/parent-consent.ts

Version 0.2.307

UI: tighten radii globally + fix mobile overflow on gym page and post action bar

May 6, 2026 at 2:46 PM GMT+0
84d7d74
🔄Changed
  • UI: tighten radii globally + fix mobile overflow on gym page and post action bar
  • Drop the borderRadius scale from xl=24px/2xl=32px down to xl=8px/2xl=10px
  • across all rounded-* tokens so cards and surfaces feel less bubbly. Fix
  • gym page double-padding (was stacking px-4 over app-frame), kill the
  • overflow-x-auto wrapper that was masking long competition names, and
  • truncate the comp name link properly with flex-1 min-w-0. Hide

Files Changed

Modified (4):
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/components/gyms/gym-season-stats.tsx
  • ~ src/components/profile/media-report-button.tsx
  • ~ src/components/profile/media-share-buttons.tsx

Version 0.2.306

DATA: check in Worlds 2026 Finals scraper + importer (already run in prod)

May 5, 2026 at 2:30 PM GMT+0
4ff707c
Added
  • scripts/import/scrape-worlds-2026-results.ts: scrape the master Finals Score Ranking table from cheertheory.com/the-cheerleading-worlds-2026-finals-results/ and write data/inbox/worlds-2026-cheertheory-finals.json. The per-division sections higher on the page render scores inline (no <table>) so we deliberately parse only the master table.
  • scripts/import/import-worlds-2026-results.ts: idempotent importer for the Finals JSON. Maps rawDivision → canonical name to match the schedule importer's DIVISION_CODE_MAP, parses country suffix off team and program names, routes through the alias-aware gym/team matchers. Defaults to --dry-run; --execute writes; --reset wipes existing Finals rows for this competition only (scoped to (competitionId, round='Finals')).
  • Already run in prod — checking these in for posterity so the import path is reproducible.

Files Changed

Created (2):
  • + scripts/import/scrape-worlds-2026-results.ts
  • + scripts/import/import-worlds-2026-results.ts

Version 0.2.305

DATA: durable team-name dedupe — strip gym prefix on write + backfill

May 5, 2026 at 2:00 PM GMT+0
fd877f3
🔄Changed
  • New helper src/lib/teams/normalize-team-name.ts strips a leading gym-name prefix from a team name ("Cheer Athletics Panthers" at gym "Cheer Athletics" → "Panthers"). Comparison is case + punctuation insensitive ('Twist & Shout' == 'Twist and Shout'). Single-token gym names, mid-word matches, and brand-tail-only remainders (athletics/allstars/cheer/...) are guarded against to avoid corrupting names when the gym side itself is a stub.
  • src/lib/import/team-matcher.ts findOrCreateTeam now normalizes the incoming team name through the helper before computing the cache key + DB lookup, so dirty inputs hit the same canonical row instead of creating duplicates. Gym name is cached per gymId.
  • scripts/maintenance/normalize-team-names.ts backfills historical rows: rename in place when no sibling clash, otherwise merge the prefix-team into the cleaner sibling (re-point Performance/Deduction/ScheduleEntry FKs, handle unique-constraint collisions, delete the loser). Defaults to --dry-run; --execute writes. Scope with --gym-name= or --gym-id=. Stubs (team.name === gym.name) are intentionally skipped.

Files Changed

Created (2):
  • + src/lib/teams/normalize-team-name.ts
  • + scripts/maintenance/normalize-team-names.ts
Modified (1):
  • ~ src/lib/import/team-matcher.ts

Version 0.2.304

OPS: temporarily disable SMS notifications while we investigate volume

May 5, 2026 at 1:00 PM GMT+0
140fc34
🔄Changed
  • sendSms() in src/lib/sms.ts now short-circuits with a single console.warn and returns false when SMS_NOTIFICATIONS_DISABLED is true. Twilio client is not constructed; no outbound SMS leaves the app.
  • This is a hot-patch kill switch, not a config flag — flipping it back on is a one-line revert. Track the underlying volume investigation separately.

Files Changed

Modified (1):
  • ~ src/lib/sms.ts

Version 0.2.303

FIX: feed shows latest round per team-comp, sorted by when score actually landed

May 5, 2026 at 3:00 AM GMT+0
241b67c
🐛Fixed
  • Feed was showing Pumas' Summit Semi-Finals (97.27, 3rd) instead of Finals (97.58, 3rd). Cause: /api/feed sorted performances by Competition.date, which is identical for every round at a multi-day event, so Finals vs Semis was a non-deterministic tie and one round often got dropped from the page. The 'Xd ago' label was also the comp's start date, not when the score landed.
  • Switched the orderBy to scoreChangedAt → performedAt → Competition.date, widened the cursor filter to match, mapped the feed item createdAt to the same effective timestamp, and added per-(team, competition) dedup that keeps the latest round. Verified Summit data: 2253/2253 performances have scoreChangedAt populated, and Pumas Finals' scoreChangedAt is later than Semis' as expected.

Files Changed

Modified (1):
  • ~ src/app/api/feed/route.ts

Version 0.2.302

UI: clear nav search on pathname change + widen team stats breakpoint to xl

May 5, 2026 at 1:45 AM GMT+0
26b1bf4
🔄Changed
  • UI: clear nav search on pathname change + widen team stats breakpoint to xl
  • HomeSearch holds the previous query when the navbar persists across
  • client-side navigations (typing "lions" then clicking a result left
  • "lions" in the input). Reset query/results/open-state on pathname change.
  • TeamStatsStrip switches its mobile-stack→grid breakpoint from lg to xl
  • and adds whitespace-nowrap to label rows so multi-word stats don't wrap

Files Changed

Modified (2):
  • ~ src/components/home-search.tsx
  • ~ src/components/teams/team-stats-strip.tsx

Version 0.2.301

DATA: durable Division-name dedupe — normalize on write + consolidate existing dupes

May 5, 2026 at 1:12 AM GMT+0
6872835
🔄Changed
  • DATA: durable Division-name dedupe — normalize on write + consolidate existing dupes
  • Across ingest paths Division.name had accumulated 1,667 near-duplicate rows
  • that differed only by whitespace, dash style, or punctuation
  • ("L1 Youth - D2 - Medium - WC" vs "L1 Youth - D2 Medium - WC", "L4 U17 -" vs
  • "L4 - U17"). These bypassed @@unique([disciplineId, name]) and split single
  • competition divisions into multiple Division rows, which split team

Files Changed

Created (2):
  • + scripts/maintenance/consolidate-duplicate-divisions.ts
  • + src/lib/division-name.ts
Modified (3):
  • ~ scripts/maintenance/consolidate-duplicate-divisions.ts
  • ~ src/lib/division-name.ts
  • ~ src/lib/prisma.ts

Version 0.2.300

UI: team page — clickable Level/Age/Size chips, drop medal emoji, score-signature dedupe

May 4, 2026 at 10:18 PM GMT+0
41847e3
🔄Changed
  • UI: team page — clickable Level/Age/Size chips, drop medal emoji, score-signature dedupe
  • TeamHero now renders Level / Age / Size as individually clickable filter chips,
  • plus a combined Level Age Size badge that filters /teams by all three
  • PerformanceCard shows uniform numeric placement circles instead of trophy
  • emoji medals for top placements
  • Performance dedupe key drops round so identical placement+score+deductions at

Files Changed

Created (1):
  • + scripts/debug/find-duplicate-divisions.ts
Modified (4):
  • ~ scripts/debug/find-duplicate-divisions.ts
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/teams/performance-card.tsx
  • ~ src/components/teams/team-hero.tsx

Version 0.2.299

FIX: route scraped-score imports through alias-aware gym/team matchers

May 4, 2026 at 9:58 PM GMT+0
e97c6a7
🐛Fixed
  • FIX: route scraped-score imports through alias-aware gym/team matchers
  • The score-import pipeline (scripts/import/import-scraped-data.ts) had its
  • own naive findOrCreateGym/Team that did exact case-insensitive name
  • match and created a new row on miss — bypassing GymAlias entirely. So
  • every scrape after a gym merge would happily re-create the duplicate,
  • fragmenting the data we just consolidated.

Files Changed

Modified (1):
  • ~ scripts/import/import-scraped-data.ts

Version 0.2.298

DATA: merge Spirit of Texas Houston into Spirit of Texas

May 4, 2026 at 9:43 PM GMT+0
94d74d4
🔄Changed
  • DATA: merge Spirit of Texas Houston into Spirit of Texas
  • Two gym rows for the same All Star program in Houston, TX — one created
  • 2026-03-14 with the rich historical data (47 teams, 1018 perfs), one
  • created 2026-03-21 from a recent live-scrape import (18 teams, 42 perfs)
  • with the cleaner /gyms/spirit-of-texas slug. Merge preserves the slug
  • the user wants to keep while pulling all historical scoring/follow data

Files Changed

Created (2):
  • + scripts/debug/check-spirit-of-texas.ts
  • + scripts/maintenance/merge-gyms.ts
Modified (2):
  • ~ scripts/debug/check-spirit-of-texas.ts
  • ~ scripts/maintenance/merge-gyms.ts

Version 0.2.297

DATA: cleanup prefix-artifact team names in Woodlands Elite chain

May 4, 2026 at 9:32 PM GMT+0
68f7cb9
🔄Changed
  • DATA: cleanup prefix-artifact team names in Woodlands Elite chain
  • The CheerTheory importer strips "Gym - Team" prefixes correctly but the
  • live-scrape import path does not, so new All Star imports keep creating
  • teams named "Woodlands Elite - Black Ops" instead of "Black Ops". The
  • April 15 cleanup (commit f0660e4) handled the backlog at the time, and
  • 17 new artifacts have accumulated in the Woodlands Elite chain since.

Files Changed

Created (4):
  • + scripts/debug/audit-prefix-artifacts.ts
  • + scripts/debug/audit-woodlands-elite-prefixes.ts
  • + scripts/debug/check-we-team-names.ts
  • + scripts/maintenance/cleanup-prefixed-teams-in-chain.ts
Modified (4):
  • ~ scripts/debug/audit-prefix-artifacts.ts
  • ~ scripts/debug/audit-woodlands-elite-prefixes.ts
  • ~ scripts/debug/check-we-team-names.ts
  • ~ scripts/maintenance/cleanup-prefixed-teams-in-chain.ts

Version 0.2.296

UI: deterministic initials-avatar fallback when logo/photo missing

May 4, 2026 at 9:21 PM GMT+0
0550eb2
🔄Changed
  • UI: deterministic initials-avatar fallback when logo/photo missing
  • New <InitialsAvatar name src size /> in src/components/ui/. Renders the
  • image when src is set, otherwise a colored circle with name initials.
  • Background hue is a deterministic hash of name, so the same brand
  • lands the same color across pages.
  • Replaced six bare-icon placeholders (Building2/Users/GraduationCap/

Files Changed

Created (2):
  • + scripts/maintenance/backfill-woodlands-elite-logo.ts
  • + src/components/ui/initials-avatar.tsx
Modified (4):
  • ~ scripts/maintenance/backfill-woodlands-elite-logo.ts
  • ~ src/app/discover/page.tsx
  • ~ src/components/discover/sortable-tables.tsx
  • ~ src/components/ui/initials-avatar.tsx

Version 0.2.295

UI: show gym + round on feed performance cards

May 4, 2026 at 9:20 PM GMT+0
4016b7f
🔄Changed
  • UI: show gym + round on feed performance cards

Files Changed

Modified (3):
  • ~ src/app/api/feed/route.ts
  • ~ src/app/home/page.tsx
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.294

UI: smarter discover-page ranking — follow-boost, starts-with, quality tiebreakers

May 4, 2026 at 9:12 PM GMT+0
3a5a6df
🔄Changed
  • UI: smarter discover-page ranking — follow-boost, starts-with, quality tiebreakers
  • Discover-page results were effectively alphabetical because trigram
  • similarity ties (every "Wild..." team scored the same) had no useful
  • secondary sort. Apply the same boost pattern shipped to the typeahead,
  • plus a starts-with bonus and per-type quality tiebreakers.
  • Discover ORDER BY layers (per entity type):

Files Changed

Modified (2):
  • ~ src/app/api/search/route.ts
  • ~ src/app/discover/page.tsx

Version 0.2.293

UI: tighten feed card radius; fix avatar fallback for non-letter usernames

May 4, 2026 at 9:07 PM GMT+0
33c1874
🔄Changed
  • UI: tighten feed card radius; fix avatar fallback for non-letter usernames

Files Changed

Modified (2):
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.292

UI: smarter search — follow-boost, follows-on-focus, substring highlight

May 4, 2026 at 8:54 PM GMT+0
f5b8b38
🔄Changed
  • UI: smarter search — follow-boost, follows-on-focus, substring highlight
  • /api/search now boosts followed entities in ORDER BY. Teams whose gym
  • you follow outrank unfollowed teams of equal similarity; directly-
  • followed teams outrank same-gym matches. Anonymous users see no boost
  • (empty arrays make ANY('{}'::text[]) a no-op).
  • Empty query returns the 24 most-recent follows (gyms, teams, people,

Files Changed

Modified (3):
  • ~ src/app/api/search/route.ts
  • ~ src/components/home-search.tsx
  • ~ src/components/navbar.tsx

Version 0.2.290

UI: hide stray feed-tabs scrollbar; unify feed card style across breakpoints

May 4, 2026 at 8:47 PM GMT+0
93707c4
🔄Changed
  • UI: hide stray feed-tabs scrollbar; unify feed card style across breakpoints

Files Changed

Modified (2):
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/feed-tabs-nav.tsx

Version 0.2.289

UI: show rank in performance trends tooltips (gym + team pages)

May 4, 2026 at 8:37 PM GMT+0
3d258c5
🔄Changed
  • UI: show rank in performance trends tooltips (gym + team pages)

Files Changed

Modified (6):
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/gyms/gym-ps-chart.tsx
  • ~ src/components/my-teams/single-team-analysis.tsx
  • ~ src/components/teams/team-ps-chart.tsx
  • ~ src/types/charts.ts

Version 0.2.288

UI: surface division + placement on /home performance cards, link to division group page

May 4, 2026 at 8:37 PM GMT+0
f85db28
🔄Changed
  • UI: surface division + placement on /home performance cards, link to division group page
  • Pull Division (with slug + display fields) and Performance.placement into
  • the home feed query (both server-render in app/home/page.tsx and the
  • infinite-scroll API in app/api/feed/route.ts) and pre-compute a
  • divisionHref on each performance feed item.
  • Performance cards now show the division name as a third subtitle line and

Files Changed

Modified (3):
  • ~ src/app/api/feed/route.ts
  • ~ src/app/home/page.tsx
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.287

DEBUG: add paid-tier audit script

May 4, 2026 at 8:02 PM GMT+0
3bf4de9
🐛Fixed
  • DEBUG: add paid-tier audit script
  • scripts/debug/audit-paid-tier-users.ts groups users by subscriptionTier
  • and lists every paid-tier account with its role, Stripe state, and most
  • recent Subscription row. Used to verify admin-driven tier flips after
  • the auth.ts session-refresh fix.

Files Changed

Created (1):
  • + scripts/debug/audit-paid-tier-users.ts
Modified (1):
  • ~ scripts/debug/audit-paid-tier-users.ts

Version 0.2.286

FIX: resumable + hash-skipped imports so live events update fast

May 4, 2026 at 7:58 PM GMT+0
cfad39f
🐛Fixed
  • FIX: resumable + hash-skipped imports so live events update fast
  • The Summit (220 divisions, 2145 teams) couldn't finish a full import in
  • the live-monitor cron's 5-min maxDuration. Status never flipped to
  • COMPLETED, the next tick re-imported from scratch, and the loop never
  • made progress — Finals from May 4 never reached the DB.
  • Two changes, one chokepoint:

Files Changed

Created (1):
  • + scripts/maintenance/unstick-import-jobs.ts
Modified (4):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/unstick-import-jobs.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/live-monitor.ts

Version 0.2.285

UI: cleanup competition page — collapsibles, rank numbers, Insights tab

May 4, 2026 at 7:58 PM GMT+0
88feb02
🔄Changed
  • UI: cleanup competition page — collapsibles, rank numbers, Insights tab
  • My Teams & Gyms: card and each gym row now collapsible via native
  • <details>; gym rows default closed and toggle on click (no longer
  • navigates to gym page).
  • Division cards: replace medal emojis with #1/#2/#3 rank numbers; #1
  • renders bold in primary color. Show all divisions per level (drop the

Files Changed

Modified (3):
  • ~ src/components/competitions/competition-tabs.tsx
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/components/competitions/my-follows-at-competition.tsx

Version 0.2.284

UI: align navbar bottom border with page content shell

May 4, 2026 at 7:57 PM GMT+0
a4b4194
🔄Changed
  • UI: align navbar bottom border with page content shell
  • Move border-b from the full-width <header> onto an inner div sitting
  • inside the app-frame's 12px gutter so the navbar's visible bottom line
  • ends at the same horizontal extent as the sticky profile header, the
  • profile card, and the photo feed below. Background stays edge-to-edge
  • so the iOS status-bar area still renders consistently.

Files Changed

Modified (1):
  • ~ src/components/navbar.tsx

Version 0.2.283

FIX: admin tier changes ignored until user re-logs in

May 4, 2026 at 7:42 PM GMT+0
269298b
🐛Fixed
  • FIX: admin tier changes ignored until user re-logs in
  • Session callback was overlaying token.subscriptionTier and token.role
  • into the session without ever refreshing them from the User row. So
  • when an admin updated a user's tier in /admin/users, the User.subscriptionTier
  • column flipped correctly, but the user's existing JWT still carried the
  • old value. Every paywalled page reads session.user.subscriptionTier, so

Files Changed

Created (1):
  • + scripts/debug/check-graham-tier.ts
Modified (2):
  • ~ scripts/debug/check-graham-tier.ts
  • ~ src/lib/auth.ts

Version 0.2.282

FIX: live-scores feed showing stale rows as "1m ago"

May 4, 2026 at 6:17 PM GMT+0
7d52e26
🐛Fixed
  • FIX: live-scores feed showing stale rows as "1m ago"
  • The feed was sorting by Performance.updatedAt, which Prisma bumps on any
  • row touch. The live-monitor cron's 5-min function timeout was killing
  • the post-import status flip on large events, so every minute it
  • re-imported the same SCRAPE_COMPLETE Summit job, bumping updatedAt on
  • 1500+ unchanged rows. The user saw 4-day-old scores marked "1m ago".

Files Changed

Created (4):
  • + scripts/debug/check-live-scores-staleness.ts
  • + scripts/debug/check-score-changed-at.ts
  • + scripts/maintenance/backfill-score-changed-at.ts
  • + scripts/maintenance/install-score-changed-at-triggers.ts
Modified (11):
  • ~ prisma/schema.prisma
  • ~ scripts/debug/check-live-scores-staleness.ts
  • ~ scripts/debug/check-score-changed-at.ts
  • ~ scripts/maintenance/backfill-score-changed-at.ts
  • ~ scripts/maintenance/install-score-changed-at-triggers.ts
  • ~ src/app/api/live-scores/route.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/live/page.tsx
  • ~ src/lib/import/index.ts
  • ~ src/lib/live-monitor.ts
  • ~ src/lib/live-score-order.ts

Version 0.2.280

FIX: move iOS-zoom @media block out of @layer base

May 4, 2026 at 5:59 PM GMT+0
1eac475
🐛Fixed
  • FIX: move iOS-zoom @media block out of @layer base
  • Nesting @media inside @layer base appears to have broken Tailwind/PostCSS
  • compilation, causing the page to render as unstyled HTML. Move the rule
  • to the top level of globals.css where it's processed independently.

Files Changed

Modified (1):
  • ~ src/app/globals.css

Version 0.2.279

UI: add "My Teams & Gyms" panel to competition page

May 4, 2026 at 5:57 PM GMT+0
e047bf5
🔄Changed
  • UI: add "My Teams & Gyms" panel to competition page
  • Shows followed teams and gyms performing at the competition, grouped
  • by gym → team → rounds, above the Division Winners chart. Followed-gym
  • includes all of that gym's teams at the comp; followed-team is shown
  • on its own under its gym. Each team lists every round it competed
  • (Prelims/Semis/Finals/etc.) with final score and placement; #1

Files Changed

Created (2):
  • + scripts/debug/check-summit-rounds.ts
  • + src/components/competitions/my-follows-at-competition.tsx
Modified (3):
  • ~ scripts/debug/check-summit-rounds.ts
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/components/competitions/my-follows-at-competition.tsx

Version 0.2.278

FIX: iOS Safari auto-zooming on input focus

May 4, 2026 at 5:57 PM GMT+0
97f3f35
🐛Fixed
  • FIX: iOS Safari auto-zooming on input focus
  • Force inputs/textareas/selects to 16px on viewports <=768px so iOS doesn't
  • zoom in when focusing the search box and other small inputs.

Files Changed

Modified (1):
  • ~ src/app/globals.css

Version 0.2.277

FIX: team cards on /discover missing logo when gym only has photoUrl

April 24, 2026 at 8:44 PM GMT+0
70a2957
🐛Fixed
  • FIX: team cards on /discover missing logo when gym only has photoUrl
  • Team query SELECT'd g."logoUrl" but not g."photoUrl", so the
  • team.gymLogoUrl fallback was null for gyms with only photoUrl set
  • (e.g. Cheer Athletics - Frisco → NovaCats).
  • Added g."photoUrl" AS "gymPhotoUrl" to the query, extended TeamResult
  • + TeamRow types, and appended gymPhotoUrl to the fallback chain in

Files Changed

Modified (2):
  • ~ src/app/discover/page.tsx
  • ~ src/components/discover/sortable-tables.tsx

Version 0.2.276

FIX: competition page showing Prelims when Finals have scored

April 24, 2026 at 8:19 PM GMT+0
7744c8b
🐛Fixed
  • FIX: competition page showing Prelims when Finals have scored
  • User reported Youth Summit 2026 competition overview showing Prelims
  • for L3 Youth - Medium even though Finals had landed in the DB with
  • real placements + scores. Division detail page was correct.
  • Root cause in src/components/competitions/divisions-tab.tsx: the round
  • picker filtered out any performance whose performedAt was in the future

Files Changed

Modified (1):
  • ~ src/components/competitions/divisions-tab.tsx

Version 0.2.275

FIX: Varsity scraper dropping Finals for divisions with Prelims

April 24, 2026 at 7:48 PM GMT+0
ca9a488
🐛Fixed
  • FIX: Varsity scraper dropping Finals for divisions with Prelims
  • User reported Finals visible on Varsity TV but missing from competition
  • pages. Investigation on Youth Summit 2026: 46 of 54 divisions had only
  • Prelims, 7 had both rounds, 1 had only Finals. Scraper ran 18 times today
  • and completed cleanly every time — Finals were being fetched from Varsity
  • and then thrown away.

Files Changed

Created (1):
  • + python-scraper/tests/test_division_merge_key.py
Modified (2):
  • ~ python-scraper/scraper/varsity_api_scraper.py
  • ~ python-scraper/tests/test_division_merge_key.py

Version 0.2.274

FIX: Varsity scraper was dropping Finals for divisions that also had Prelims

April 24, 2026 at 7:55 PM GMT+0
3ba94af
🐛Fixed
  • Youth Summit 2026 and similar live events were missing Finals rounds
  • on most divisions (46 of 54 Prelims-only, only 7 with both rounds).
  • Root cause was in the Python scraper's filter-sweep merge step: when
  • Varsity TV's results endpoint is queried with a roundName facet, it
  • often returns a record whose name field has been stripped of the
  • round suffix, so a Prelims query and a Finals query produce records
  • with identical names. The four merge sites in varsity_api_scraper.py
  • all keyed on the raw name, collapsing the two records into one via
  • choose_preferred_division — which prefers team count, so Prelims
  • (larger field) always won and Finals were silently dropped.
🔄Changed
  • python-scraper/scraper/varsity_api_scraper.py: new division_merge_key()
  • helper keys on (base_name, round_label); all four merge sites now use
  • it so Prelims and Finals survive as distinct records.
  • python-scraper/tests/test_division_merge_key.py: 9 unit tests locking
  • in the round-preservation invariant.

Files Changed

Modified (2):
  • ~ python-scraper/scraper/varsity_api_scraper.py
  • ~ python-scraper/tests/test_division_merge_key.py

Version 0.2.272

FIX: canonicalize Division.level at the write layer (Youth Summit 2026)

April 24, 2026 at 7:40 PM GMT+0
1d46473
🐛Fixed
  • Competition pages were splitting a single level (e.g. L2) into two
  • separate headers when some divisions had been imported as 'Level 2'
  • and others as 'L2'. Most visible on Youth Summit 2026, which showed
  • only 2 of 16 L2 divisions under the 'Level 2' heading. 2,455 rows
  • across the whole DB had non-canonical level strings (Level 1-7).
🔄Changed
  • src/lib/division-level.ts: new canonical normalizeLevel() utility.
  • src/lib/prisma.ts: Prisma client $extends hook routes every
  • division.create/createMany/update/updateMany/upsert through
  • normalizeLevel so no import path can write a non-canonical value.
  • src/components/competitions/divisions-tab.tsx: normalizes at grouping
  • as defense-in-depth.
  • scripts/maintenance/normalize-division-levels.ts: idempotent backfill
  • (ran once to clean up 2,455 historical rows).

Files Changed

Modified (8):
  • ~ src/lib/division-level.ts
  • ~ src/lib/__tests__/division-level.test.ts
  • ~ src/lib/prisma.ts
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ scripts/maintenance/normalize-division-levels.ts
  • ~ scripts/debug/smoke-test-level-extension.ts
  • ~ CLAUDE.md
  • ~ tasks/lessons.md

Version 0.2.271

FIX: live-monitor now harvests SCRAPE_COMPLETE jobs (admin-sync race)

April 23, 2026 at 9:54 PM GMT+0
db7186c
🐛Fixed
  • FIX: live-monitor now harvests SCRAPE_COMPLETE jobs (admin-sync race)
  • The admin scraper dashboard polls /api/admin/scraper/jobs every 10s
  • whenever an admin has the page open, and its sync function flips any
  • SCRAPING row whose Python work is done to SCRAPE_COMPLETE. Because
  • live-monitor Phase 1 only harvested jobs with status="SCRAPING", any
  • scrape the admin path caught first got stuck forever — Python finished,

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.270

LIVE: tighten live-monitor cadence to 10 min (was 45 min)

April 23, 2026 at 6:07 PM GMT+0
8d2d622
🔄Changed
  • LIVE: tighten live-monitor cadence to 10 min (was 45 min)
  • Competitions in their live window are now re-scraped every 10 minutes
  • instead of every 45. Also split "in-flight" from "recently completed"
  • checks so the tighter cadence can't stack duplicate scrapes on the same
  • event while one is still running — STALE_JOB_THRESHOLD_MS (45 min)
  • still reclaims truly stuck jobs.

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.269

LIVE: tighten live-monitor cadence to 10 min (was 45 min)

April 23, 2026 at 6:06 PM GMT+0
b90cad9
🔄Changed
  • LIVE: tighten live-monitor cadence to 10 min (was 45 min)
  • Competitions in their live window are now re-scraped every 10 minutes
  • instead of every 45. Also split "in-flight" from "recently completed"
  • checks so the tighter cadence can't stack duplicate scrapes on the same
  • event while one is still running — STALE_JOB_THRESHOLD_MS (45 min)
  • still reclaims truly stuck jobs.

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.267

DOCS: consolidate brand positioning across overview + brand guide

April 23, 2026 at 1:19 AM GMT+0
9fc394b
🔄Changed
  • DOCS: consolidate brand positioning across overview + brand guide
  • Rewrite FULLOUT_COMPANY_OVERVIEW.md to align with media-company + athlete-first positioning, drop the phantom 4th tier, and use Prep/Elite/Pro naming. Fix stray "Novice" tier references in brand-guide.md and upgrade-prompt-audit.md to match live /pricing.

Version 0.2.266

FIX: guard against session.user.id=undefined in dashboard layout

April 22, 2026 at 6:36 PM GMT+0
918dc1c
🐛Fixed
  • FIX: guard against session.user.id=undefined in dashboard layout
  • Prod logs showed "Invalid prisma.user.findUnique() invocation: where.id=undefined"
  • on GET /home when a session existed without an id. Tightening the guard from
  • session?.user to session?.user?.id redirects those requests to /login instead.

Files Changed

Modified (1):
  • ~ src/app/dashboard/layout.tsx

Version 0.2.265

DATA: strip "TBD" prefix from competition names at all ingest + display paths

April 22, 2026 at 6:21 PM GMT+0
07b7440
🔄Changed
  • DATA: strip "TBD" prefix from competition names at all ingest + display paths
  • Varsity event listings sometimes use a "TBD" placeholder prefix for unfinalized
  • event titles (e.g. "TBDThe U.S. Finals Worcester"). Only the schedule-intake
  • route was sanitizing it — auto-discover, bulk-scrape, and rescrape-orchestrator
  • all wrote raw titles. Now all three run parseEventName(), the /competitions and
  • /competitions/browse pages scrub names on render, and the fix-competition-names

Files Changed

Modified (6):
  • ~ scripts/fix-competition-names.ts
  • ~ src/app/competitions/browse/page.tsx
  • ~ src/app/competitions/page.tsx
  • ~ src/lib/auto-discover.ts
  • ~ src/lib/bulk-scrape.ts
  • ~ src/lib/rescrape-orchestrator.ts

Version 0.2.264

DATA: audit + merge 19 duplicate gyms created by STUNT import

April 22, 2026 at 5:35 PM GMT+0
1b92bdc
Added
  • DATA: audit + merge 19 duplicate gyms created by STUNT import
  • The 2026-04-20 STUNT import created new gym records for entities that
  • already existed (e.g. "Cheer Athletics Frisco" vs "Cheer Athletics -
  • Frisco", Purdue × 2, UT × 2, etc.). scripts/debug/stunt-audit.ts tiers
  • candidates by normalized-name + city/state match; scripts/maintenance/
  • merge-stunt-gyms.ts moves all 15 gym FK references from dupe → canonical

Files Changed

Created (8):
  • + scripts/debug/inspect-failed-merges.ts
  • + scripts/debug/list-gym-fks.ts
  • + scripts/debug/stunt-audit.ts
  • + scripts/debug/verify-all-merges.ts
  • + scripts/debug/verify-frisco-merge.ts
  • + scripts/maintenance/create-gemini-team.ts
  • + scripts/maintenance/merge-stunt-gyms.ts
  • + scripts/maintenance/update-ca-frisco-stunt.ts
Modified (8):
  • ~ scripts/debug/inspect-failed-merges.ts
  • ~ scripts/debug/list-gym-fks.ts
  • ~ scripts/debug/stunt-audit.ts
  • ~ scripts/debug/verify-all-merges.ts
  • ~ scripts/debug/verify-frisco-merge.ts
  • ~ scripts/maintenance/create-gemini-team.ts
  • ~ scripts/maintenance/merge-stunt-gyms.ts
  • ~ scripts/maintenance/update-ca-frisco-stunt.ts

Version 0.2.263

UI: consolidate /search + /explore + /discover into single search page

April 22, 2026 at 5:34 PM GMT+0
6982286
🔄Changed
  • UI: consolidate /search + /explore + /discover into single search page
  • /discover now hosts the full search experience: trigram + normalized-ILIKE
  • matching (fixes "cheer athletic plano" returning no results), tabs with
  • counts, grid/table view toggle with sortable table columns, claim banner,
  • and category cards as the empty state. /search and /explore became 301
  • redirects. Updated all callers (home autocomplete, landing hero, mobile

Files Changed

Created (1):
  • + src/components/discover/sortable-tables.tsx
Modified (10):
  • ~ src/app/discover/page.tsx
  • ~ src/app/explore/page.tsx
  • ~ src/app/search/page.tsx
  • ~ src/components/dashboard/dashboard-shell.tsx
  • ~ src/components/discover/sortable-tables.tsx
  • ~ src/components/explore/explore-results.tsx
  • ~ src/components/explore/explore-view-toggle.tsx
  • ~ src/components/explore/results-per-page-selector.tsx
  • ~ src/components/home-search.tsx
  • ~ src/components/landing/landing-search.tsx

Version 0.2.262

PCL: add International Cheer + NBA disciplines, link national teams

April 22, 2026 at 2:33 PM GMT+0
a5e86bb
🔄Changed
  • PCL: add International Cheer + NBA disciplines, link national teams
  • Two new disciplines for PCL athletes' non-all-star/college experiences:
  • international_cheer (USA Cheer Coed Premier, All Girl Premier,
  • National Team — Anuhea Keene, Maddie Hayes, Kollin Cockrell, Ryan
  • Claunch, Hailey Smith, Sahanna Doherty, James Thomas, Anuhea Keene)
  • nba (Utah Jazz Stunt Team — Kollin Cockrell, Hailey Smith)

Files Changed

Created (1):
  • + scripts/setup/link-pcl-national-teams.ts
Modified (3):
  • ~ scripts/setup/backfill-pcl-gym-logos.ts
  • ~ scripts/setup/link-pcl-national-teams.ts
  • ~ src/lib/disciplines/registry.ts

Version 0.2.261

PCL: backfill gym/team logos and create missing program stubs

April 22, 2026 at 2:17 PM GMT+0
ba5f1e6
Added
  • PCL: backfill gym/team logos and create missing program stubs
  • backfill-pcl-gym-logos.ts gains throttling + Wikimedia PNG-thumb URLs
  • (Supabase bucket rejects image/svg+xml). Pulled 12 college logos
  • (Navarro, TX Tech, Kennesaw, UCF, UWG, Louisville, Morehead State,
  • Troy, Sam Houston, Eastern Michigan, UGA, Weber State, Lindenwood)
  • plus 3 program logos (Southwestern Christian, Twist & Shout,

Files Changed

Created (2):
  • + scripts/setup/create-missing-pcl-gyms.ts
  • + scripts/setup/propagate-team-logos-from-gyms.ts
Modified (3):
  • ~ scripts/setup/backfill-pcl-gym-logos.ts
  • ~ scripts/setup/create-missing-pcl-gyms.ts
  • ~ scripts/setup/propagate-team-logos-from-gyms.ts

Version 0.2.260

PCL: link athlete experiences to real gym/team IDs

April 22, 2026 at 2:06 PM GMT+0
d5a888c
🔄Changed
  • PCL: link athlete experiences to real gym/team IDs
  • Resolved 88% of PCL athletes' historical PersonExperience rows
  • (224 / 255 gym links, 174 / 255 team links). Previously all rows had
  • \`manualGymName\` / \`manualTeamName\` strings only — so PCL pros never
  • showed up on their former gym/team pages.
  • scripts/setup/link-pcl-gyms-teams.ts — manual rule table for the messy

Files Changed

Created (13):
  • + scripts/debug/audit-pcl-experiences.ts
  • + scripts/debug/audit-pcl-final.ts
  • + scripts/debug/audit-pcl-photos.ts
  • + scripts/debug/check-caleb-henderson.ts
  • + scripts/debug/check-existing-gym-photos.ts
  • + scripts/debug/find-pcl-teams.ts
  • + scripts/debug/list-pcl-gym-teams.ts
  • + scripts/debug/match-pcl-gyms.ts
  • + scripts/debug/revert-bad-navarro-match.ts
  • + scripts/debug/show-navarro.ts
  • + scripts/debug/show-pcl-person.ts
  • + scripts/setup/backfill-pcl-gym-logos.ts
  • + scripts/setup/link-pcl-gyms-teams.ts
Modified (13):
  • ~ scripts/debug/audit-pcl-experiences.ts
  • ~ scripts/debug/audit-pcl-final.ts
  • ~ scripts/debug/audit-pcl-photos.ts
  • ~ scripts/debug/check-caleb-henderson.ts
  • ~ scripts/debug/check-existing-gym-photos.ts
  • ~ scripts/debug/find-pcl-teams.ts
  • ~ scripts/debug/list-pcl-gym-teams.ts
  • ~ scripts/debug/match-pcl-gyms.ts
  • ~ scripts/debug/revert-bad-navarro-match.ts
  • ~ scripts/debug/show-navarro.ts
  • ~ scripts/debug/show-pcl-person.ts
  • ~ scripts/setup/backfill-pcl-gym-logos.ts
  • ~ scripts/setup/link-pcl-gyms-teams.ts

Version 0.2.259

UI: add /gyms/[id]/athletes + /teams/[id]/athletes roster pages

April 22, 2026 at 2:06 PM GMT+0
99c533d
🔄Changed
  • UI: add /gyms/[id]/athletes + /teams/[id]/athletes roster pages
  • The compact sidebar's "View all" link was pointing at an #athletes
  • anchor that didn't exist on desktop, so historical athletes (PCL pros
  • whose tenure was years ago) had no way to surface — the season filter
  • hid them and there was no full-roster view to fall back on.
  • New AthleteRosterBrowser with search, season filter, and sort

Files Changed

Created (3):
  • + src/app/gyms/[id]/athletes/page.tsx
  • + src/app/teams/[id]/athletes/page.tsx
  • + src/components/athletes/athlete-roster-browser.tsx
Modified (5):
  • ~ src/app/gyms/[id]/athletes/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/athletes/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/athletes/athlete-roster-browser.tsx

Version 0.2.258

UI: render discipline badges across search, team listings, gym rosters, and athlete profiles

April 22, 2026 at 3:06 AM GMT+0
465d760
🔄Changed
  • UI: render discipline badges across search, team listings, gym rosters, and athlete profiles
  • Teams carry their own Team.disciplineId; athletes aggregate disciplines from
  • their team history (PersonExperience + PersonTeamTimeline) so multi-discipline
  • pros — e.g. PCL players with All Star and College history — surface all three
  • badges side-by-side. Wave 1 covers the home search dropdown and athlete profile
  • header; Wave 2 covers /teams grid + list views and the gym page team roster.

Files Changed

Modified (7):
  • ~ src/app/api/search/route.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/teams/page.tsx
  • ~ src/components/gyms/gym-teams-section.tsx
  • ~ src/components/home-search.tsx
  • ~ src/components/profile/profile-card-clean.tsx

Version 0.2.257

PERF: speed up schedule filters by removing nested Division where-clauses

April 22, 2026 at 12:31 AM GMT+0
d4c792e
🔄Changed
  • PERF: speed up schedule filters by removing nested Division where-clauses
  • The /competitions/[id]/schedule filters were slow because both API routes
  • used `where.Division = {...}`, which CLAUDE.md flags as generating slow
  • correlated subqueries through PgBouncer (~15x slower). filter-options
  • also re-scanned every entry with a Division JOIN on each filter click
  • (300ms debounced), and the SSR page re-derived sessions/dates from a

Files Changed

Created (1):
  • + src/lib/schedule-division-filter.ts
Modified (4):
  • ~ src/app/api/competitions/[id]/schedule/entries/route.ts
  • ~ src/app/api/competitions/[id]/schedule/filter-options/route.ts
  • ~ src/app/competitions/[id]/schedule/page.tsx
  • ~ src/lib/schedule-division-filter.ts

Version 0.2.256

STUNT: import Youth Summit 2026 schedule (551 performances)

April 22, 2026 at 12:01 AM GMT+0
e7d8a61
🔄Changed
  • STUNT: import Youth Summit 2026 schedule (551 performances)
  • Parse Varsity PDF performance order and insert CompetitionSchedule +
  • ScheduleEntry rows for youth-summit-2026. Thursday, April 23 is split
  • across West/Central/East Hall (179/181/191 entries). Friday finals are
  • skipped — they are blank bracket slots in the source PDF.
  • Match rates: 551/551 divisions, 545/551 gyms, 148 teams exact-matched.

Files Changed

Created (1):
  • + scripts/import/import-youth-summit-2026-schedule.ts
Modified (1):
  • ~ scripts/import/import-youth-summit-2026-schedule.ts

Version 0.2.255

STUNT: import 849 PSAL HS matches with point scores (2015-2026)

April 21, 2026 at 4:12 PM GMT+0
d4a775c
🔄Changed
  • STUNT: import 849 PSAL HS matches with point scores (2015-2026)
  • Reverse-engineered PSAL's WCF JSON service at /SportDisplay.svc — same
  • API the team-standings.aspx page uses. Bootstrap session by GETting any
  • public PSAL page (cookies set automatically), then call:
  • GetSportLeague?csports='069'&season='YYYY' (find STUNT leagues per year)
  • getTeamScheduleAny?csports='069'&season=YYYY&schoolid='XXXXX'

Files Changed

Created (5):
  • + scripts/debug/analyze-psal-data.ts
  • + scripts/debug/count-psal-imports.ts
  • + scripts/import/import-psal-stunt.ts
  • + scripts/maintenance/dedupe-psal-matches.ts
  • + scripts/scrape/scrape-psal-stunt.ts
Modified (5):
  • ~ scripts/debug/analyze-psal-data.ts
  • ~ scripts/debug/count-psal-imports.ts
  • ~ scripts/import/import-psal-stunt.ts
  • ~ scripts/maintenance/dedupe-psal-matches.ts
  • ~ scripts/scrape/scrape-psal-stunt.ts

Version 0.2.254

UI: fix unreadable gym popup on /gyms map

April 21, 2026 at 3:18 PM GMT+0
bdefa9f
🔄Changed
  • UI: fix unreadable gym popup on /gyms map
  • The global maplibre popup override strips background/padding for the dark
  • theme, so the gyms-map popup's dark text rendered invisible on the dark
  • basemap. Wrap the popup content in a dark card with light text, matching
  • the density map treatment.

Files Changed

Modified (1):
  • ~ src/components/gyms/gyms-map.tsx

Version 0.2.253

STUNT: import 5 historical club championship finals (2022-2024)

April 20, 2026 at 2:09 PM GMT+0
35ebc72
🔄Changed
  • STUNT: import 5 historical club championship finals (2022-2024)
  • From stuntthesport.org/club-team-rankings/ "Club STUNT Championship
  • History" table (10 rows = 5 finals × 2 teams each).
  • Covered:
  • 2024 West Coast Regional (18U + 14U)
  • 2023 West Coast Regional (18U + 14U)

Files Changed

Created (3):
  • + scripts/debug/find-similar-names.ts
  • + scripts/debug/show-club-championships.ts
  • + scripts/import/import-club-championship-history.ts
Modified (3):
  • ~ scripts/debug/find-similar-names.ts
  • ~ scripts/debug/show-club-championships.ts
  • ~ scripts/import/import-club-championship-history.ts

Version 0.2.252

PROFILE: build Chris Muniz athlete/coach profile + career history

April 20, 2026 at 2:00 PM GMT+0
e1885a6
🔄Changed
  • PROFILE: build Chris Muniz athlete/coach profile + career history
  • Person record @roostermuniz with 24 PersonExperience rows covering
  • 1999-2019 career arc (Cheer Athletics Plano, TVCC, U of Houston,
  • GymTyme, PowerHouse Belton, World Cup Freehold, + 4 historical gyms
  • created: Texas Air Force, Cheer Nation, Texas Lonestar teams).
  • Also materializes 30 Performance records across 16 newly-created

Files Changed

Created (6):
  • + scripts/setup/build-chris-muniz-performances.ts
  • + scripts/setup/build-chris-muniz-profile.ts
  • + scripts/setup/create-chris-muniz-missing-orgs.ts
  • + scripts/setup/fix-chris-muniz-team-links.ts
  • + scripts/setup/fix-powerhouse-worldcup-dupes.ts
  • + scripts/setup/upload-chris-muniz-photo.ts
Modified (6):
  • ~ scripts/setup/build-chris-muniz-performances.ts
  • ~ scripts/setup/build-chris-muniz-profile.ts
  • ~ scripts/setup/create-chris-muniz-missing-orgs.ts
  • ~ scripts/setup/fix-chris-muniz-team-links.ts
  • ~ scripts/setup/fix-powerhouse-worldcup-dupes.ts
  • ~ scripts/setup/upload-chris-muniz-photo.ts

Version 0.2.251

STUNT: import 2025 Youth Club Nationals brackets (22 matches)

April 20, 2026 at 12:19 AM GMT+0
6887486
🔄Changed
  • STUNT: import 2025 Youth Club Nationals brackets (22 matches)
  • Scraped via Playwright MCP from stuntthesport.org/youthclubnationals/.
  • Two schedule tables (Day 1, Day 2) — winners are bolded text in either
  • the Home or Away cell. Two championship rows (18U + 14U) lack the
  • "Game (N)" pattern, parsed separately.
  • Special case: 18U Championship row has no bolded winner in HTML — only

Files Changed

Created (7):
  • + scripts/debug/check-stunt-match-shape.ts
  • + scripts/debug/check-stunt-team-seasons.ts
  • + scripts/debug/inspect-nationals-bolding.ts
  • + scripts/debug/verify-youth-nationals.ts
  • + scripts/import/import-youth-nationals-2025.ts
  • + scripts/maintenance/cleanup-ycn-dupes.ts
  • + scripts/scrape/parse-youth-nationals.ts
Modified (7):
  • ~ scripts/debug/check-stunt-match-shape.ts
  • ~ scripts/debug/check-stunt-team-seasons.ts
  • ~ scripts/debug/inspect-nationals-bolding.ts
  • ~ scripts/debug/verify-youth-nationals.ts
  • ~ scripts/import/import-youth-nationals-2025.ts
  • ~ scripts/maintenance/cleanup-ycn-dupes.ts
  • ~ scripts/scrape/parse-youth-nationals.ts

Version 0.2.250

STUNT: webpoint Gym team-coverage diagnostic

April 19, 2026 at 11:56 PM GMT+0
ad0f224
🔄Changed
  • STUNT: webpoint Gym team-coverage diagnostic
  • Cross-references webpoint-imported Gyms with their Team counts:
  • 71% are directory-only (no teams yet — expected, will accrue from
  • competition data). Big all-star programs already have 15-43 teams
  • from Varsity TV imports; webpoint just enriched their contact info.

Files Changed

Created (1):
  • + scripts/debug/webpoint-team-coverage.ts
Modified (1):
  • ~ scripts/debug/webpoint-team-coverage.ts

Version 0.2.249

STUNT: ingest entire 545-program webpoint directory + 188 logos

April 19, 2026 at 11:30 PM GMT+0
57060fc
🔄Changed
  • STUNT: ingest entire 545-program webpoint directory + 188 logos
  • Scraped via Playwright MCP: empty-filter search on usacheer.webpoint.us
  • returned the complete USA Cheer programs database (545 listings, no
  • pagination cap). Cf_clearance cookie from interactive session passed
  • Cloudflare invisibly.
  • Pipeline:

Files Changed

Created (7):
  • + scripts/debug/analyze-webpoint-dump.ts
  • + scripts/debug/check-webpoint-logos.ts
  • + scripts/debug/find-webpoint-dupes.ts
  • + scripts/debug/verify-webpoint-all-import.ts
  • + scripts/import/import-webpoint-all.ts
  • + scripts/maintenance/dedupe-webpoint-gyms.ts
  • + scripts/scrape/download-webpoint-logos.ts
Modified (7):
  • ~ scripts/debug/analyze-webpoint-dump.ts
  • ~ scripts/debug/check-webpoint-logos.ts
  • ~ scripts/debug/find-webpoint-dupes.ts
  • ~ scripts/debug/verify-webpoint-all-import.ts
  • ~ scripts/import/import-webpoint-all.ts
  • ~ scripts/maintenance/dedupe-webpoint-gyms.ts
  • ~ scripts/scrape/download-webpoint-logos.ts

Version 0.2.248

STUNT: import 42 more teams from webpoint via interactive browser

April 19, 2026 at 10:54 PM GMT+0
7df2b58
🔄Changed
  • STUNT: import 42 more teams from webpoint via interactive browser
  • Pivoted from custom scraper to using the Playwright MCP browser directly
  • in the user's interactive session. cf_clearance cookie from prior
  • solves let us pass Cloudflare Turnstile invisibly. Searched
  • CompanyName=STUNT on usacheer.webpoint.us/Clubs-wp.php → 47 STUNT-named
  • programs returned with full address + head coach contact info.

Files Changed

Created (2):
  • + scripts/debug/verify-webpoint-import.ts
  • + scripts/import/import-webpoint-stunt.ts
Modified (2):
  • ~ scripts/debug/verify-webpoint-import.ts
  • ~ scripts/import/import-webpoint-stunt.ts

Version 0.2.247

STUNT: import 51 non-college teams from stuntthesport.org

April 19, 2026 at 10:34 PM GMT+0
c8aea21
🔄Changed
  • STUNT: import 51 non-college teams from stuntthesport.org
  • Webpoint scraper hit a wall — Cloudflare requires a fresh Turnstile token
  • in every form POST body, not just the cf_clearance cookie, so cookie-replay
  • via Playwright's APIRequestContext also returns a challenge. Captured the
  • attempt in scrape-webpoint-http.ts as documentation; persistent-profile
  • flow stays as scrape-webpoint.ts (only useful with paid Captcha solver).

Files Changed

Created (5):
  • + scripts/debug/dbg-sts-tables.ts
  • + scripts/debug/verify-sts-import.ts
  • + scripts/import/import-stunt-rankings.ts
  • + scripts/scrape/parse-stuntthesport-rankings.ts
  • + scripts/scrape/scrape-webpoint-http.ts
Modified (6):
  • ~ scripts/debug/dbg-sts-tables.ts
  • ~ scripts/debug/verify-sts-import.ts
  • ~ scripts/import/import-stunt-rankings.ts
  • ~ scripts/scrape/parse-stuntthesport-rankings.ts
  • ~ scripts/scrape/scrape-webpoint-http.ts
  • ~ scripts/scrape/scrape-webpoint.ts

Version 0.2.246

STUNT: webpoint scraper using persistent Chromium profile

April 19, 2026 at 9:48 PM GMT+0
41bc870
🔄Changed
  • STUNT: webpoint scraper using persistent Chromium profile
  • Bypasses Cloudflare Turnstile checkbox-mode challenge by using
  • chromium.launchPersistentContext — user solves the checkbox once on
  • first run, cf_clearance cookie persists in playwright-profile/ for
  • subsequent unattended runs.
  • Iterates 7 webpoint categories (Club, Dev Club, Elem-Club, HS,

Files Changed

Created (1):
  • + scripts/scrape/scrape-webpoint.ts
Modified (1):
  • ~ scripts/scrape/scrape-webpoint.ts

Version 0.2.245

PDF extractor: NCA cheer-21 + flex-no-toss templates, max-value validation

April 19, 2026 at 9:45 PM GMT+0
c98f75f
🔄Changed
  • PDF extractor: NCA cheer-21 + flex-no-toss templates, max-value validation
  • pdf-score-extractor: nca_cheer_21 template (NCA Division Averages PDFs
  • omit runningTumblingMpd; 21 values per team), cheer_flex_no_toss_20
  • template (Flex divisions skip TOSS, have RT MAX/MPD)
  • pdf-completeness-loop: per-field FIELD_MAX bounds reject mis-mapped values
  • from shifted templates so we don't propagate garbage scores

Files Changed

Created (13):
  • + scripts/debug/check-hiss-raw.ts
  • + scripts/debug/check-hiss-score.ts
  • + scripts/debug/check-sea-to-sky-comp.ts
  • + scripts/debug/debug-hiss-extract.ts
  • + scripts/debug/diagnose-stuck-templates.ts
  • + scripts/debug/dump-lines.ts
  • + scripts/debug/find-special-pdf.ts
  • + scripts/debug/inspect-pdf-by-id.ts
  • + scripts/debug/inspect-pdf-headers.ts
  • + scripts/debug/test-u18nt-extract.ts
  • + scripts/debug/trace-extract.ts
  • + scripts/maintenance/clear-corrupted-pdf-breakdowns.ts
  • + scripts/maintenance/flag-nonstandard-competitions.ts
Modified (15):
  • ~ scripts/debug/check-hiss-raw.ts
  • ~ scripts/debug/check-hiss-score.ts
  • ~ scripts/debug/check-sea-to-sky-comp.ts
  • ~ scripts/debug/debug-hiss-extract.ts
  • ~ scripts/debug/diagnose-stuck-templates.ts
  • ~ scripts/debug/dump-lines.ts
  • ~ scripts/debug/find-special-pdf.ts
  • ~ scripts/debug/inspect-pdf-by-id.ts
  • ~ scripts/debug/inspect-pdf-headers.ts
  • ~ scripts/debug/test-u18nt-extract.ts
  • ~ scripts/debug/trace-extract.ts
  • ~ scripts/maintenance/clear-corrupted-pdf-breakdowns.ts
  • ~ scripts/maintenance/flag-nonstandard-competitions.ts
  • ~ scripts/maintenance/pdf-completeness-loop.ts
  • ~ src/lib/import/pdf-score-extractor.ts

Version 0.2.244

STUNT discipline launch — full hub, ~2k match results, scoring + standings

April 20, 2026 at 1:34 AM GMT+0
48e7d26
Added
  • STUNT (Stunt The Sport) added as first-class discipline with MATCH scoring model
  • /stunt hub with category navigation (College, Conferences, Matches, Standings)
  • /stunt/programs filterable directory of 88 college programs
  • /stunt/matches feed with quarter-by-quarter scoring on detail pages
  • /stunt/standings with W/L/PF/PA grouped by NCAA division
  • /stunt/conferences and /stunt/conferences/[slug] for league-level browsing
  • <DisciplineBadge> component with color-coded discipline tags integrated into team-hero, gym-hero, athlete experience
  • Discipline registry at src/lib/disciplines/registry.ts as single source of truth
  • ~2,000 historical STUNT matches imported from collegestunt.org with quarter-by-quarter scoring
  • 36 STUNT head coaches imported with team affiliations
  • Daily collegestunt.org sync + weekly usacheer.org sync wired into Railway worker
🔄Changed
  • Discipline taxonomy cleaned up: 5 inactive disciplines activated (~15,700 hidden teams now visible in filters)
  • Renamed legacy STUNT discipline (140 Group Stunt teams) to Group Stunt
  • Merged All Star duplicate discipline into All Star Cheer (1,196 teams + 533 divisions consolidated)
  • 2,496 NULL-discipline teams classified via heuristic
  • 67 STUNT logos mirrored to Supabase storage to remove partner-CDN dependency
  • Sitemap updated to include /stunt routes
🗑️Removed
  • Empty placeholder disciplines deleted: CheerABILITIES, Rec Cheer (dupe), Pro, Sideline

Version 0.2.244

STUNT discipline launch: hub, ~2k matches, scoring + standings

April 19, 2026 at 9:44 PM GMT+0
4c8e728
🔄Changed
  • STUNT discipline launch: hub, ~2k matches, scoring + standings
  • Schema: VarsityOrClub enum, Gym.ncaaDivision/institutionConference,
  • Team.varsityOrClub/conference/scholarshipsOffered, StuntMatchTeam.quarterScores
  • Discipline registry as single source of truth (src/lib/disciplines/registry.ts)
  • /stunt hub: landing, programs directory, match feed, match detail with
  • quarter-by-quarter scoring, standings, conferences

Files Changed

Created (20):
  • + scripts/debug/audit-allstar-dupe.ts
  • + scripts/debug/audit-stunt-gyms.ts
  • + scripts/debug/check-cheerabilities.ts
  • + scripts/debug/check-stunt-import.ts
  • + scripts/debug/check-stunt-match-progress.ts
  • + scripts/debug/find-dupes.ts
  • + scripts/debug/find-pm-accounts.ts
  • + scripts/debug/inspect-cstunt-oldest.ts
  • + scripts/debug/inspect-cstunt-tables.ts
  • + scripts/debug/inspect-name-collisions.ts
  • + scripts/debug/inspect-null-discipline-teams.ts
  • + scripts/debug/move-leftover-divs.ts
  • + scripts/debug/probe-collegestunt-api.ts
  • + scripts/debug/probe-collegestunt-endpoints.ts
  • + scripts/debug/probe-stunt-schema.ts
  • + scripts/debug/reconcile-cstunt-teams.ts
  • + scripts/debug/verify-cali-coed.ts
  • + scripts/debug/verify-stunt-in-picker.ts
  • + scripts/import/import-cstunt-matches.ts
  • + scripts/import/import-cstunt-staff.ts
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/debug/audit-allstar-dupe.ts
  • ~ scripts/debug/audit-stunt-gyms.ts
  • ~ scripts/debug/check-cheerabilities.ts
  • ~ scripts/debug/check-stunt-import.ts
  • ~ scripts/debug/check-stunt-match-progress.ts
  • ~ scripts/debug/find-dupes.ts
  • ~ scripts/debug/find-pm-accounts.ts
  • ~ scripts/debug/inspect-cstunt-oldest.ts
  • ~ scripts/debug/inspect-cstunt-tables.ts
  • ~ scripts/debug/inspect-name-collisions.ts
  • ~ scripts/debug/inspect-null-discipline-teams.ts
  • ~ scripts/debug/move-leftover-divs.ts
  • ~ scripts/debug/probe-collegestunt-api.ts
  • ~ scripts/debug/probe-collegestunt-endpoints.ts
  • ~ scripts/debug/probe-stunt-schema.ts
  • ~ scripts/debug/reconcile-cstunt-teams.ts
  • ~ scripts/debug/verify-cali-coed.ts
  • ~ scripts/debug/verify-stunt-in-picker.ts
  • ~ scripts/import/import-cstunt-matches.ts

Version 0.2.243

Pricing page: align features with actual tier gates, add audit skill

April 19, 2026 at 5:48 PM GMT+0
b565778
🔄Changed
  • Pricing page: align features with actual tier gates, add audit skill
  • Added missing features to comparison table: media uploads, PDF export,
  • scorecard share, coach/choreographer pages, division access, CSV export,
  • advanced filters, schedule reminders
  • Removed SMS notifications (not shipped)
  • Fixed Score Breakdown using wrong feature flag

Files Changed

Created (1):
  • + src/docs/design-audit-prompt.md
Modified (3):
  • ~ src/app/pricing/page.tsx
  • ~ src/docs/design-audit-prompt.md
  • ~ src/lib/pricing-plans.ts

Version 0.2.242

Cross-surface polish: consistent heading styles, profile max-width

April 19, 2026 at 4:54 PM GMT+0
0e2c884
🔄Changed
  • Cross-surface polish: consistent heading styles, profile max-width
  • Division page season chart CardTitle aligned to text-base (was text-sm)
  • Athlete profile constrained to max-w-3xl to prevent ultrawide stretch

Files Changed

Modified (2):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/app/people/[username]/page.tsx

Version 0.2.241

Athlete profile: PDF export, empty states, motion, perf, a11y

April 19, 2026 at 4:32 PM GMT+0
3520fa1
🔄Changed
  • Athlete profile: PDF export, empty states, motion, perf, a11y
  • PDF export route (/api/pdf/profile/[username]) generates resume-style
  • PDF with experience, skills, competition results, stats, and profile URL
  • Pro tier can export any profile, Elite can export their own, free users
  • see upgrade CTA
  • Timeline empty state shows helpful message instead of blank

Files Changed

Created (2):
  • + src/app/api/pdf/profile/[username]/route.tsx
  • + src/components/pdf/profile-pdf-document.tsx
Modified (7):
  • ~ src/app/api/pdf/profile/[username]/route.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/pdf/profile-pdf-document.tsx
  • ~ src/components/people/person-timeline-viz.tsx
  • ~ src/components/people/recent-results-list.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/components/profile/profile-tabs.tsx

Version 0.2.240

Athlete profile: KPIs in header, remove profile type badges, auto-derive discipline

April 19, 2026 at 3:44 PM GMT+0
648577c
🔄Changed
  • Athlete profile: KPIs in header, remove profile type badges, auto-derive discipline
  • KPI stats (Performances, Wins, Podiums, Avg Score) render inside the
  • profile card on desktop, eliminating the standalone strip
  • Removed profile type badges (ATHLETE, PARENT, etc.) — role is shown
  • via experiences instead
  • Discipline field removed from Add/Edit Experience form — auto-fills

Files Changed

Modified (4):
  • ~ src/app/api/teams/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/people/person-experience.tsx
  • ~ src/components/profile/profile-card-clean.tsx

Version 0.2.239

Athlete profile: add See Less toggle on results, taller timeline with uncropped tooltips

April 19, 2026 at 3:42 AM GMT+0
a0a1a1d
🔄Changed
  • Athlete profile: add See Less toggle on results, taller timeline with uncropped tooltips
  • RecentResultsList client component with View All / See Less toggle (5 initial)
  • Timeline height scales to 350px/year and 50px per performance marker
  • Performance hover tooltips no longer truncated or clipped by container

Files Changed

Created (1):
  • + src/components/people/recent-results-list.tsx
Modified (3):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/people/person-timeline-viz.tsx
  • ~ src/components/people/recent-results-list.tsx

Version 0.2.238

Add season-based athlete filtering and confirmation system

April 19, 2026 at 3:32 AM GMT+0
439ba4a
Added
  • Add season-based athlete filtering and confirmation system
  • Athletes on team/gym pages now filter by the selected season dropdown
  • instead of being hardcoded to the current season. Ongoing experiences
  • require confirmation each August — athletes see "Still on [Team]?"
  • on their home feed and profile, preventing stale rosters.
  • SeasonAthleteGrid client component filters by season context

Files Changed

Created (5):
  • + src/app/api/cron/create-seasons/route.ts
  • + src/app/api/person/[id]/experience/confirm/route.ts
  • + src/components/athletes/season-athlete-grid.tsx
  • + src/components/people/season-confirmation-prompt.tsx
  • + src/lib/season-experience.ts
Modified (11):
  • ~ prisma/schema.prisma
  • ~ src/app/api/cron/create-seasons/route.ts
  • ~ src/app/api/person/[id]/experience/confirm/route.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/home/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/athletes/season-athlete-grid.tsx
  • ~ src/components/people/person-timeline-viz.tsx
  • ~ src/components/people/season-confirmation-prompt.tsx
  • ~ src/lib/season-experience.ts

Version 0.2.237

Division page: remove confusing charts, add analyze button, clean up line chart

April 19, 2026 at 2:32 AM GMT+0
ca0c8fa
🔄Changed
  • Division page: remove confusing charts, add analyze button, clean up line chart
  • Removed Score Bands chart (confusing, low value)
  • Kept Season line chart with fixes: removed tick marks, transparent
  • dots (only current competition shows filled dots), tighter margins
  • Added "Analyze [Division]" button that loads all division teams
  • into /analyze workspace as temporary group

Files Changed

Modified (3):
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/components/competitions/division-team-history-chart.tsx

Version 0.2.236

Competition page: Pro tier division modal, wins filter on gym map

April 19, 2026 at 1:59 AM GMT+0
00a9ecb
🔄Changed
  • Competition page: Pro tier division modal, wins filter on gym map
  • Division cards show glass upgrade overlay for non-Pro users instead
  • of redirecting to /pricing. "Upgrade to Pro to unlock" + Dismiss.
  • Divisions limited to 6 per level with expand link
  • Gym map: Wins | All | No Wins filter on same row as D1/D2 toggle
  • "No Wins" shows blue-gray bubbles (same size as 1-win)

Files Changed

Modified (4):
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/components/competitions/gym-wins-map-wrapper.tsx
  • ~ src/components/competitions/gym-wins-map.tsx
  • ~ src/components/competitions/gyms-tab.tsx

Version 0.2.235

Competition page: admin tier override, division limit, glass upgrade modal

April 19, 2026 at 1:30 AM GMT+0
419da28
🔄Changed
  • Competition page: admin tier override, division limit, glass upgrade modal
  • Admin accounts get PRO-equivalent tier access
  • Divisions limited to 6 per level with "Show all" expand link
  • Free users see glass overlay on division cards instead of redirect
  • to /pricing — "Unlock full scorecard details" + Upgrade/Dismiss
  • Cards use overflow-hidden to contain the overlay

Files Changed

Modified (3):
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/components/competitions/competition-tabs.tsx
  • ~ src/components/competitions/divisions-tab.tsx

Version 0.2.234

Design overhaul: Teams + Gyms pages, design system foundation, tier gating

April 19, 2026 at 12:07 AM GMT+0
8a94d2e
🔄Changed
  • Design overhaul: Teams + Gyms pages, design system foundation, tier gating
  • Phase 3: Design system foundation
  • 29 new UI primitives (scoring, skills, progression, tier, layout)
  • Design tokens (level colors, skill categories, tier colors, locked states)
  • Spring motion system (snappy/smooth/bouncy/heavy presets)
  • /design-system preview page

Files Changed

Created (20):
  • + src/app/design-system/page.tsx
  • + src/app/teams/[id]/not-found.tsx
  • + src/components/gyms/gym-hero.tsx
  • + src/components/gyms/gym-more-button.tsx
  • + src/components/teams/performance-card.tsx
  • + src/components/teams/performance-history.tsx
  • + src/components/teams/team-hero.tsx
  • + src/components/teams/team-performance-view-toggle.tsx
  • + src/components/teams/team-stats-strip.tsx
  • + src/components/ui/animated-counter.tsx
  • + src/components/ui/badge-display.tsx
  • + src/components/ui/bottom-sheet.tsx
  • + src/components/ui/category-bar.tsx
  • + src/components/ui/celebration-overlay.tsx
  • + src/components/ui/comparison-ghost-slot.tsx
  • + src/components/ui/comparison-row.tsx
  • + src/components/ui/deduction-tag.tsx
  • + src/components/ui/dimmed-data-preview.tsx
  • + src/components/ui/division-status-pill.tsx
  • + src/components/ui/downgrade-notice.tsx
Modified (20):
  • ~ scripts/setup/seed-score-maximums.ts
  • ~ src/app/design-system/page.tsx
  • ~ src/app/globals.css
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/loading.tsx
  • ~ src/app/teams/[id]/not-found.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/gym-analysis/gym-dashboard.tsx
  • ~ src/components/gyms/gym-choreography-section.tsx
  • ~ src/components/gyms/gym-hero.tsx
  • ~ src/components/gyms/gym-more-button.tsx
  • ~ src/components/gyms/gym-more-section.tsx
  • ~ src/components/gyms/gym-season-filter.tsx
  • ~ src/components/gyms/gym-season-kpis.tsx
  • ~ src/components/gyms/gym-teams-section.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/components/teams/performance-card.tsx
  • ~ src/components/teams/performance-history.tsx
  • ~ src/components/teams/team-hero.tsx

Version 0.2.233

Perf: faster builds and page loads — force-dynamic, parallel queries, lazy charts

April 17, 2026 at 5:59 PM GMT+0
d0dd2a9
🔄Changed
  • Perf: faster builds and page loads — force-dynamic, parallel queries, lazy charts
  • Add force-dynamic to 78 DB-backed pages to prevent build-time static generation
  • (eliminates DB connections/timeouts during Vercel builds)
  • Remove duplicate prisma generate from build script (postinstall handles it)
  • Dynamic import 15+ Recharts chart components with ssr:false (~90KB bundle savings)
  • Parallelize sequential DB queries in schedules, gyms, leaderboard breakdown API

Files Changed

Modified (20):
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/[username]/analyze/team/[slug]/page.tsx
  • ~ src/app/[username]/competitions/page.tsx
  • ~ src/app/[username]/gyms/page.tsx
  • ~ src/app/[username]/people/page.tsx
  • ~ src/app/[username]/schedules/page.tsx
  • ~ src/app/[username]/teams/page.tsx
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/app/admin/choreographers/[id]/page.tsx
  • ~ src/app/admin/choreographers/page.tsx
  • ~ src/app/admin/coaches/[id]/page.tsx
  • ~ src/app/admin/coaches/page.tsx
  • ~ src/app/admin/competitions/[id]/data/page.tsx
  • ~ src/app/admin/competitions/page.tsx
  • ~ src/app/admin/content/page.tsx
  • ~ src/app/admin/data-audit/page.tsx
  • ~ src/app/admin/disciplines/page.tsx
  • ~ src/app/admin/divisions/page.tsx

Version 0.2.232

Add force-dynamic to search page to prevent static generation DB timeouts

April 17, 2026 at 5:43 PM GMT+0
3b589cc
Added
  • Add force-dynamic to search page to prevent static generation DB timeouts

Files Changed

Modified (1):
  • ~ src/app/search/page.tsx

Version 0.2.231

Move sidebar collapse toggle above logout divider for clarity

April 17, 2026 at 1:35 PM GMT+0
e8afdab
🔄Changed
  • Move sidebar collapse toggle above logout divider for clarity

Files Changed

Modified (2):
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.230

Update hero background image to Group 198

April 17, 2026 at 1:27 PM GMT+0
151d438
🔄Changed
  • Update hero background image to Group 198

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.229

Fix mobile sticky CTA: hide near final CTA, cap button width

April 17, 2026 at 4:09 AM GMT+0
2b3e467
🐛Fixed
  • Fix mobile sticky CTA: hide near final CTA, cap button width

Files Changed

Modified (2):
  • ~ src/components/landing/landing-page.tsx
  • ~ src/components/landing/landing-sticky-cta.tsx

Version 0.2.228

Add bottom padding to final CTA so it clears sticky mobile bar

April 17, 2026 at 3:55 AM GMT+0
a2c3030
Added
  • Add bottom padding to final CTA so it clears sticky mobile bar

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.227

Hero headline: single line, all white, lighter weight

April 17, 2026 at 3:48 AM GMT+0
7d4bca1
🔄Changed
  • Hero headline: single line, all white, lighter weight

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.226

Add maintenance toolkit, growth docs, search avatars + gitignore cleanup

April 17, 2026 at 3:12 AM GMT+0
2c4b724
Added
  • Add maintenance toolkit, growth docs, search avatars + gitignore cleanup
  • Search page: add avatar/logo images for gyms, teams, coaches,
  • choreographers, and competitions in search results
  • Growth docs: add outreach scripts, IG calendar, Klaviyo sequences,
  • ManyChat flows, and growth strategy
  • Maintenance scripts: commit 90+ operational tools for data quality,

Files Changed

Created (20):
  • + python-scraper/scrape_single_event.py
  • + python-scraper/scraper/html_scraper.py
  • + python-scraper/scraper/reconciler.py
  • + scripts/audit-missing-fields.ts
  • + scripts/backfill-score-fields.ts
  • + scripts/check-scoresheets.ts
  • + scripts/check-skills.ts
  • + scripts/local-full-scrape.ts
  • + scripts/maintenance/apply-gym-enrichment.ts
  • + scripts/maintenance/apply-late-results.ts
  • + scripts/maintenance/assess-gym-social.ts
  • + scripts/maintenance/audit-pdf-score-gaps.ts
  • + scripts/maintenance/backfill-bell-schedule-ids.ts
  • + scripts/maintenance/backfill-schedule-team-ids.ts
  • + scripts/maintenance/backfill-score-fields.ts
  • + scripts/maintenance/backfill-scores-from-pdf.ts
  • + scripts/maintenance/backfill-top-gym-locations.ts
  • + scripts/maintenance/check-all-missing.ts
  • + scripts/maintenance/check-apparel-data.ts
  • + scripts/maintenance/check-ca-frisco.ts
Modified (20):
  • ~ python-scraper/scrape_single_event.py
  • ~ python-scraper/scraper/html_scraper.py
  • ~ python-scraper/scraper/reconciler.py
  • ~ scripts/audit-missing-fields.ts
  • ~ scripts/backfill-score-fields.ts
  • ~ scripts/check-scoresheets.ts
  • ~ scripts/check-skills.ts
  • ~ scripts/local-full-scrape.ts
  • ~ scripts/maintenance/apply-gym-enrichment.ts
  • ~ scripts/maintenance/apply-late-results.ts
  • ~ scripts/maintenance/assess-gym-social.ts
  • ~ scripts/maintenance/audit-pdf-score-gaps.ts
  • ~ scripts/maintenance/backfill-bell-schedule-ids.ts
  • ~ scripts/maintenance/backfill-schedule-team-ids.ts
  • ~ scripts/maintenance/backfill-score-fields.ts
  • ~ scripts/maintenance/backfill-scores-from-pdf.ts
  • ~ scripts/maintenance/backfill-top-gym-locations.ts
  • ~ scripts/maintenance/check-all-missing.ts
  • ~ scripts/maintenance/check-apparel-data.ts
  • ~ scripts/maintenance/check-ca-frisco.ts

Version 0.2.225

Dedupe 130 gyms + 317 teams + fix Cheer Athletics city data

April 17, 2026 at 3:03 AM GMT+0
a51cf41
🔄Changed
  • Dedupe 130 gyms + 317 teams + fix Cheer Athletics city data
  • Full-database dedup Ralph loop: merged duplicate gyms (exact-name),
  • teams (same-gym exact, prefix-artifact, franchise siblings), cleaned
  • orphans, and fixed CA franchise city/state data (10 locations had
  • wrong city from backfill, e.g. Pensacola showed MS instead of FL,
  • Pittsburgh showed OH instead of PA, St. Louis showed Monroe LA).

Files Changed

Created (3):
  • + scripts/maintenance/dedup-gyms.ts
  • + scripts/maintenance/fix-ca-cities.ts
  • + scripts/maintenance/full-dedup-loop.ts
Modified (4):
  • ~ scripts/maintenance/dedup-gyms.ts
  • ~ scripts/maintenance/fix-ca-cities.ts
  • ~ scripts/maintenance/full-dedup-loop.ts
  • ~ scripts/maintenance/merge-same-gym-prefix-dupes.ts

Version 0.2.224

Make FullOut logo larger, shrink Build Your Legacy to match width

April 17, 2026 at 2:54 AM GMT+0
321571d
🔄Changed
  • Make FullOut logo larger, shrink Build Your Legacy to match width

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.223

Redesign landing page: dark mode, broader positioning, team preview

April 16, 2026 at 10:33 PM GMT+0
4515cd2
🔄Changed
  • Redesign landing page: dark mode, broader positioning, team preview
  • Force dark mode on landing page via wrapper class
  • Update hero subhead to cover scores + profiles (not just profiles)
  • Broaden search placeholder to include competitions
  • Reorder sections: fans/parents module now appears first after hero
  • Add team data preview mockup (Orange / Stingray Allstars) with

Files Changed

Modified (3):
  • ~ src/app/page.tsx
  • ~ src/components/landing/landing-page.tsx
  • ~ src/components/landing/landing-search.tsx

Version 0.2.222

Group nav into My Stuff / Explore / More collapsibles

April 16, 2026 at 9:12 PM GMT+0
3332157
🔄Changed
  • Group nav into My Stuff / Explore / More collapsibles
  • Collapse the flat 15-item nav into 4 top-level anchors (Feed, Scores,
  • Profile, Notifications) plus three collapsible groups:
  • My Stuff: My People, Teams, Gyms, Competitions, Schedules
  • Explore: People, Teams, Gyms, Competitions, Schedules
  • More: News, Learn, Analyze, Settings

Files Changed

Created (3):
  • + src/components/dashboard/nav-group-item.tsx
  • + src/lib/hooks/use-local-storage-boolean.ts
  • + src/lib/nav-config.ts
Modified (5):
  • ~ src/components/dashboard/nav-group-item.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/navbar.tsx
  • ~ src/lib/hooks/use-local-storage-boolean.ts
  • ~ src/lib/nav-config.ts

Version 0.2.221

Fix PDF extractor + UI polish + dedupe R1/R2 scores

April 16, 2026 at 7:28 PM GMT+0
3fbd9d1
🐛Fixed
  • Fix PDF extractor + UI polish + dedupe R1/R2 scores
  • PDF extractor (src/lib/import/pdf-score-extractor.ts)
  • Delay team flush until next team label is seen so the 22-field template
  • wins over the 15-field template when the numeric buffer crosses 15.
  • Skip "-" / "--" null placeholders that previously split Team labels.
  • Add header-fragment noise detection ("mansh", "ip", "pyram", etc.) for

Files Changed

Modified (12):
  • ~ scripts/maintenance/pdf-completeness-loop.ts
  • ~ src/app/globals.css
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/competitions/competition-performances.tsx
  • ~ src/components/competitions/division-scorecard.tsx
  • ~ src/components/gym-analysis/gym-scorecard-export.ts
  • ~ src/components/gym-analysis/gym-scorecard.tsx
  • ~ src/components/teams/competition-analysis/team-page-tabs.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/components/teams/team-stats-bar.tsx
  • ~ src/lib/import/pdf-score-extractor.ts

Version 0.2.220

Dedupe 622 more same-gym prefix-artifact Team rows

April 15, 2026 at 10:33 PM GMT+0
50eccda
🔄Changed
  • Dedupe 622 more same-gym prefix-artifact Team rows
  • User still saw "Top Gun All Stars - TGLC" alongside "TGLC" at the same
  • gym — the original audit didn't catch this class because the prefix is
  • only part of the gym name (franchise root), not the full gym name.
  • This adds merge-same-gym-prefix-dupes.ts which, for each Team, tries
  • stripping a leading "<gym-name>[ - | ]" OR "<franchise-prefix>[ - | ]"

Files Changed

Created (1):
  • + scripts/maintenance/merge-same-gym-prefix-dupes.ts
Modified (1):
  • ~ scripts/maintenance/merge-same-gym-prefix-dupes.ts

Version 0.2.219

Dedupe 419 duplicate Team rows + prevent recurrence

April 15, 2026 at 10:14 PM GMT+0
bb07f42
🔄Changed
  • Dedupe 419 duplicate Team rows + prevent recurrence
  • Problem: /search surfaced 15+ fragmented cards for single franchises
  • (Top Gun, Stingray, etc.) because team imports created bare-gym artifact
  • teams alongside the real located-gym teams, and no DB constraint stopped
  • same-gym same-name dupes from forming.
  • Cleanup (data):

Files Changed

Created (5):
  • + prisma/migrations/add_team_unique_name_gym.sql
  • + scripts/maintenance/apply-team-unique-index.ts
  • + scripts/maintenance/audit-team-duplicates.ts
  • + scripts/maintenance/merge-same-gym-exact-dupes.ts
  • + scripts/maintenance/merge-team-clusters.ts
Modified (7):
  • ~ prisma/migrations/add_team_unique_name_gym.sql
  • ~ scripts/maintenance/apply-team-unique-index.ts
  • ~ scripts/maintenance/audit-team-duplicates.ts
  • ~ scripts/maintenance/merge-exact-franchise-team-dupes.ts
  • ~ scripts/maintenance/merge-same-gym-exact-dupes.ts
  • ~ scripts/maintenance/merge-team-clusters.ts
  • ~ src/lib/import/franchise-team-resolver.ts

Version 0.2.218

Dedupe 419 duplicate Team rows + prevent recurrence

April 15, 2026 at 10:13 PM GMT+0
b98ab8d
🔄Changed
  • Dedupe 419 duplicate Team rows + prevent recurrence
  • Problem: /search surfaced 15+ fragmented cards for single franchises
  • (Top Gun, Stingray, etc.) because team imports created bare-gym artifact
  • teams alongside the real located-gym teams, and no DB constraint stopped
  • same-gym same-name dupes from forming.
  • Cleanup (data):

Files Changed

Created (5):
  • + prisma/migrations/add_team_unique_name_gym.sql
  • + scripts/maintenance/apply-team-unique-index.ts
  • + scripts/maintenance/audit-team-duplicates.ts
  • + scripts/maintenance/merge-same-gym-exact-dupes.ts
  • + scripts/maintenance/merge-team-clusters.ts
Modified (7):
  • ~ prisma/migrations/add_team_unique_name_gym.sql
  • ~ scripts/maintenance/apply-team-unique-index.ts
  • ~ scripts/maintenance/audit-team-duplicates.ts
  • ~ scripts/maintenance/merge-exact-franchise-team-dupes.ts
  • ~ scripts/maintenance/merge-same-gym-exact-dupes.ts
  • ~ scripts/maintenance/merge-team-clusters.ts
  • ~ src/lib/import/franchise-team-resolver.ts

Version 0.2.217

Dedupe 419 duplicate Team rows + prevent recurrence

April 15, 2026 at 10:12 PM GMT+0
321d1ed
🔄Changed
  • Dedupe 419 duplicate Team rows + prevent recurrence
  • Problem: /search surfaced 15+ fragmented cards for single franchises
  • (Top Gun, Stingray, etc.) because team imports created bare-gym artifact
  • teams alongside the real located-gym teams, and no DB constraint stopped
  • same-gym same-name dupes from forming.
  • Cleanup (data):

Files Changed

Created (5):
  • + prisma/migrations/add_team_unique_name_gym.sql
  • + scripts/maintenance/apply-team-unique-index.ts
  • + scripts/maintenance/audit-team-duplicates.ts
  • + scripts/maintenance/merge-same-gym-exact-dupes.ts
  • + scripts/maintenance/merge-team-clusters.ts
Modified (7):
  • ~ prisma/migrations/add_team_unique_name_gym.sql
  • ~ scripts/maintenance/apply-team-unique-index.ts
  • ~ scripts/maintenance/audit-team-duplicates.ts
  • ~ scripts/maintenance/merge-exact-franchise-team-dupes.ts
  • ~ scripts/maintenance/merge-same-gym-exact-dupes.ts
  • ~ scripts/maintenance/merge-team-clusters.ts
  • ~ src/lib/import/franchise-team-resolver.ts

Version 0.2.216

Add onboarding routes and harden team import safety

April 12, 2026 at 2:48 PM GMT+0
6b07bb5
Added
  • Add onboarding routes and harden team import safety

Files Changed

Created (5):
  • + src/app/api/klaviyo/track-cancel/route.ts
  • + src/app/api/klaviyo/track-feature-gated/route.ts
  • + src/app/api/klaviyo/track-referral-shared/route.ts
  • + src/app/api/stripe/pause/route.ts
  • + src/app/welcome/page.tsx
Modified (7):
  • ~ src/app/api/klaviyo/track-cancel/route.ts
  • ~ src/app/api/klaviyo/track-feature-gated/route.ts
  • ~ src/app/api/klaviyo/track-referral-shared/route.ts
  • ~ src/app/api/stripe/pause/route.ts
  • ~ src/app/welcome/page.tsx
  • ~ src/lib/import/team-matcher.ts
  • ~ src/lib/schedule-display.ts

Version 0.2.215

Fix gym season filtering and franchise team resolution

April 12, 2026 at 2:39 PM GMT+0
888a2bf
🐛Fixed
  • Fix gym season filtering and franchise team resolution

Files Changed

Created (2):
  • + scripts/maintenance/merge-exact-franchise-team-dupes.ts
  • + src/lib/import/franchise-team-resolver.ts
Modified (8):
  • ~ scripts/maintenance/merge-exact-franchise-team-dupes.ts
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/components/competitions/competition-performances.tsx
  • ~ src/components/competitions/division-scorecard.tsx
  • ~ src/components/competitions/divisions-tab.tsx
  • ~ src/components/gyms/gym-teams-section.tsx
  • ~ src/lib/import/franchise-team-resolver.ts
  • ~ src/lib/import/index.ts

Version 0.2.214

Fix schedule import: strict gym matching + franchise-aware team lookup

April 9, 2026 at 11:07 PM GMT+0
1786835
🐛Fixed
  • Fix schedule import: strict gym matching + franchise-aware team lookup
  • Two latent bugs surfaced importing the 2026 Northeast Summit schedule:
  • 1. findOrCreateGym fuzzy-matched at 0.75 with no city/state, collapsing
  • distinct franchises (e.g. "Force Athletics" -> "G-Force Athletics",
  • "Cheer Idol Athletics" -> "Cheer Athletics"). Summit spreadsheets
  • rarely ship city/state, so the fuzzy branch was ungrounded.

Files Changed

Created (7):
  • + scripts/debug/audit-northeast-schedule.ts
  • + scripts/debug/find-northeast-summit.ts
  • + scripts/debug/import-northeast-summit-schedule.ts
  • + scripts/debug/import-summit-2026-regionals.ts
  • + scripts/debug/rerun-northeast-summit.ts
  • + scripts/debug/spot-check-new-teams.ts
  • + scripts/debug/verify-northeast-fix.ts
Modified (10):
  • ~ scripts/debug/audit-northeast-schedule.ts
  • ~ scripts/debug/find-northeast-summit.ts
  • ~ scripts/debug/import-northeast-summit-schedule.ts
  • ~ scripts/debug/import-summit-2026-regionals.ts
  • ~ scripts/debug/rerun-northeast-summit.ts
  • ~ scripts/debug/spot-check-new-teams.ts
  • ~ scripts/debug/verify-northeast-fix.ts
  • ~ src/lib/import/gym-matcher.ts
  • ~ src/lib/import/schedule-import.ts
  • ~ src/lib/import/schedule-matcher.ts

Version 0.2.213

Match desktop sidebar to mobile drawer (parity nav)

April 9, 2026 at 11:04 PM GMT+0
1df74c1
🔄Changed
  • Match desktop sidebar to mobile drawer (parity nav)
  • Desktop sidebar was showing 4 items (Feed/Scores/Plan/Me) while mobile
  • drawer has 15. Rewrites DashboardSidebarNav to render the full rich list
  • that mirrors the drawer, so every destination reachable from mobile is
  • also reachable from desktop in one click.
  • Desktop sidebar now shows:

Files Changed

Modified (1):
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.212

Add My People and News to mobile drawer nav

April 9, 2026 at 10:48 PM GMT+0
3b6bd0b
Added
  • Add My People and News to mobile drawer nav
  • Drawer was missing two destinations users want quick access to:
  • My People (/:username/people) — follows people/athletes
  • News (/news) — the public cheer hub
  • Added to the main drawer section alongside the other personal destinations.

Files Changed

Modified (1):
  • ~ src/components/navbar.tsx

Version 0.2.211

Fix empty mobile drawer: rich Twitter/X-style personal hub

April 9, 2026 at 10:37 PM GMT+0
ca567d5
🐛Fixed
  • Fix empty mobile drawer: rich Twitter/X-style personal hub
  • Phase 5 scoped the drawer down too far — it ended up with 4 items in a full-height container, looking broken. Rebuild the drawer as a proper Twitter/X-style personal navigation hub.
  • User header card at top (tap to Profile): avatar, display name, @handle
  • Main personal destinations: Profile, Notifications (with unread badge), My Teams, My Schedules, My Gyms, My Competitions, Analyze, Groups
  • Settings section: Settings, Switch accounts, Send feedback, Learn
  • Conditional Upgrade to Elite pill (free tier only) with the existing pink/purple gradient

Files Changed

Modified (1):
  • ~ src/components/navbar.tsx

Version 0.2.210

Nav redesign: mobile header + 4-tab bottom bar + audience-aware /my

April 9, 2026 at 9:31 PM GMT+0
d1b2c93
🔄Changed
  • Nav redesign: mobile header + 4-tab bottom bar + audience-aware /my
  • Mobile header now has search + notification bell for auth users (was logo-only)
  • Bottom bar: Feed / Scores / Plan / Me (4 tabs, renamed from 5). News merged into Feed context
  • Me tab routes to /my (dashboard), unorphaning the personalization surface
  • /my hero card adapts to audience: athletes see profile completion pull, free watchers with 2+ follows see Elite upgrade CTA, new users see welcome nudge
  • /my tile grid reorders by audience (athlete/watcher/new)

Files Changed

Created (2):
  • + src/components/feed-tabs-nav.tsx
  • + src/components/my/my-hero-card.tsx
Modified (9):
  • ~ src/app/home/page.tsx
  • ~ src/app/my/page.tsx
  • ~ src/app/news/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/feed-tabs-nav.tsx
  • ~ src/components/my/my-hero-card.tsx
  • ~ src/components/my/my-stuff-grid.tsx
  • ~ src/components/navbar.tsx

Version 0.2.209

Allow logged-in users to view landing page at /

April 9, 2026 at 6:30 PM GMT+0
2b94705
🔄Changed
  • Allow logged-in users to view landing page at /
  • Remove the RootPage redirect to /home so both guests and authenticated
  • users can revisit the onboarding pitch and product overview on the
  • landing page. Middleware already treats / as public, so no other
  • changes were needed.

Files Changed

Modified (1):
  • ~ src/app/page.tsx

Version 0.2.208

Fix schedule display: Summit routine codes + /schedules dedupe

April 9, 2026 at 2:56 PM GMT+0
d2a8260
🐛Fixed
  • Fix schedule display: Summit routine codes + /schedules dedupe
  • Three schedule-page bugs spotted on fullout.energy:
  • 1. Summit regional schedules rendered routine/entry IDs (L2S82936, L3Y0114,
  • CA-EL102772) as bold team names because Varsity's Summit spreadsheets put
  • codes in the "Team" column and the matcher created Team rows keyed to
  • them. New isRoutineCode() helper in src/lib/schedule-display.ts; card

Files Changed

Created (2):
  • + scripts/import/import-missing-summit-schedules.ts
  • + src/lib/schedule-display.ts
Modified (6):
  • ~ scripts/import/import-missing-summit-schedules.ts
  • ~ src/app/schedules/page.tsx
  • ~ src/components/schedules/grouped-schedule-table.tsx
  • ~ src/components/schedules/schedule-card.tsx
  • ~ src/components/schedules/schedule-table.tsx
  • ~ src/lib/schedule-display.ts

Version 0.2.207

Fix Stingray Allstars franchise mapping: split 291-team HQ into 15 locations

April 9, 2026 at 2:47 PM GMT+0
2f5e25d
🐛Fixed
  • Fix Stingray Allstars franchise mapping: split 291-team HQ into 15 locations
  • The main "The Stingray Allstars" Marietta gym had 291 teams dumped into it
  • across multiple real franchise locations. Research-verified the full list
  • of ~15 active Stingray Allstars franchises and re-assigned teams by theme:
  • Marietta HQ: 291 → 73 (Green flagship + core colors)
  • Cartersville: 8 → 40 (weather/elements)

Files Changed

Created (5):
  • + scripts/investigate-stingray-main-gym.ts
  • + scripts/investigate-stingray.ts
  • + scripts/maintenance/cleanup-stingray-empty-gyms.ts
  • + scripts/maintenance/fix-stingray-franchises.ts
  • + scripts/verify-stingray-final.ts
Modified (5):
  • ~ scripts/investigate-stingray-main-gym.ts
  • ~ scripts/investigate-stingray.ts
  • ~ scripts/maintenance/cleanup-stingray-empty-gyms.ts
  • ~ scripts/maintenance/fix-stingray-franchises.ts
  • ~ scripts/verify-stingray-final.ts

Version 0.2.206

Fix Vercel build: add missing src/components/growth/ directory

April 9, 2026 at 1:52 PM GMT+0
95df868
🐛Fixed
  • Fix Vercel build: add missing src/components/growth/ directory
  • subscription-actions.tsx was committed earlier (a7a0156) importing
  • @/components/growth/CancelSaveFlow but the growth/ directory was left
  • untracked, breaking the Vercel build. Adds the three growth components
  • that were sitting in the working tree so the build can resolve the import.

Files Changed

Created (3):
  • + src/components/growth/CancelSaveFlow.tsx
  • + src/components/growth/ReferralPrompt.tsx
  • + src/components/growth/UpgradePrompt.tsx
Modified (3):
  • ~ src/components/growth/CancelSaveFlow.tsx
  • ~ src/components/growth/ReferralPrompt.tsx
  • ~ src/components/growth/UpgradePrompt.tsx

Version 0.2.205

Import The Cheerleading Worlds (2004-2025) + 2026 schedule + franchise remap

April 9, 2026 at 1:47 PM GMT+0
ac0d26e
🔄Changed
  • Import The Cheerleading Worlds (2004-2025) + 2026 schedule + franchise remap
  • Adds full historical Worlds ranking data from thecheerleadingworlds.net
  • and the 2026 compete order PDF, plus cleanup tools for the franchise
  • gym naming drift that the import surfaced.
  • Historical import (2004-2025, 2020 cancelled for COVID):
  • scripts/import/scrape-cheerleading-worlds.ts parses the TablePress HTML

Files Changed

Created (9):
  • + scripts/import/import-cheerleading-worlds.ts
  • + scripts/import/import-worlds-2026-schedule.ts
  • + scripts/import/remap-worlds-flagship-fixes.ts
  • + scripts/import/remap-worlds-franchise-gyms.ts
  • + scripts/import/scrape-cheerleading-worlds.ts
  • + src/components/ui/worlds-champion-badge.tsx
  • + src/lib/import/worlds-parsers.ts
  • + src/lib/worlds-event-dates.ts
  • + src/lib/worlds-utils.ts
Modified (11):
  • ~ scripts/import/import-cheerleading-worlds.ts
  • ~ scripts/import/import-worlds-2026-schedule.ts
  • ~ scripts/import/remap-worlds-flagship-fixes.ts
  • ~ scripts/import/remap-worlds-franchise-gyms.ts
  • ~ scripts/import/scrape-cheerleading-worlds.ts
  • ~ src/app/schedules/[slug]/page.tsx
  • ~ src/components/competitions/series-page-client.tsx
  • ~ src/components/ui/worlds-champion-badge.tsx
  • ~ src/lib/import/worlds-parsers.ts
  • ~ src/lib/worlds-event-dates.ts
  • ~ src/lib/worlds-utils.ts

Version 0.2.204

C:/Program Files/Git/home Instagram redesign + /scores cleanup + perf pass

April 9, 2026 at 1:25 PM GMT+0
b3ec2f1
🔄Changed
  • C:/Program Files/Git/home Instagram redesign + /scores cleanup + perf pass
  • /home feed redesign
  • Kill giant "Your feed of highlights..." header (wasted 20% of viewport)
  • Kill "Photo uploaded / Video uploaded / Performance update" titles
  • Collapse card to Instagram layout: avatar + name + relative time in one row,
  • edge-to-edge media on mobile, icon-only share action, name-prefixed caption

Files Changed

Modified (15):
  • ~ src/app/api/competitions/[id]/route.ts
  • ~ src/app/api/competitions/route.ts
  • ~ src/app/api/feed/route.ts
  • ~ src/app/api/live-scores/route.ts
  • ~ src/app/globals.css
  • ~ src/app/home/page.tsx
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/profile/media-share-buttons.tsx
  • ~ src/components/profile/profile-video-player.tsx
  • ~ src/components/providers/page-transition-provider.tsx
  • ~ src/components/scores/competitions-tab.tsx
  • ~ src/components/scores/scores-tab-nav.tsx
  • ~ src/lib/auth.ts
  • ~ src/lib/prisma.ts
  • ~ src/lib/utils.ts

Version 0.2.203

Schedule filters + grouping: dynamic Division + Discipline

April 9, 2026 at 1:21 PM GMT+0
ae17f3e
🔄Changed
  • Schedule filters + grouping: dynamic Division + Discipline
  • The schedule viewer's filters and group-by were hardcoded around
  • all-star data (level L1–L7, Tiny/Mini/Youth ages, etc.), so college
  • schedules showed empty filter sections and no useful grouping
  • options (level/age/size/divisionGroup were all null for NCA
  • Collegiate rows).

Files Changed

Created (2):
  • + scripts/debug/resolve-nca-schedule-slug.ts
  • + scripts/maintenance/set-nca-college-schedule-matched.ts
Modified (12):
  • ~ scripts/debug/resolve-nca-schedule-slug.ts
  • ~ scripts/import/import-nca-college-2026-schedule.ts
  • ~ scripts/maintenance/set-nca-college-schedule-matched.ts
  • ~ src/app/api/schedules/[slug]/entries/route.ts
  • ~ src/app/api/schedules/[slug]/filter-options/route.ts
  • ~ src/components/schedules/grouped-schedule-cards.tsx
  • ~ src/components/schedules/grouped-schedule-table.tsx
  • ~ src/components/schedules/schedule-filters-sheet.tsx
  • ~ src/components/schedules/schedule-filters-sidebar.tsx
  • ~ src/components/schedules/schedule-viewer.tsx
  • ~ src/lib/import/discipline-inference.ts
  • ~ src/lib/schedule-slug.ts

Version 0.2.202

Phase 3e: Elite 14-day trial + invite friends + Klaviyo events + brand polish

April 9, 2026 at 12:14 AM GMT+0
7773c7b
🔄Changed
  • Phase 3e: Elite 14-day trial + invite friends + Klaviyo events + brand polish
  • Five threads of polish landing together:
  • 1. 14-day free trial for Elite monthly
  • Stripe checkout accepts a new trial: true flag and sets trialDays=14
  • when the plan is Elite monthly with no conflicting offer code.
  • Pricing page adds a secondary "Try Elite Free for 14 Days" button

Files Changed

Modified (20):
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/build-your-legacy/page.tsx
  • ~ src/app/go-pro/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/how-scores-work/page.tsx
  • ~ src/app/plan-your-day/page.tsx
  • ~ src/app/pricing/page.tsx
  • ~ src/app/settings/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/landing/landing-page.tsx
  • ~ src/components/navbar.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/subscription-actions.tsx
  • ~ src/components/teams/team-header.tsx
  • ~ src/components/welcome/welcome-step-friends.tsx
  • ~ src/components/welcome/welcome-step-intro.tsx
  • ~ src/components/welcome/welcome-step-share.tsx
  • ~ src/components/welcome/welcome-step-upgrade.tsx

Version 0.2.201

Track college cheer + dance: NCA Collegiate 2026 setup

April 8, 2026 at 11:55 PM GMT+0
23374ea
🔄Changed
  • Track college cheer + dance: NCA Collegiate 2026 setup
  • The site has never tracked college cheer or dance as first-class
  • disciplines before. NCA & NDA Collegiate Nationals (Daytona Beach)
  • starts 2026-04-09, so:
  • Activate College Cheer discipline (was inactive) and add new
  • College Dance discipline with category+tier classification schema.

Files Changed

Created (14):
  • + scripts/debug/audit-college-inference.ts
  • + scripts/debug/check-live-monitor-detection.ts
  • + scripts/debug/check-nca-college-state.ts
  • + scripts/debug/check-schedule-entries.ts
  • + scripts/debug/inspect-nca-college-pdf.ts
  • + scripts/debug/inspect-nca-dance-section.ts
  • + scripts/debug/review-nca-college-schedule.ts
  • + scripts/debug/review-nca-suspicious.ts
  • + scripts/debug/test-parse-event-name.ts
  • + scripts/import/import-nca-college-2026-schedule.ts
  • + scripts/maintenance/fix-nca-college-2026.ts
  • + scripts/maintenance/fix-nca-college-schedule-rows.ts
  • + scripts/setup/activate-college-disciplines.ts
  • + src/lib/import/discipline-inference.ts
Modified (17):
  • ~ scripts/debug/audit-college-inference.ts
  • ~ scripts/debug/check-live-monitor-detection.ts
  • ~ scripts/debug/check-nca-college-state.ts
  • ~ scripts/debug/check-schedule-entries.ts
  • ~ scripts/debug/inspect-nca-college-pdf.ts
  • ~ scripts/debug/inspect-nca-dance-section.ts
  • ~ scripts/debug/review-nca-college-schedule.ts
  • ~ scripts/debug/review-nca-suspicious.ts
  • ~ scripts/debug/test-parse-event-name.ts
  • ~ scripts/import/import-nca-college-2026-schedule.ts
  • ~ scripts/maintenance/fix-nca-college-2026.ts
  • ~ scripts/maintenance/fix-nca-college-schedule-rows.ts
  • ~ scripts/setup/activate-college-disciplines.ts
  • ~ src/app/api/admin/scraper/schedule-intake/route.ts
  • ~ src/lib/import/discipline-inference.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/import/schedule-import.ts

Version 0.2.200

Update hero search helper copy on landing page

April 8, 2026 at 11:46 PM GMT+0
103ed48
🔄Changed
  • Update hero search helper copy on landing page
  • Replace "Find your team — your data might already be here" with
  • "Your team's already here. Now build your profile." The old copy
  • sounded surveillance-y ("your data might already be here"). The new
  • line leads with the real value prop (team history is already tracked)
  • and ties directly to the primary CTA.

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.199

Content queue: swap Buffer schedule for in-app post flow

April 8, 2026 at 11:35 PM GMT+0
8d18cd2
🔄Changed
  • Content queue: swap Buffer schedule for in-app post flow
  • Replace the "Schedule to Buffer" button with a self-contained manual
  • posting workflow. Everything stays on the app — no external service
  • dependency for daily use.
  • Admin queue preview dialog now has three footer actions:
  • Download Image — downloads the rendered PNG with a filename-safe slug

Files Changed

Modified (1):
  • ~ src/components/admin/content-actions.tsx

Version 0.2.198

Phase 3c + 3d: Kill ambient upgrade nags + Pro tier /go-pro showcase

April 8, 2026 at 11:29 PM GMT+0
3357d19
🔄Changed
  • Phase 3c + 3d: Kill ambient upgrade nags + Pro tier /go-pro showcase
  • Phase 3c — Contextual upgrade prompts
  • Based on the Phase 1c audit, the app had two patterns competing: ambient
  • banners / persistent sidebar nags (passive, annoying, low-converting) and
  • contextual prompts that fire at the moment of the limit (targeted,
  • high-converting). This phase removes the ambient pattern and doubles down

Files Changed

Created (1):
  • + src/app/go-pro/page.tsx
Modified (8):
  • ~ src/app/compose/page.tsx
  • ~ src/app/go-pro/page.tsx
  • ~ src/app/news/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/competitions/competition-tabs.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/welcome/welcome-step-upgrade.tsx
  • ~ src/middleware.ts

Version 0.2.197

Phase 2: Restructure core logged-in experience

April 8, 2026 at 11:21 PM GMT+0
b78c893
🔄Changed
  • Phase 2: Restructure core logged-in experience
  • Three sub-phases that together rebuild the /home experience, create a
  • public /news hub, and simplify the navigation to 5 clear destinations.
  • ## Phase 2a — Move hub to /news
  • The existing content hub (scores ticker, news articles, podcasts,
  • leaderboards, featured gyms, competition timeline, etc.) now lives at

Files Changed

Created (1):
  • + src/app/news/page.tsx
Modified (8):
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/app/home/page.tsx
  • ~ src/app/news/page.tsx
  • ~ src/app/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/navbar.tsx
  • ~ src/middleware.ts

Version 0.2.196

Content factory: add athlete, rankings, gym generators + LLM captions

April 8, 2026 at 11:09 PM GMT+0
4dbd262
🔄Changed
  • Content factory: add athlete, rankings, gym generators + LLM captions
  • Expands the content queue into a hands-off weekly content machine covering
  • all 5 content pillars from the growth playbook.
  • New generators (all follow the existing satori→resvg→sharp pipeline):
  • ATHLETE_SPOTLIGHT: picks a high-density public Person (photos + teams +
  • badges), renders portrait card for the Build Your Legacy track. 30-day

Files Changed

Created (10):
  • + src/app/api/admin/content/competitions/[id]/divisions/route.ts
  • + src/app/api/admin/content/competitions/route.ts
  • + src/app/api/cron/content-athlete-spotlight/route.ts
  • + src/app/api/cron/content-gym-story/route.ts
  • + src/app/api/cron/content-season-standings/route.ts
  • + src/components/admin/competition-scorecard-dialog.tsx
  • + src/lib/content/athlete-spotlight.ts
  • + src/lib/content/caption-variants.ts
  • + src/lib/content/gym-story.ts
  • + src/lib/content/season-standings.ts
Modified (19):
  • ~ src/app/admin/content/page.tsx
  • ~ src/app/api/admin/content/competitions/[id]/divisions/route.ts
  • ~ src/app/api/admin/content/competitions/route.ts
  • ~ src/app/api/admin/content/generate/route.ts
  • ~ src/app/api/cron/content-athlete-spotlight/route.ts
  • ~ src/app/api/cron/content-gym-story/route.ts
  • ~ src/app/api/cron/content-season-standings/route.ts
  • ~ src/components/admin/competition-scorecard-dialog.tsx
  • ~ src/components/admin/content-actions.tsx
  • ~ src/components/admin/content-generate-button.tsx
  • ~ src/lib/competition-scorecards.ts
  • ~ src/lib/content/athlete-spotlight.ts
  • ~ src/lib/content/caption-templates.ts
  • ~ src/lib/content/caption-variants.ts
  • ~ src/lib/content/gym-story.ts
  • ~ src/lib/content/score-drop.ts
  • ~ src/lib/content/season-standings.ts
  • ~ src/lib/content/weekend-preview.ts
  • ~ src/lib/content/weekly-roundup.ts

Version 0.2.195

Phase 3a + 3b: Expand /welcome to 6 steps with pain setup, friends finder, soft paywall

April 8, 2026 at 10:27 PM GMT+0
bd65a2a
🔄Changed
  • Phase 3a + 3b: Expand /welcome to 6 steps with pain setup, friends finder, soft paywall
  • Rebuild the post-signup onboarding flow following validated patterns from
  • Duolingo, Strava, and Hudl: remind users of the pain, show the solution,
  • ask for commitment (soft paywall) before the celebration.
  • Previous flow (3 steps):
  • Photo → Follow team → Share link

Files Changed

Created (8):
  • + src/components/welcome/welcome-flow.tsx
  • + src/components/welcome/welcome-progress.tsx
  • + src/components/welcome/welcome-step-follow.tsx
  • + src/components/welcome/welcome-step-friends.tsx
  • + src/components/welcome/welcome-step-intro.tsx
  • + src/components/welcome/welcome-step-photo.tsx
  • + src/components/welcome/welcome-step-share.tsx
  • + src/components/welcome/welcome-step-upgrade.tsx
Modified (9):
  • ~ src/components/navbar.tsx
  • ~ src/components/welcome/welcome-flow.tsx
  • ~ src/components/welcome/welcome-progress.tsx
  • ~ src/components/welcome/welcome-step-follow.tsx
  • ~ src/components/welcome/welcome-step-friends.tsx
  • ~ src/components/welcome/welcome-step-intro.tsx
  • ~ src/components/welcome/welcome-step-photo.tsx
  • ~ src/components/welcome/welcome-step-share.tsx
  • ~ src/components/welcome/welcome-step-upgrade.tsx

Version 0.2.194

Phase 1: Content lock + Athletes tab + upgrade audit + docs realign

April 8, 2026 at 10:14 PM GMT+0
76e8a97
🔄Changed
  • Phase 1: Content lock + Athletes tab + upgrade audit + docs realign
  • Three independent tactical wins that prepare FullOut for monetization
  • and reinforce the profile-first pitch, plus PRD and brand guide updates
  • to match the new product direction.
  • ## Content creation locked to Elite+ (Phase 1a)
  • Free users can no longer post photos, videos, or link embeds. The prior

Files Changed

Created (1):
  • + src/components/athletes/athlete-card.tsx
Modified (8):
  • ~ src/app/api/videos/route.ts
  • ~ src/app/compose/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/athletes/athlete-card.tsx
  • ~ src/components/dashboard/post-content.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/teams/competition-analysis/team-page-tabs.tsx

Version 0.2.193

Link profile mockup and feature cards to /build-your-legacy, use pink logo

April 8, 2026 at 4:00 PM GMT+0
24ca775
🔄Changed
  • Link profile mockup and feature cards to /build-your-legacy, use pink logo
  • Phone mockup in profile preview is now a clickable link to the
  • profile walkthrough, with a subtle hover lift
  • The three "Everything an athlete needs" feature cards now link to
  • /build-your-legacy as well
  • Swap the hero logo from white to the pink brand logo and nearly

Files Changed

Modified (1):
  • ~ src/components/landing/landing-page.tsx

Version 0.2.192

Add showcase pages, viral loop, and search conversion funnel

April 8, 2026 at 3:56 PM GMT+0
96b40ee
Added
  • Add showcase pages, viral loop, and search conversion funnel
  • The landing page drives signups, but the rest of the site wasn't converting —
  • search dumped 200+ raw results, profile pages had no viral hook, and the
  • value props (scores, schedules) had no marketing surface. This adds three
  • showcase experiences that sell each value prop with real data, a search
  • redesign that converts instead of just retrieves, and a viral loop on every

Files Changed

Created (10):
  • + src/app/build-your-legacy/page.tsx
  • + src/app/how-scores-work/page.tsx
  • + src/app/plan-your-day/page.tsx
  • + src/components/search/claim-banner.tsx
  • + src/components/showcase/showcase-level-preview.tsx
  • + src/components/showcase/showcase-profile-view.tsx
  • + src/components/viral/built-with-badge.tsx
  • + src/components/viral/viral-footer-cta.tsx
  • + src/lib/showcase-competition.ts
  • + src/lib/showcase-schedule.ts
Modified (14):
  • ~ src/app/build-your-legacy/page.tsx
  • ~ src/app/globals.css
  • ~ src/app/how-scores-work/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/plan-your-day/page.tsx
  • ~ src/app/search/page.tsx
  • ~ src/components/landing/landing-page.tsx
  • ~ src/components/search/claim-banner.tsx
  • ~ src/components/showcase/showcase-level-preview.tsx
  • ~ src/components/showcase/showcase-profile-view.tsx
  • ~ src/components/viral/built-with-badge.tsx
  • ~ src/components/viral/viral-footer-cta.tsx
  • ~ src/lib/showcase-competition.ts
  • ~ src/lib/showcase-schedule.ts

Version 0.2.191

Add sitemap, robots, and per-route metadata for SEO

April 8, 2026 at 1:34 PM GMT+0
e8e3484
Added
  • Add sitemap, robots, and per-route metadata for SEO
  • robots.ts: allow root, block /admin, /api, /settings, /onboarding,
  • /monitoring. Points crawlers at /sitemap.xml.
  • sitemap.ts: static routes + dynamic entries for up to 2k competitions,
  • 10k gyms, 20k teams (slug-preferred URLs). Revalidates daily. Queries
  • are .catch()-guarded so one failing section can't nuke the sitemap.

Files Changed

Created (5):
  • + src/app/login/layout.tsx
  • + src/app/pricing/layout.tsx
  • + src/app/robots.ts
  • + src/app/signup/layout.tsx
  • + src/app/sitemap.ts
Modified (5):
  • ~ src/app/login/layout.tsx
  • ~ src/app/pricing/layout.tsx
  • ~ src/app/robots.ts
  • ~ src/app/signup/layout.tsx
  • ~ src/app/sitemap.ts

Version 0.2.190

Optimize hub data queries: batch N+1, cache, remove nested relation filters

April 8, 2026 at 1:32 PM GMT+0
03164be
🔄Changed
  • Optimize hub data queries: batch N+1, cache, remove nested relation filters
  • getPersonalizedTeams: was firing 2 queries per followed team in a loop
  • (~22 round-trips for 10 teams). Now batches into 3 parallel findMany
  • calls and groups in-memory. Also wrapped in unstable_cache with a
  • per-user key and 60s TTL.
  • getCompetitionTimeline: previously uncached, now wrapped in

Files Changed

Modified (1):
  • ~ src/lib/hub-data.ts

Version 0.2.189

Add landing-focused SEO metadata to root route

April 8, 2026 at 1:27 PM GMT+0
608b246
Added
  • Add landing-focused SEO metadata to root route
  • Most visits to `/` from social shares and search engines are
  • unauthenticated, so the metadata should target the guest landing page
  • experience rather than the hub defaults from the root layout.

Files Changed

Modified (1):
  • ~ src/app/page.tsx

Version 0.2.188

Add profile-focused landing page for logged-out visitors

April 8, 2026 at 1:26 PM GMT+0
67a4f79
Added
  • Add profile-focused landing page for logged-out visitors
  • Split the root route by auth state: guests see a new mobile-first landing
  • page that sells "Build Your Legacy" and athlete profiles, while logged-in
  • users keep the existing hub. Also adds people to search results, brings
  • the brand pink in line with #EE2B8C, and fixes mobile overflow on the
  • search page.

Files Changed

Created (4):
  • + src/components/landing/landing-page.tsx
  • + src/components/landing/landing-scroll-reveal.tsx
  • + src/components/landing/landing-search.tsx
  • + src/components/landing/landing-sticky-cta.tsx
Modified (9):
  • ~ src/app/globals.css
  • ~ src/app/layout.tsx
  • ~ src/app/page.tsx
  • ~ src/app/search/page.tsx
  • ~ src/components/landing/landing-page.tsx
  • ~ src/components/landing/landing-scroll-reveal.tsx
  • ~ src/components/landing/landing-search.tsx
  • ~ src/components/landing/landing-sticky-cta.tsx
  • ~ src/components/navbar.tsx

Version 0.2.187

Overlap profile avatar on cover photo like Twitter/X

April 8, 2026 at 1:05 PM GMT+0
87f01c4
🔄Changed
  • Overlap profile avatar on cover photo like Twitter/X
  • Avatar now sits halfway over the cover photo bottom edge. Cover and
  • profile card are bundled in a single rounded/shadow container so they
  • read as one unit.

Files Changed

Modified (2):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-card-clean.tsx

Version 0.2.186

Fix mobile overflow on competition cards by adding min-w-0

April 8, 2026 at 2:05 AM GMT+0
31f8dd1
🐛Fixed
  • Fix mobile overflow on competition cards by adding min-w-0
  • CSS Grid children default to min-width:auto, preventing text
  • truncation from working. min-w-0 lets overflow-hidden take effect.

Files Changed

Modified (1):
  • ~ src/components/hub/competition-card.tsx

Version 0.2.185

Improve weekend preview card and add job numbers to content queue

April 3, 2026 at 1:40 AM GMT+0
49d3659
🔄Changed
  • Improve weekend preview card and add job numbers to content queue
  • Weekend preview: bump comp name 30→38px, always show city/state below
  • each competition, drop venue line, reduce max items 6→5, use FONT_SIZES
  • constants throughout. Content queue: add sequential # column for easy
  • reference when discussing corrections.

Files Changed

Modified (2):
  • ~ src/app/admin/content/page.tsx
  • ~ src/lib/content/weekend-preview.ts

Version 0.2.184

Increase content card font sizes to match scorecard generator minimums

April 2, 2026 at 2:24 AM GMT+0
c6459c3
🔄Changed
  • Increase content card font sizes to match scorecard generator minimums
  • Aligned FONT_SIZES with competition-scorecards.ts scale (sy() at 1920→1350).
  • Body text 18→22px, primary 22→28px, scores 24→32px, sections 30→34px.
  • Reduced max items per card from 4→3 to fit the larger text. All generators
  • now use FONT_SIZES constants with nothing below 22px.

Files Changed

Modified (4):
  • ~ src/lib/content/brand.ts
  • ~ src/lib/content/score-drop.ts
  • ~ src/lib/content/weekend-preview.ts
  • ~ src/lib/content/weekly-roundup.ts

Version 0.2.183

Fix Vercel build: move serverExternalPackages and outputFileTracingIncludes under experimental

April 1, 2026 at 9:34 PM GMT+0
4975dc5
🐛Fixed
  • Fix Vercel build: move serverExternalPackages and outputFileTracingIncludes under experimental
  • Next.js 14 expects these under `experimental`, not at the top level. The top-level
  • keys were silently ignored, causing webpack to try bundling @resvg/resvg-js native
  • binaries which fails on Vercel.

Version 0.2.182

Add uniform brand icons to gyms listing page

April 1, 2026 at 9:33 PM GMT+0
f1b6784
Added
  • Add uniform brand icons to gyms listing page
  • The uniformBrand field wasn't being fetched or rendered on the gyms
  • page, so Rebel/Varsity icons were missing next to gym names.

Files Changed

Modified (1):
  • ~ src/app/gyms/page.tsx

Version 0.2.181

Add collapsible "More" section to sidebar nav for Leaderboards and Analyze

April 1, 2026 at 9:26 PM GMT+0
2a0cfe4
Added
  • Add collapsible "More" section to sidebar nav for Leaderboards and Analyze
  • These pages became unreachable after the March hub redesign removed them from
  • the main nav. Adds a "More" toggle below Settings (desktop) and a popover on
  • mobile bottom nav. Auto-expands when the user is already on one of those pages.

Files Changed

Modified (1):
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.180

Fix satori module not found on Vercel by using direct ES imports

April 1, 2026 at 7:10 PM GMT+0
572ba6b
🐛Fixed
  • Fix satori module not found on Vercel by using direct ES imports
  • Replaced __non_webpack_require__ dynamic require hack with standard ES
  • module imports. These packages are already in serverExternalPackages in
  • next.config.js so Next.js resolves them from node_modules at runtime.

Files Changed

Modified (1):
  • ~ src/lib/content/image-renderer.ts

Version 0.2.179

Remove broken "From the Cheer Community" Instagram gallery from hub

April 1, 2026 at 7:04 PM GMT+0
0a634cc
🗑️Removed
  • Remove broken "From the Cheer Community" Instagram gallery from hub

Files Changed

Modified (1):
  • ~ src/app/page.tsx

Version 0.2.178

Enforce minimum font sizes on social media content cards for mobile legibility

April 1, 2026 at 6:46 PM GMT+0
fa721a3
🔄Changed
  • Enforce minimum font sizes on social media content cards for mobile legibility
  • Instagram images are 1080px but viewed at ~360px on phones (3× reduction).
  • Added FONT_SIZES constants (min 18px body, 22px primary, 30px section) and
  • applied across all three card types. Reduced visible items per card (5→4) to
  • compensate. Also excluded Prep and Cheerabilities divisions from score drops.

Files Changed

Modified (4):
  • ~ src/lib/content/brand.ts
  • ~ src/lib/content/score-drop.ts
  • ~ src/lib/content/weekend-preview.ts
  • ~ src/lib/content/weekly-roundup.ts

Version 0.2.177

Add calendar preview, upgrade CTA, feed rename, switch account, and mobile nav polish

April 1, 2026 at 6:46 PM GMT+0
9ebe5ef
Added
  • Add calendar preview, upgrade CTA, feed rename, switch account, and mobile nav polish
  • Competitions page: add calendar + upcoming events section above browse CTA
  • Home page: add Elite upgrade banner for free-tier authenticated users
  • Feed page: rename "Home" to "My Feed", remove "Restart setup" button
  • Settings: add Switch Account option to Account section
  • Mobile bottom nav: increase glass opacity for readability over dark images

Files Changed

Created (2):
  • + src/components/competitions/competition-calendar-preview.tsx
  • + src/components/hub/upgrade-cta-banner.tsx
Modified (6):
  • ~ src/app/competitions/page.tsx
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/app/page.tsx
  • ~ src/components/competitions/competition-calendar-preview.tsx
  • ~ src/components/hub/upgrade-cta-banner.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.176

Add upgrade-to-Pro CTA in sidebar for free-tier users

April 1, 2026 at 6:45 PM GMT+0
4606bc2
Added
  • Add upgrade-to-Pro CTA in sidebar for free-tier users

Files Changed

Modified (1):
  • ~ src/components/app-shell.tsx

Version 0.2.175

Redesign nav and competitions page: add My Feed, rename Schedules to Competitions

April 1, 2026 at 5:38 PM GMT+0
ff457e4
🔄Changed
  • Redesign nav and competitions page: add My Feed, rename Schedules to Competitions
  • Add "My Feed" to sidebar nav (auth users) linking to /dashboard/feed
  • Rename "Schedules" to "Competitions" in nav, pointing to /competitions
  • Remove "People" from auth nav (accessible via Discover)
  • Replace mobile bottom nav People with My Feed
  • Competitions page: featured hero cards + weekly timeline + browse CTA

Files Changed

Created (1):
  • + src/app/competitions/browse/page.tsx
Modified (4):
  • ~ src/app/competitions/browse/page.tsx
  • ~ src/app/competitions/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx

Version 0.2.174

Make Recent Top Scores cards clickable and hide scoreless competitions from Last Week

April 1, 2026 at 5:01 PM GMT+0
6490a52
🔄Changed
  • Make Recent Top Scores cards clickable and hide scoreless competitions from Last Week
  • Score ticker cards now link to the division scores page using a stretched-link pattern
  • Added competitionSlug/divisionSlug to ScoreTickerItem type and query
  • Last Week tab filters out competitions with zero performances
  • Watch link remains independently clickable above the card link

Files Changed

Modified (2):
  • ~ src/components/hub/score-ticker.tsx
  • ~ src/lib/hub-data.ts

Version 0.2.173

Improve hub home page: news layout, scores, podcasts, social ordering

April 1, 2026 at 2:42 PM GMT+0
d512e86
🔄Changed
  • Improve hub home page: news layout, scores, podcasts, social ordering
  • Recent Top Scores: show highest scores from most recent competitions, exclude Prep divisions
  • Cheer News: split articles with images (visual grid) from text-only (compact list)
  • Podcasts: increase to 12 episodes, interleave shows to avoid same show back-to-back
  • Social: sort FullOut entries to top of Follow the Community section
  • Hide broken IG gallery section (From The Cheer Community) until images are fixed

Files Changed

Modified (5):
  • ~ src/app/page.tsx
  • ~ src/components/hub/news-card.tsx
  • ~ src/components/hub/news-section.tsx
  • ~ src/components/hub/social-section.tsx
  • ~ src/lib/hub-data.ts

Version 0.2.172

Fix build: remove unused @ts-expect-error directives in image-renderer

April 1, 2026 at 2:41 PM GMT+0
7df1fa3
🐛Fixed
  • Fix build: remove unused @ts-expect-error directives in image-renderer
  • Vercel build failed because TypeScript flagged unused @ts-expect-error
  • directives — the underlying expressions don't actually produce TS errors.

Files Changed

Modified (1):
  • ~ src/lib/content/image-renderer.ts

Version 0.2.171

Simplify people page: replace filter sidebar with search box and grid/list toggle

March 31, 2026 at 6:30 PM GMT+0
f6f6ed2
🔄Changed
  • Simplify people page: replace filter sidebar with search box and grid/list toggle

Files Changed

Created (1):
  • + src/components/people/people-search-bar.tsx
Modified (2):
  • ~ src/app/people/page.tsx
  • ~ src/components/people/people-search-bar.tsx

Version 0.2.170

Add missing scores tab components that broke the build

March 31, 2026 at 3:07 PM GMT+0
8b15726
Added
  • Add missing scores tab components that broke the build
  • rankings-tab.tsx and competitions-tab.tsx were imported by
  • scores-tab-nav.tsx but never committed, causing build failure.

Files Changed

Created (2):
  • + src/components/scores/competitions-tab.tsx
  • + src/components/scores/rankings-tab.tsx
Modified (2):
  • ~ src/components/scores/competitions-tab.tsx
  • ~ src/components/scores/rankings-tab.tsx

Version 0.2.169

Add PCL team detail pages with season stats and news coverage

March 31, 2026 at 3:04 PM GMT+0
0e7ecc7
Added
  • Add PCL team detail pages with season stats and news coverage
  • Create /pcl/teams/[slug] pages with season stats (W-L, points, rank),
  • match-by-match results, notable performances, roster, and news
  • Add Founding Season PCL Substack RSS feed for PCL news coverage
  • Add News & Coverage section to PCL hub page
  • Update all PCL team links to use /pcl/teams/ routes

Files Changed

Created (1):
  • + src/app/pcl/teams/[slug]/page.tsx
Modified (6):
  • ~ scripts/setup/seed-rss-feeds.ts
  • ~ src/app/pcl/matches/[slug]/page.tsx
  • ~ src/app/pcl/page.tsx
  • ~ src/app/pcl/teams/[slug]/page.tsx
  • ~ src/components/hub/news-card.tsx
  • ~ src/components/pcl/pcl-standings.tsx

Version 0.2.168

Lazy-load scores tabs, auto-poll on empty feed, add Vercel ignoreCommand

March 30, 2026 at 11:58 PM GMT+0
bdee7b1
🔄Changed
  • Lazy-load scores tabs, auto-poll on empty feed, add Vercel ignoreCommand
  • Live scores feed: poll immediately on mount when no initial items provided
  • Scores tab nav: lazy-load Rankings and Competitions tabs (was static links)
  • vercel.json: add ignoreCommand to skip builds when only non-source files change

Files Changed

Modified (2):
  • ~ src/components/live/live-scores-feed.tsx
  • ~ src/components/scores/scores-tab-nav.tsx

Version 0.2.167

Add setup scripts for hub content management

March 30, 2026 at 9:35 PM GMT+0
5b6843b
Added
  • Add setup scripts for hub content management
  • Scripts for: fixing feed URLs, podcast feeds (iTunes API lookup),
  • IG profile pic matching, RSS thumbnail auditing, content state checks.

Files Changed

Created (7):
  • + scripts/setup/check-content-state.ts
  • + scripts/setup/check-ig-data.ts
  • + scripts/setup/check-rss-thumbs.ts
  • + scripts/setup/fetch-ig-profile-pics.ts
  • + scripts/setup/fix-feed-urls.ts
  • + scripts/setup/fix-podcast-feeds.ts
  • + scripts/setup/match-social-photos.ts
Modified (7):
  • ~ scripts/setup/check-content-state.ts
  • ~ scripts/setup/check-ig-data.ts
  • ~ scripts/setup/check-rss-thumbs.ts
  • ~ scripts/setup/fetch-ig-profile-pics.ts
  • ~ scripts/setup/fix-feed-urls.ts
  • ~ scripts/setup/fix-podcast-feeds.ts
  • ~ scripts/setup/match-social-photos.ts

Version 0.2.166

Add content blocks CMS, YouTube support, podcast fetch

March 30, 2026 at 7:21 PM GMT+0
62d47c8
Added
  • Add content blocks CMS, YouTube support, podcast fetch
  • Content block system:
  • HubContentBlock CRUD API (/api/admin/hub/blocks)
  • Admin UI: create/edit/delete/reorder blocks with type selector
  • (Custom HTML, YouTube Channel, CTA, Featured Content)
  • Display options: wide, half, square, carousel

Files Changed

Created (4):
  • + scripts/setup/trigger-hub-fetch.ts
  • + src/app/api/admin/hub/blocks/route.ts
  • + src/components/admin/hub/content-block-manager.tsx
  • + src/components/hub/content-block.tsx
Modified (9):
  • ~ scripts/setup/trigger-hub-fetch.ts
  • ~ src/app/admin/hub/page.tsx
  • ~ src/app/api/admin/hub/blocks/route.ts
  • ~ src/app/page.tsx
  • ~ src/components/admin/hub/content-block-manager.tsx
  • ~ src/components/admin/hub/rss-feed-manager.tsx
  • ~ src/components/hub/content-block.tsx
  • ~ src/lib/hub-data.ts
  • ~ src/lib/rss.ts

Version 0.2.165

Hub v2: visual overhaul, admin feed management, IG scraper, content blocks

March 30, 2026 at 2:58 PM GMT+0
ebcb4da
🔄Changed
  • Hub v2: visual overhaul, admin feed management, IG scraper, content blocks
  • Visual improvements:
  • Fix blurry Cheer Theory thumbnails (strip WP -150x150 size suffix)
  • Top Scores by Division: podium-style scorecards with gym photos,
  • placement badges, video links (L6+ only, top 3 per division)
  • Social section: compact two-column link list (no fake image cards)

Files Changed

Created (10):
  • + python-scraper/scraper/ig_post_scraper.py
  • + scripts/setup/add-hub-sections.ts
  • + scripts/setup/audit-hub-visuals.ts
  • + scripts/setup/fix-blurry-thumbnails.ts
  • + scripts/setup/seed-rss-feeds.ts
  • + src/app/api/admin/hub/feeds/route.ts
  • + src/components/admin/hub/podcast-manager.tsx
  • + src/components/admin/hub/rss-feed-manager.tsx
  • + src/components/hub/featured-gyms.tsx
  • + src/components/hub/ig-gallery.tsx
Modified (18):
  • ~ prisma/schema.prisma
  • ~ python-scraper/scraper/ig_post_scraper.py
  • ~ scripts/setup/add-hub-sections.ts
  • ~ scripts/setup/audit-hub-visuals.ts
  • ~ scripts/setup/fix-blurry-thumbnails.ts
  • ~ scripts/setup/seed-rss-feeds.ts
  • ~ src/app/admin/hub/page.tsx
  • ~ src/app/api/admin/hub/feeds/route.ts
  • ~ src/app/api/cron/fetch-hub-content/route.ts
  • ~ src/app/page.tsx
  • ~ src/components/admin/hub/podcast-manager.tsx
  • ~ src/components/admin/hub/rss-feed-manager.tsx
  • ~ src/components/hub/featured-gyms.tsx
  • ~ src/components/hub/ig-gallery.tsx
  • ~ src/components/hub/leaderboard-snapshot.tsx
  • ~ src/components/hub/social-section.tsx
  • ~ src/lib/hub-data.ts
  • ~ src/lib/rss.ts

Version 0.2.164

Add IG profile pics via unavatar.io + improve leaderboard display

March 30, 2026 at 4:54 AM GMT+0
bad2183
Added
  • Add IG profile pics via unavatar.io + improve leaderboard display
  • Social cards now pull Instagram profile pictures from unavatar.io
  • as a fallback when no imageUrl is set in the database
  • Bigger circular avatar overlays on gradient headers
  • Leaderboard query improved: picks divisions with most performances
  • (min 5) instead of random L6/L7 divisions

Files Changed

Modified (3):
  • ~ src/components/hub/leaderboard-snapshot.tsx
  • ~ src/components/hub/social-card.tsx
  • ~ src/lib/hub-data.ts

Version 0.2.163

Fix CSP for RSS images + hydration mismatch on date

March 30, 2026 at 4:45 AM GMT+0
6c08696
🐛Fixed
  • Fix CSP for RSS images + hydration mismatch on date
  • Open img-src to allow all https/http images (RSS thumbnails come
  • from arbitrary domains)
  • Pin HubHero date to America/Chicago timezone to prevent server/client
  • hydration mismatch

Files Changed

Modified (1):
  • ~ src/components/hub/hub-hero.tsx

Version 0.2.162

Fix hub 500: remove onClick handler from server component

March 30, 2026 at 4:31 AM GMT+0
7580e14
🐛Fixed
  • Fix hub 500: remove onClick handler from server component
  • ScoreTicker is rendered as a server component but had an onClick
  • event handler on an <a> tag. Event handlers can't be passed to
  • client component props from server components.

Files Changed

Modified (1):
  • ~ src/components/hub/score-ticker.tsx

Version 0.2.161

Fix hub 500: wrap ALL data fetches including getHubConfig in catch

March 30, 2026 at 4:21 AM GMT+0
f645e4e
🐛Fixed
  • Fix hub 500: wrap ALL data fetches including getHubConfig in catch
  • The error was happening before the safe() wrappers — getHubConfig()
  • and getSession() could throw and crash the entire page. Now every
  • single data fetch has a catch handler with fallback defaults.
  • Also added default section order when HubConfig is empty.

Files Changed

Modified (1):
  • ~ src/app/page.tsx

Version 0.2.160

Fix hub 500: wrap all data fetches in safe catch handlers

March 30, 2026 at 4:13 AM GMT+0
42af3ed
🐛Fixed
  • Fix hub 500: wrap all data fetches in safe catch handlers
  • Each hub section data fetch is now wrapped in try/catch so one failing
  • query doesn't crash the entire page. Failed sections silently render
  • empty instead of taking down the home page.

Files Changed

Modified (1):
  • ~ src/app/page.tsx

Version 0.2.159

Fix home page 500: remove invalid discFilter from competition query

March 30, 2026 at 4:00 AM GMT+0
2b2a5d0
🐛Fixed
  • Fix home page 500: remove invalid discFilter from competition query
  • Competition model doesn't have a Division relation, so spreading
  • activeDisciplineFilter() into the where clause caused a runtime error.
  • Removed the filter since competitions don't need discipline filtering
  • at the timeline level.

Files Changed

Modified (1):
  • ~ src/lib/hub-data.ts

Version 0.2.158

Visual overhaul: sharper corners, richer hub with images and scores

March 30, 2026 at 3:54 AM GMT+0
8b4cf65
🔄Changed
  • Visual overhaul: sharper corners, richer hub with images and scores
  • Reduce global border-radius from 0.75rem to 0.375rem (sharper, less soft)
  • Competition cards: show photo headers with gradient overlays, gym logos in scores
  • News section: featured hero card with big image for top article
  • Score ticker: ESPN-style horizontal scoreboard with gym logos, scores, video links
  • Leaderboard: gym logos, placement badges with color hierarchy

Files Changed

Created (1):
  • + src/components/hub/score-ticker.tsx
Modified (11):
  • ~ src/app/globals.css
  • ~ src/app/page.tsx
  • ~ src/components/hub/competition-card.tsx
  • ~ src/components/hub/leaderboard-snapshot.tsx
  • ~ src/components/hub/news-card.tsx
  • ~ src/components/hub/news-section.tsx
  • ~ src/components/hub/personalized-section.tsx
  • ~ src/components/hub/podcast-card.tsx
  • ~ src/components/hub/score-ticker.tsx
  • ~ src/components/hub/social-card.tsx
  • ~ src/lib/hub-data.ts

Version 0.2.157

Transform home page into content hub + simplify navigation

March 30, 2026 at 3:12 AM GMT+0
41ef07f
🔄Changed
  • Transform home page into content hub + simplify navigation
  • Replace SaaS landing page with "The Home of Competitive Cheer" content hub:
  • Competition timeline (last/this/next week with L6/L7 top scores)
  • Curated news from 8 cheer RSS feeds
  • Podcast episodes, social personality cards, leaderboard snapshot
  • Personalized "Your Teams" section for logged-in users

Files Changed

Created (20):
  • + scripts/setup/seed-hub-content.ts
  • + src/app/admin/hub/page.tsx
  • + src/app/api/admin/hub/featured/route.ts
  • + src/app/api/admin/hub/route.ts
  • + src/app/api/cron/fetch-hub-content/route.ts
  • + src/app/api/hub/competitions/route.ts
  • + src/app/discover/loading.tsx
  • + src/app/discover/page.tsx
  • + src/app/my/loading.tsx
  • + src/app/my/page.tsx
  • + src/app/scores/loading.tsx
  • + src/app/scores/page.tsx
  • + src/components/admin/hub/featured-competitions.tsx
  • + src/components/admin/hub/feed-source-toggles.tsx
  • + src/components/admin/hub/section-manager.tsx
  • + src/components/home-legacy/gyms-map-section.tsx
  • + src/components/home-legacy/hero-section.tsx
  • + src/components/home-legacy/live-scores-section.tsx
  • + src/components/home-legacy/pillar-section.tsx
  • + src/components/home-legacy/pillar-visuals.tsx
Modified (20):
  • ~ prisma/schema.prisma
  • ~ scripts/setup/seed-hub-content.ts
  • ~ src/app/admin/hub/page.tsx
  • ~ src/app/admin/page.tsx
  • ~ src/app/api/admin/hub/featured/route.ts
  • ~ src/app/api/admin/hub/route.ts
  • ~ src/app/api/cron/fetch-hub-content/route.ts
  • ~ src/app/api/hub/competitions/route.ts
  • ~ src/app/discover/loading.tsx
  • ~ src/app/discover/page.tsx
  • ~ src/app/home/page.tsx
  • ~ src/app/my/loading.tsx
  • ~ src/app/my/page.tsx
  • ~ src/app/page.tsx
  • ~ src/app/scores/loading.tsx
  • ~ src/app/scores/page.tsx
  • ~ src/components/admin/hub/featured-competitions.tsx
  • ~ src/components/admin/hub/feed-source-toggles.tsx
  • ~ src/components/admin/hub/section-manager.tsx
  • ~ src/components/app-shell.tsx

Version 0.2.156

Increase scraper timeouts and limit concurrent scrapes

March 29, 2026 at 10:12 PM GMT+0
5371aab
🔄Changed
  • Increase scraper timeouts and limit concurrent scrapes
  • JustDance Grand Nationals has 267+ divisions across 8 sub-events —
  • each takes 15-30 min to scrape. The 15-min stale threshold was reclaiming
  • jobs before the scraper finished, creating an infinite retry loop.
  • Increase stale threshold from 15 to 45 minutes
  • Increase recent job window from 30 to 45 minutes

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.155

Fix live monitor timeout: switch to fire-and-forget scrape with async harvest

March 29, 2026 at 9:45 PM GMT+0
b58a14c
🐛Fixed
  • Fix live monitor timeout: switch to fire-and-forget scrape with async harvest
  • The live monitor was waiting inline for scrape completion (3-min timeout).
  • Large events like JustDance Grand Nationals (267 divisions) take 10+ minutes
  • to scrape, causing every job to fail with "Scrape timeout" and no scores
  • imported — which means no score notifications fire.
  • New two-phase approach:

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.154

Fix score notifications not firing: add notifiedAt tracking to prevent silent skips

March 29, 2026 at 7:47 PM GMT+0
62fdb9c
🐛Fixed
  • Fix score notifications not firing: add notifiedAt tracking to prevent silent skips
  • Root cause: score change detection only fired when totalScore changed numerically.
  • If a score was already imported (by worker, manual import, or prior cycle), re-scraping
  • the same data produced no change — silently skipping all notifications.
  • Fix: Add notifiedAt field to Score model. Notifications now fire when:
  • totalScore actually changed (existing behavior), OR

Files Changed

Created (1):
  • + scripts/maintenance/backfill-notified-at.ts
Modified (5):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/backfill-notified-at.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/notifications/reminder-engine.ts
  • ~ src/lib/notifications/score-notifications.ts

Version 0.2.153

Fix mobile bottom nav floating mid-screen in WebView browsers

March 28, 2026 at 5:35 PM GMT+0
ff76906
🐛Fixed
  • Fix mobile bottom nav floating mid-screen in WebView browsers
  • Move MobileBottomNav out of AppShell (which is inside Framer Motion's
  • PageTransitionProvider context) and render it directly in root layout as
  • a sibling of Toaster/PushPrompt. This ensures no ancestor transform from
  • page transitions can break position:fixed, especially in in-app browsers
  • like Telegram's WebView.

Files Changed

Modified (2):
  • ~ src/app/layout.tsx
  • ~ src/components/app-shell.tsx

Version 0.2.152

Remove temporary VAPID debug endpoint

March 28, 2026 at 5:15 PM GMT+0
b1b31d3
🐛Fixed
  • Remove temporary VAPID debug endpoint

Files Changed

Modified (1):
  • ~ src/app/api/debug/vapid/route.ts

Version 0.2.151

Debug: add push send test to VAPID endpoint

March 28, 2026 at 5:11 PM GMT+0
3661710
🐛Fixed
  • Debug: add push send test to VAPID endpoint

Files Changed

Modified (1):
  • ~ src/app/api/debug/vapid/route.ts

Version 0.2.150

Add temporary VAPID debug endpoint

March 28, 2026 at 5:07 PM GMT+0
1f7069d
🐛Fixed
  • Add temporary VAPID debug endpoint

Files Changed

Created (1):
  • + src/app/api/debug/vapid/route.ts
Modified (1):
  • ~ src/app/api/debug/vapid/route.ts

Version 0.2.149

Add try/catch around push sends in score notifications

March 28, 2026 at 4:22 PM GMT+0
545307b
Added
  • Add try/catch around push sends in score notifications
  • Same fix as reminder engine — push errors were unhandled and could
  • crash the entire score notification flow, preventing email/SMS/telegram
  • from being sent for that score.

Files Changed

Modified (1):
  • ~ src/lib/notifications/score-notifications.ts

Version 0.2.148

Fix reminder engine: prevent duplicates and catch push errors

March 28, 2026 at 4:19 PM GMT+0
602046e
🐛Fixed
  • Fix reminder engine: prevent duplicates and catch push errors
  • Two bugs:
  • 1. Push send had no try/catch — if VAPID was misconfigured on prod,
  • the crash prevented SentReminder dedup rows from being written,
  • causing duplicate in-app notifications every cron cycle.
  • 2. Dedup was at the end after all sends. Moved it BEFORE sends so

Files Changed

Modified (1):
  • ~ src/lib/notifications/reminder-engine.ts

Version 0.2.147

Auto-resync push subscription with server on page load

March 28, 2026 at 2:42 PM GMT+0
22b38e1
🔄Changed
  • Auto-resync push subscription with server on page load
  • If the browser has a push subscription but the server lost the record
  • (e.g., deleted during cleanup), the hook now re-sends the subscription
  • data to /api/push/subscribe on every page load. This is an upsert so
  • it's safe to call repeatedly. Fixes the case where the UI shows push
  • as enabled but the server can't send because it has no subscription.

Files Changed

Modified (1):
  • ~ src/hooks/use-push-subscription.ts

Version 0.2.146

Auto-enable reminders when saving a schedule

March 28, 2026 at 1:43 PM GMT+0
38437d4
🔄Changed
  • Auto-enable reminders when saving a schedule
  • Previously, reminders were opt-in after save — users had to click
  • "Enable Reminders" on the success screen. Most users skipped this,
  • resulting in 22/25 saved schedules having 0 bells and no notifications.
  • Now bells are automatically created when a schedule is saved (for
  • eligible tiers). The success screen confirms reminders are on instead

Files Changed

Modified (1):
  • ~ src/components/schedules/save-schedule-dialog.tsx

Version 0.2.145

Fix push notification subscription pruning: only delete on 404/410

March 27, 2026 at 6:26 PM GMT+0
275ca9e
🐛Fixed
  • Fix push notification subscription pruning: only delete on 404/410
  • Previously, sendPushToUser deleted subscriptions on ANY send failure
  • (including VAPID misconfiguration, network errors, 401/403). This meant
  • a temporary server-side issue would permanently nuke all push subscriptions,
  • requiring users to manually re-subscribe.
  • Now sendPushNotification returns "ok" | "expired" | "error", and only

Files Changed

Modified (1):
  • ~ src/lib/push.ts

Version 0.2.144

Improve schedule filter performance: debounce search input

March 27, 2026 at 3:55 PM GMT+0
1961282
🔄Changed
  • Improve schedule filter performance: debounce search input
  • Add 400ms debounce to search filter input (was triggering API call per
  • keystroke — typing "Texas" fired 5 separate requests)
  • Remove availableOptions from fetchFilterOptions dependency array to
  • break circular re-fetch loop
  • Search now uses pendingSearch pattern matching state/city debounce

Files Changed

Modified (1):
  • ~ src/components/schedules/schedule-viewer.tsx

Version 0.2.143

Add schedule PDFs to public/uploads for download links

March 27, 2026 at 3:43 PM GMT+0
45c1521
Added
  • Add schedule PDFs to public/uploads for download links
  • Force-add the 4 schedule PDFs so they're served from Vercel.
  • Also optimize announcement image for Instagram mobile readability:
  • bigger title, simplified cards (name + date only), larger text throughout.

Version 0.2.142

Fix announcement image font: use satori + resvg for proper Bebas Neue rendering

March 27, 2026 at 3:26 PM GMT+0
b437d6a
🐛Fixed
  • Fix announcement image font: use satori + resvg for proper Bebas Neue rendering
  • node-canvas registerFont doesn't work on Windows. Switch to satori (same
  • engine as @vercel/og) which handles font embedding natively. Download
  • static Inter weights since satori can't parse variable font fvar tables.

Files Changed

Modified (1):
  • ~ scripts/generate-schedule-announcement.ts

Version 0.2.141

Add schedule PDF links to competition pages and generic schedule importer

March 27, 2026 at 3:20 PM GMT+0
6d6caff
Added
  • Add schedule PDF links to competition pages and generic schedule importer
  • Add Source and Schedule PDF links to competition header metadata line
  • Add PDF Schedule download link to schedule page header
  • Add generic schedule PDF import script handling multiple formats
  • (AC, ACDA, One Up, Spirit Sports) with fuzzy matching
  • Add Instagram announcement image generator matching scorecard style

Files Changed

Created (2):
  • + scripts/generate-schedule-announcement.ts
  • + scripts/import/import-schedule-generic.ts
Modified (5):
  • ~ scripts/generate-schedule-announcement.ts
  • ~ scripts/import/import-schedule-generic.ts
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/app/competitions/[id]/schedule/page.tsx
  • ~ src/components/competitions/competition-header.tsx

Version 0.2.140

Move analytics section above social copy templates on partner dashboard

March 27, 2026 at 2:51 PM GMT+0
cc805de
🔄Changed
  • Move analytics section above social copy templates on partner dashboard

Files Changed

Modified (1):
  • ~ src/components/partner/partner-dashboard.tsx

Version 0.2.139

Widen partner dashboard to max-w-5xl and add social copy templates

March 27, 2026 at 2:38 PM GMT+0
e8964de
🔄Changed
  • Widen partner dashboard to max-w-5xl and add social copy templates

Files Changed

Modified (1):
  • ~ src/app/admin/partners/[id]/dashboard/page.tsx

Version 0.2.138

Fix delete button being clipped by overflow-hidden on profile content cards

March 27, 2026 at 12:07 AM GMT+0
d9ea0b6
🐛Fixed
  • Fix delete button being clipped by overflow-hidden on profile content cards

Files Changed

Modified (1):
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.137

Add value prop, 30-second pitch, and social copy templates to partner dashboard

March 26, 2026 at 11:15 PM GMT+0
7682f93
Added
  • Add value prop, 30-second pitch, and social copy templates to partner dashboard
  • Highlights what the audience gets (first month free / up to 20% off annual)
  • Adds a ready-to-use 30-second pitch partners can use in conversations
  • Includes 4 copy-paste social templates: social post, YouTube description,
  • newsletter CTA, and short link-in-bio CTA
  • Enhanced referral link card with clearer discount explanation

Files Changed

Modified (1):
  • ~ src/components/partner/partner-dashboard.tsx

Version 0.2.136

Fix mobile video decode errors by limiting resolution and deferring preload

March 26, 2026 at 11:06 PM GMT+0
dbd5802
🐛Fixed
  • Fix mobile video decode errors by limiting resolution and deferring preload
  • Adds maxResolution=720p and preload=none to prevent multiple videos from
  • overwhelming mobile device decoders simultaneously.

Files Changed

Modified (1):
  • ~ src/components/profile/profile-video-player.tsx

Version 0.2.135

Add partner exclusive offers: free trial on monthly, discount on annual

March 26, 2026 at 10:48 PM GMT+0
c6eec9a
Added
  • Add partner exclusive offers: free trial on monthly, discount on annual
  • Monthly plans: auto-apply trial_period_days (default 30) via Stripe
  • Annual plans: auto-apply percentage discount coupon (default 10% ≈ 1 extra month free)
  • Subscribe page shows offer banner: "FullOut exclusive offer — first 30 days free!"
  • New Partner fields: trialDays, annualDiscountPct (configurable per partner)
  • Edit partner dialog includes offer settings

Files Changed

Modified (9):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/partners/[id]/page.tsx
  • ~ src/app/api/admin/partners/[id]/route.ts
  • ~ src/app/api/partner/dashboard/analytics/route.ts
  • ~ src/app/api/partner/validate/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/components/admin/partners/edit-partner-dialog.tsx
  • ~ src/components/partner/partner-analytics.tsx

Version 0.2.134

Show partner referral banner on subscribe page when arriving via partner link

March 26, 2026 at 10:29 PM GMT+0
507915b
🔄Changed
  • Show partner referral banner on subscribe page when arriving via partner link
  • Displays "Referred by [Partner Name]" banner so visitors know the partner link worked.

Files Changed

Modified (1):
  • ~ src/app/subscribe/subscribe-page-client.tsx

Version 0.2.133

Add admin partner dashboard preview and edit settings dialog

March 26, 2026 at 10:27 PM GMT+0
d2618a2
Added
  • Add admin partner dashboard preview and edit settings dialog
  • Admin can view partner's dashboard at /admin/partners/[id]/dashboard
  • Edit Settings dialog on partner detail page (commission, status, payout, etc.)
  • Partner APIs support admin access via partnerId query param

Files Changed

Created (2):
  • + src/app/admin/partners/[id]/dashboard/page.tsx
  • + src/components/admin/partners/edit-partner-dialog.tsx
Modified (9):
  • ~ src/app/admin/partners/[id]/dashboard/page.tsx
  • ~ src/app/admin/partners/[id]/page.tsx
  • ~ src/app/api/partner/dashboard/analytics/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/route.ts
  • ~ src/app/api/partner/dashboard/stats/route.ts
  • ~ src/components/admin/partners/edit-partner-dialog.tsx
  • ~ src/components/partner/partner-analytics.tsx
  • ~ src/components/partner/partner-campaigns.tsx
  • ~ src/components/partner/partner-dashboard.tsx

Version 0.2.132

Organize admin dashboard into labeled sections alphabetized by title

March 26, 2026 at 10:22 PM GMT+0
81a30b9
🔄Changed
  • Organize admin dashboard into labeled sections alphabetized by title
  • Sections: Business, Content, Competition Data, People & Organizations, System

Files Changed

Modified (1):
  • ~ src/app/admin/page.tsx

Version 0.2.131

Add partner referral system with analytics, campaigns, payouts, and OG tags

March 26, 2026 at 10:14 PM GMT+0
26a548b
Added
  • Add partner referral system with analytics, campaigns, payouts, and OG tags
  • Full partner/affiliate system for media partners with monetary compensation:
  • Partner dashboard with analytics charts (clicks, revenue, sources, date ranges)
  • Partner-facing campaign management with custom OG image uploads
  • Dynamic OG meta tags on subscribe page for partner/campaign links
  • Banner templates and HTML embed code for partner marketing

Files Changed

Created (20):
  • + src/app/admin/partners/[id]/page.tsx
  • + src/app/admin/partners/page.tsx
  • + src/app/api/admin/partners/[id]/campaigns/route.ts
  • + src/app/api/admin/partners/[id]/payouts/route.ts
  • + src/app/api/admin/partners/[id]/route.ts
  • + src/app/api/admin/partners/route.ts
  • + src/app/api/admin/partners/stats/route.ts
  • + src/app/api/partner/dashboard/analytics/route.ts
  • + src/app/api/partner/dashboard/campaigns/[id]/route.ts
  • + src/app/api/partner/dashboard/campaigns/route.ts
  • + src/app/api/partner/dashboard/campaigns/upload-og/route.ts
  • + src/app/api/partner/dashboard/payout-method/route.ts
  • + src/app/api/partner/dashboard/stats/route.ts
  • + src/app/api/partner/dashboard/stripe-connect/route.ts
  • + src/app/api/partner/track/route.ts
  • + src/app/api/partner/validate/route.ts
  • + src/components/admin/partner-actions.tsx
  • + src/components/admin/partner-form.tsx
  • + src/components/admin/partners/create-payout-dialog.tsx
  • + src/components/partner/partner-analytics.tsx
Modified (20):
  • ~ src/app/admin/page.tsx
  • ~ src/app/admin/partners/[id]/page.tsx
  • ~ src/app/admin/partners/page.tsx
  • ~ src/app/api/admin/partners/[id]/campaigns/route.ts
  • ~ src/app/api/admin/partners/[id]/payouts/route.ts
  • ~ src/app/api/admin/partners/[id]/route.ts
  • ~ src/app/api/admin/partners/route.ts
  • ~ src/app/api/admin/partners/stats/route.ts
  • ~ src/app/api/partner/dashboard/analytics/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/[id]/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/route.ts
  • ~ src/app/api/partner/dashboard/campaigns/upload-og/route.ts
  • ~ src/app/api/partner/dashboard/payout-method/route.ts
  • ~ src/app/api/partner/dashboard/stats/route.ts
  • ~ src/app/api/partner/dashboard/stripe-connect/route.ts
  • ~ src/app/api/partner/track/route.ts
  • ~ src/app/api/partner/validate/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/settings/page.tsx
  • ~ src/app/subscribe/page.tsx

Version 0.2.130

Add partner referral system, video description editing, and settings updates

March 26, 2026 at 9:33 PM GMT+0
6076a1f
Added
  • Add partner referral system, video description editing, and settings updates
  • Includes partner tracking endpoints, Stripe webhook handling for partner
  • commissions, video description support, and partner settings nav item.

Files Changed

Modified (10):
  • ~ prisma/schema.prisma
  • ~ src/app/api/person/videos/route.ts
  • ~ src/app/api/stripe/create-checkout/route.ts
  • ~ src/app/api/stripe/webhook/route.ts
  • ~ src/app/settings/page.tsx
  • ~ src/app/subscribe/subscribe-page-client.tsx
  • ~ src/components/profile/profile-video-manager.tsx
  • ~ src/components/settings/settings-layout.tsx
  • ~ src/components/settings/settings-nav.tsx
  • ~ src/middleware.ts

Version 0.2.129

Remove skills, badges, timeline, and experience from home feed to reduce spam

March 26, 2026 at 6:44 PM GMT+0
c36a433
🗑️Removed
  • Remove skills, badges, timeline, and experience from home feed to reduce spam
  • Also adds debug logging to Resend email sending for password reset troubleshooting.

Files Changed

Modified (3):
  • ~ src/app/api/feed/route.ts
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.128

Add debug logging to Resend email sending for password reset troubleshooting

March 26, 2026 at 5:49 PM GMT+0
6535bfb
🐛Fixed
  • Add debug logging to Resend email sending for password reset troubleshooting

Files Changed

Modified (2):
  • ~ src/app/api/auth/forgot-password/route.ts
  • ~ src/lib/resend.ts

Version 0.2.127

Fix broken profile pics on admin users page by using Avatar component

March 26, 2026 at 5:33 PM GMT+0
bcd166f
🐛Fixed
  • Fix broken profile pics on admin users page by using Avatar component
  • Replaced raw <img> tag with shadcn Avatar component which gracefully
  • falls back to showing the user's initial when the image URL fails to load.

Files Changed

Modified (1):
  • ~ src/app/admin/users/page.tsx

Version 0.2.126

Fix mobile timeline: add proper vertical timeline with chronological skills

March 26, 2026 at 3:47 PM GMT+0
740d109
🐛Fixed
  • Fix mobile timeline: add proper vertical timeline with chronological skills
  • Mobile view was just stacked cards with skills dumped as undated pills at
  • the bottom. Now renders a true vertical timeline with year markers,
  • experience cards connected by dots, and skills/badges placed inline at
  • their correct chronological position with dates shown.

Files Changed

Modified (1):
  • ~ src/components/people/person-timeline-viz.tsx

Version 0.2.125

Fix team selection UX in Add Experience dialog

March 26, 2026 at 3:27 PM GMT+0
c766748
🐛Fixed
  • Fix team selection UX in Add Experience dialog
  • Hide dropdown after selecting a team (like gym selector does)
  • Show selected team name in search field with clear button
  • Skip unnecessary re-fetches when team is already selected

Files Changed

Modified (1):
  • ~ src/components/people/person-experience.tsx

Version 0.2.124

Fix gym and team search in Add Experience dialog

March 26, 2026 at 3:16 PM GMT+0
b9a08eb
🐛Fixed
  • Fix gym and team search in Add Experience dialog
  • API returns results under `data.data` but component was reading
  • `data.gyms` and `data.teams`, causing searches to always return empty.

Files Changed

Modified (1):
  • ~ src/components/people/person-experience.tsx

Version 0.2.123

Add username column, profile pic, profile links, and username search to User Management

March 26, 2026 at 3:04 PM GMT+0
1ec2976
Added
  • Add username column, profile pic, profile links, and username search to User Management

Files Changed

Modified (1):
  • ~ src/app/admin/users/page.tsx

Version 0.2.122

Fix build: remove reference to non-existent partnerConversion model

March 26, 2026 at 2:48 PM GMT+0
730ead9
🐛Fixed
  • Fix build: remove reference to non-existent partnerConversion model
  • The PartnerConversion model hasn't been added to the schema yet,
  • so this deleteMany call was causing a type error during build.

Files Changed

Modified (1):
  • ~ src/app/api/admin/users/[id]/route.ts

Version 0.2.121

Remove highlights from explore page search results

March 26, 2026 at 2:44 PM GMT+0
4132157
🗑️Removed
  • Remove highlights from explore page search results

Files Changed

Modified (1):
  • ~ src/app/explore/page.tsx

Version 0.2.120

Add admin ability to delete user accounts from User Management

March 26, 2026 at 2:35 PM GMT+0
8b73902
Added
  • Add admin ability to delete user accounts from User Management
  • Adds DELETE endpoint with safety guards (can't delete self or other admins),
  • cascading cleanup for blocking relations, and a confirmation dialog in the UI.

Files Changed

Modified (3):
  • ~ src/app/admin/users/page.tsx
  • ~ src/app/api/admin/users/[id]/route.ts
  • ~ src/components/admin/user-edit-form.tsx

Version 0.2.119

Fix ESLint build error: remove reference to unconfigured rule

March 23, 2026 at 8:06 PM GMT+0
7858067
🐛Fixed
  • Fix ESLint build error: remove reference to unconfigured rule
  • Remove eslint-disable comment for @typescript-eslint/no-explicit-any
  • (not configured in project) and replace `any` with proper types.

Files Changed

Modified (1):
  • ~ src/components/density/density-wins-scatter.tsx

Version 0.2.118

Add density map page with geocoded gym locations

March 23, 2026 at 7:03 PM GMT+0
2b371bb
Added
  • Add density map page with geocoded gym locations
  • New /analyze/density page with per-sq-mi heatmap visualization
  • Interactive MapLibre heatmap with athletes/gyms/teams layers
  • Clickable gym dots with dark-themed popups showing gym details
  • Metro area rankings table grouped by city, expandable to show gyms
  • Density vs competitive success scatter plot

Files Changed

Created (11):
  • + scripts/maintenance/fix-gym-city-from-coords.ts
  • + scripts/maintenance/fix-gym-locations-fast.ts
  • + scripts/maintenance/fix-gym-locations.ts
  • + src/app/[username]/analyze/density/page.tsx
  • + src/app/api/gyms/density/route.ts
  • + src/components/density/density-heatmap-wrapper.tsx
  • + src/components/density/density-heatmap.tsx
  • + src/components/density/density-page-client.tsx
  • + src/components/density/density-wins-scatter.tsx
  • + src/components/density/haversine.ts
  • + src/components/density/metro-rankings.tsx
Modified (14):
  • ~ scripts/maintenance/fix-gym-city-from-coords.ts
  • ~ scripts/maintenance/fix-gym-locations-fast.ts
  • ~ scripts/maintenance/fix-gym-locations.ts
  • ~ src/app/[username]/analyze/density/page.tsx
  • ~ src/app/api/gyms/density/route.ts
  • ~ src/app/globals.css
  • ~ src/components/dashboard/dashboard-client.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/density/density-heatmap-wrapper.tsx
  • ~ src/components/density/density-heatmap.tsx
  • ~ src/components/density/density-page-client.tsx
  • ~ src/components/density/density-wins-scatter.tsx
  • ~ src/components/density/haversine.ts
  • ~ src/components/density/metro-rankings.tsx

Version 0.2.117

Fix hydration mismatch in FollowButton SVG icons

March 23, 2026 at 6:04 PM GMT+0
3da00c5
🐛Fixed
  • Fix hydration mismatch in FollowButton SVG icons
  • Lucide SVGs inside buttons caused server/client mismatch because
  • useSession returns different status during SSR vs client hydration.
  • Defer icon rendering until after mount to prevent the error.

Files Changed

Modified (1):
  • ~ src/components/follow-button.tsx

Version 0.2.116

Add post dialog, compose page, density map link, and misc improvements

March 23, 2026 at 2:31 AM GMT+0
6a6fed1
Added
  • Add post dialog, compose page, density map link, and misc improvements
  • Post dialog: sidebar "Post" button opens modal with PostForm (desktop)
  • Compose page: /compose route for mobile post creation
  • Post-info API: lazy-loads user tier/media permissions for post dialog
  • Density map: link added to analyze page header
  • Feed: remove PostContent card from feed page (moved to dialog)

Files Changed

Created (4):
  • + src/app/api/person/post-info/route.ts
  • + src/app/compose/compose-client.tsx
  • + src/app/compose/page.tsx
  • + src/components/dashboard/post-dialog.tsx
Modified (13):
  • ~ scripts/check-user-tier.ts
  • ~ src/app/[username]/analyze/page.tsx
  • ~ src/app/api/person/post-info/route.ts
  • ~ src/app/compose/compose-client.tsx
  • ~ src/app/compose/page.tsx
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/dashboard/post-content.tsx
  • ~ src/components/dashboard/post-dialog.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/people/person-profile-edit.tsx
  • ~ src/lib/import/gym-matcher.ts

Version 0.2.115

Fix following count: show all follows, not just people

March 23, 2026 at 2:25 AM GMT+0
7a9b7e4
🐛Fixed
  • Fix following count: show all follows, not just people
  • Reverts the PERSON-only filter — users expect the following count
  • to include teams, gyms, and competitions they follow too.

Files Changed

Modified (1):
  • ~ src/app/people/[username]/page.tsx

Version 0.2.114

Add cover photo API route and 3:1 banner aspect ratio

March 23, 2026 at 2:16 AM GMT+0
1cdd3a3
Added
  • Add cover photo API route and 3:1 banner aspect ratio
  • Required by the cover photo component committed in the previous
  • commit. Adds the upload/delete API and the LANDSCAPE_3_1 crop option.

Files Changed

Created (1):
  • + src/app/api/person/cover-photo/route.ts
Modified (2):
  • ~ src/app/api/person/cover-photo/route.ts
  • ~ src/types/aspect-ratios.ts

Version 0.2.113

Include cover photo component with canEdit/personId props

March 23, 2026 at 2:15 AM GMT+0
d9b68c0
🔄Changed
  • Include cover photo component with canEdit/personId props
  • The previous commit updated the page to pass these props but
  • didn't include the component changes, breaking the build.

Files Changed

Modified (1):
  • ~ src/components/profile/profile-cover-photo.tsx

Version 0.2.112

Fix follow system: correct following count and unique constraint

March 23, 2026 at 2:11 AM GMT+0
aacb31c
🐛Fixed
  • Fix follow system: correct following count and unique constraint
  • Following count now only counts person-to-person follows (was
  • inflating count with teams, gyms, competitions, choreographers)
  • Fix unique constraint on Follow model: use userId instead of
  • profileId (profileId was always NULL, making constraint useless)
  • Backfilled auto-follows: all 153 existing users now follow @joe

Files Changed

Modified (2):
  • ~ prisma/schema.prisma
  • ~ src/app/people/[username]/page.tsx

Version 0.2.111

Fix live monitor stalling: auto-reclaim stuck scrape jobs

March 22, 2026 at 9:43 PM GMT+0
b41d284
🐛Fixed
  • Fix live monitor stalling: auto-reclaim stuck scrape jobs
  • The live monitor was completely blocked because scrape jobs stuck in
  • SCRAPING status prevented new scrapes for all competitions. Root cause:
  • the poll loop (15 min max) exceeded Vercel's 5-min function timeout,
  • so jobs never got marked FAILED, and the 30-min dedup guard blocked
  • all subsequent cycles.

Files Changed

Modified (1):
  • ~ src/lib/live-monitor.ts

Version 0.2.110

Constrain home feed to 600px max width on desktop

March 22, 2026 at 2:51 AM GMT+0
8e3ca4b
🔄Changed
  • Constrain home feed to 600px max width on desktop
  • Match Twitter/X-style narrow feed layout on desktop while keeping
  • full width on mobile. Also fix username casing preservation on
  • profile updates (no longer lowercases on save).

Files Changed

Modified (1):
  • ~ src/app/dashboard/feed/page.tsx

Version 0.2.109

Fix username casing: preserve original case on profile update

March 22, 2026 at 2:39 AM GMT+0
a3a6344
🐛Fixed
  • Fix username casing: preserve original case on profile update
  • The person update endpoint was lowercasing usernames via
  • normalizeUsername() on save. Now preserves original casing while
  • still doing case-insensitive uniqueness checks.

Files Changed

Modified (1):
  • ~ src/app/api/person/[id]/route.ts

Version 0.2.108

Fix cover photo: use 3:1 Twitter ratio and stop using profile pic

March 22, 2026 at 2:17 AM GMT+0
cd2aa33
🐛Fixed
  • Fix cover photo: use 3:1 Twitter ratio and stop using profile pic
  • Cover photo now crops to 3:1 aspect ratio (matching Twitter/X) instead
  • of 4:5 portrait. Uses highlighted or first uploaded photo from gallery
  • instead of the profile picture.

Files Changed

Modified (2):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-cover-photo.tsx

Version 0.2.107

Add auto follow-back from @FullOut to new users on registration

March 22, 2026 at 2:16 AM GMT+0
d8458a0
Added
  • Add auto follow-back from @FullOut to new users on registration
  • When a new account is created, @FullOut now automatically follows
  • the new user back, creating a mutual follow relationship.

Files Changed

Modified (1):
  • ~ src/app/api/auth/register/route.ts

Version 0.2.106

Fix missing slug fields in division scorecard serialization

March 22, 2026 at 2:02 AM GMT+0
50d5a77
🐛Fixed
  • Fix missing slug fields in division scorecard serialization
  • Team and gym objects passed to the scorecard component were missing
  • slug fields, causing getTeamUrl/getGymUrl to fall back to raw IDs
  • instead of readable slugs.

Files Changed

Modified (2):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/components/competitions/division-scorecard.tsx

Version 0.2.105

Add caption display to post permalink page

March 22, 2026 at 1:59 AM GMT+0
d1c6155
Added
  • Add caption display to post permalink page
  • Photo captions and video descriptions now render on the /post/[id]
  • page using the CaptionDisplay component with @mention support.

Files Changed

Modified (1):
  • ~ src/app/post/[id]/page.tsx

Version 0.2.104

Add color-coded category groups to scorecard headers

March 22, 2026 at 1:34 AM GMT+0
fe9911e
Added
  • Add color-coded category groups to scorecard headers
  • Division and team scorecard tables now show 3-row headers matching the
  • analyze page: color-coded group labels (Building/Tumbling/Performance),
  • full column names, and abbreviated sort headers. Body cells are tinted
  • to match their category group.

Files Changed

Modified (3):
  • ~ src/components/competitions/division-scorecard.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/lib/breakdown-keys.ts

Version 0.2.103

Add share scorecard feature for Elite+ users

March 22, 2026 at 1:33 AM GMT+0
0b128bb
Added
  • Add share scorecard feature for Elite+ users
  • Allow Elite and Pro tier users to generate and share division scorecard
  • PNG images to social media. Uses Web Share API on mobile (native share
  • sheet for Instagram, TikTok, etc.) with download fallback on desktop.

Files Changed

Created (2):
  • + src/app/api/competitions/[id]/scorecard/route.ts
  • + src/components/competitions/share-scorecard-button.tsx
Modified (5):
  • ~ src/app/api/competitions/[id]/scorecard/route.ts
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/components/competitions/share-scorecard-button.tsx
  • ~ src/lib/tiers-config.ts
  • ~ src/lib/tiers.ts

Version 0.2.102

Improve video upload error handling for Mux asset limits

March 22, 2026 at 12:21 AM GMT+0
d167ed5
🔄Changed
  • Improve video upload error handling for Mux asset limits
  • Surface actual Mux error messages instead of generic "Internal server
  • error" and detect asset limit errors with a user-friendly message.
  • Remove invalid timeout parameter from Mux upload create call.

Files Changed

Modified (1):
  • ~ src/app/api/person/videos/route.ts

Version 0.2.101

Add update mode option to import pipeline

March 21, 2026 at 7:24 PM GMT+0
8e63de2
Added
  • Add update mode option to import pipeline
  • Supports create-only (skip existing), fill-empty (only fill null fields),
  • and overwrite (default) modes for importScrapedEvent, enabling selective
  • rescrapes that fill gaps without clobbering existing data.

Files Changed

Modified (1):
  • ~ src/lib/import/index.ts

Version 0.2.100

Add gym history tracking and alias-based matching

March 21, 2026 at 7:24 PM GMT+0
20dbd2c
Added
  • Add gym history tracking and alias-based matching
  • Adds GymHistory and GymAlias schema models for tracking rebrands/mergers.
  • Gym and team pages display a history badge when history exists. Import
  • pipeline preloads aliases so old brand names resolve to the correct gym.

Files Changed

Created (1):
  • + src/components/gyms/gym-history-badge.tsx
Modified (5):
  • ~ prisma/schema.prisma
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/gyms/gym-history-badge.tsx
  • ~ src/lib/import/gym-matcher.ts

Version 0.2.99

Add score notifications for saved schedule teams

March 21, 2026 at 6:41 PM GMT+0
a6fa0c4
Added
  • Add score notifications for saved schedule teams
  • Users with schedule entry bells now receive score notifications when their
  • saved teams post scores, scoped to the specific competition.

Files Changed

Modified (1):
  • ~ src/lib/notifications/score-notifications.ts

Version 0.2.98

Fix home feed post: show photo preview in caption step and use upchunk for video

March 21, 2026 at 4:32 PM GMT+0
79e3d10
🐛Fixed
  • Fix home feed post: show photo preview in caption step and use upchunk for video
  • The Post Content widget on the home feed was missing the photo preview
  • during the caption step — now shows the cropped image before upload.
  • Also replaced raw XHR video upload with the same upchunk chunked uploader
  • used on the profile page (1MB chunks on iOS, retries, FileReader fallback).

Files Changed

Modified (1):
  • ~ src/components/dashboard/post-content.tsx

Version 0.2.97

Add "This Week" section to schedules and remove inconsistent discipline badge

March 21, 2026 at 4:22 PM GMT+0
a83a2e1
Added
  • Add "This Week" section to schedules and remove inconsistent discipline badge
  • Schedules page now has three sections: "This Week" (currently happening +
  • starting within 7 days), "Upcoming Events", and "Past Events". Multi-day
  • events that started before today but haven't ended are no longer shown
  • as "Past Events."
  • Also removed the discipline badge from competition cards since it's only

Files Changed

Modified (4):
  • ~ src/app/[username]/schedules/page.tsx
  • ~ src/app/schedules/page.tsx
  • ~ src/components/competitions/competitions-list-client.tsx
  • ~ src/components/schedules/schedules-list-client.tsx

Version 0.2.96

Remove deleted items from feed instantly without refresh

March 21, 2026 at 4:11 PM GMT+0
078f877
🗑️Removed
  • Remove deleted items from feed instantly without refresh
  • Added onDeleted callback to MediaDeleteButton that removes the item
  • from the feed list's client state immediately after successful delete.
  • No more manual page refresh needed.

Files Changed

Modified (2):
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/profile/media-delete-button.tsx

Version 0.2.95

Add delete button for owned photos/videos in home feed

March 21, 2026 at 3:59 PM GMT+0
59e203f
Added
  • Add delete button for owned photos/videos in home feed
  • Users can now delete their own photos and videos directly from the home
  • feed without navigating to their profile page. The feed API now includes
  • personId and isOwner fields for media items, and the feed list renders
  • a delete button (trash icon) for owned content.

Files Changed

Modified (3):
  • ~ src/app/api/feed/route.ts
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.94

Fix video in feed navigating to post page instead of playing inline

March 21, 2026 at 2:57 PM GMT+0
a034766
🐛Fixed
  • Fix video in feed navigating to post page instead of playing inline
  • The card onClick handler was navigating to /post/{id} when clicking
  • anywhere on the card, including the Mux video player. Now ignores
  • clicks on interactive elements (video, mux-player, buttons, links)
  • so videos play inline in the feed.

Files Changed

Modified (1):
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.93

Fix video upload: add Mux domains to Content-Security-Policy

March 21, 2026 at 2:44 PM GMT+0
60e660d
🐛Fixed
  • Fix video upload: add Mux domains to Content-Security-Policy
  • The CSP connect-src was missing storage.googleapis.com and *.mux.com,
  • causing the browser to block upchunk's XHR PUT requests to Mux's upload
  • endpoint with status code 0. This was the root cause of all iPhone PWA
  • video upload failures.
  • Also added Mux domains to img-src, frame-src, and media-src for

Version 0.2.92

Show uploads instantly (optimistic UI) and fix iPhone PWA video uploads

March 21, 2026 at 2:22 PM GMT+0
f52654f
🔄Changed
  • Show uploads instantly (optimistic UI) and fix iPhone PWA video uploads
  • Photos and videos now appear in the feed immediately after upload instead
  • of requiring a manual page refresh. Uses optimistic state that deduplicates
  • against server data when router.refresh() completes.
  • For iPhone PWA video uploads: reduced chunk size to 1MB, increased retries
  • to 15, and enabled useLargeFileWorkaround (FileReader fallback instead of

Files Changed

Modified (1):
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.91

Fix @mention crash in captions and improve iPhone PWA video upload reliability

March 21, 2026 at 2:02 PM GMT+0
c30f5b8
🐛Fixed
  • Fix @mention crash in captions and improve iPhone PWA video upload reliability
  • Caption @mention crashed because the search API returns `name` (combined) but
  • the component expected separate `firstName`/`lastName` fields — accessing
  • `undefined[0]` for avatar initials threw a TypeError. Also hardened the post
  • page initials against null names.
  • Video uploads on iPhone PWA were failing with "server responded with 0" due to

Files Changed

Modified (3):
  • ~ src/app/post/[id]/page.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/ui/caption-input.tsx

Version 0.2.90

Fix video upload CORS for iPhone/iPad and add step diagnostics

March 20, 2026 at 11:59 PM GMT+0
fde68e4
🐛Fixed
  • Fix video upload CORS for iPhone/iPad and add step diagnostics
  • Use cors_origin: "*" for Mux uploads — the upload URL is single-use
  • and short-lived, so wildcard is safe. Fixes CORS mismatch when origin
  • header is missing (PWA mode) or differs (www vs non-www).
  • Add step tracking to video upload (file-check → create-upload →
  • mux-upload) so error toasts show exactly which step failed.

Files Changed

Modified (2):
  • ~ src/app/api/person/videos/route.ts
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.89

Fix iPhone video upload failure and improve upload UX

March 20, 2026 at 10:37 PM GMT+0
65732be
🐛Fixed
  • Fix iPhone video upload failure and improve upload UX
  • Add file readability check before upload to catch Safari stale File references
  • Add zero-size file check for iOS HEVC transcoding edge case
  • Show photo/video preview in caption step before posting
  • Change button from "Upload" to "Post" with Send icon
  • Generate video thumbnail preview (frame at 0.5s) when file is selected

Files Changed

Modified (1):
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.88

Fix PDF scorecard links blocked by popup blocker

March 20, 2026 at 7:12 PM GMT+0
c8a670c
🐛Fixed
  • Fix PDF scorecard links blocked by popup blocker
  • window.open() after an async fetch() is blocked by popup blockers on
  • most browsers. Now opens the window synchronously before the fetch,
  • then updates its location with the signed URL once received.

Files Changed

Modified (2):
  • ~ src/components/competitions/division-scorecard.tsx
  • ~ src/components/teams/competition-performance-table.tsx

Version 0.2.87

Remove temporary debug step tracking from upload error toasts

March 20, 2026 at 5:41 PM GMT+0
989b66d
🐛Fixed
  • Remove temporary debug step tracking from upload error toasts

Files Changed

Modified (1):
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.86

Replace XHR video upload with Mux chunked uploader for mobile Safari

March 20, 2026 at 5:32 PM GMT+0
c0839a6
🔄Changed
  • Replace XHR video upload with Mux chunked uploader for mobile Safari
  • Mobile Safari drops XHR PUT connections for large video files, causing
  • "Upload network error" on iPhone/iPad. Now uses @mux/upchunk which
  • splits files into 5MB chunks — much more reliable on mobile connections.

Files Changed

Modified (2):
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-video-manager.tsx

Version 0.2.85

Add step-by-step debug info to upload error toasts for iPad diagnosis

March 20, 2026 at 5:01 PM GMT+0
f8af4f1
🐛Fixed
  • Add step-by-step debug info to upload error toasts for iPad diagnosis
  • Temporary diagnostic: error toast now shows [step:X, type:Y, name:Z]
  • so we can identify exactly where iPad Safari throws.

Files Changed

Modified (1):
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.84

Convert HEIC to JPEG client-side before upload to fix iPad Safari failures

March 20, 2026 at 4:05 PM GMT+0
b65a4dc
🔄Changed
  • Convert HEIC to JPEG client-side before upload to fix iPad Safari failures
  • The actual cause of "string did not match expected pattern" on iPad is
  • Safari failing to serialize raw HEIC File objects in FormData for fetch().
  • Now all photo uploads convert to JPEG via canvas before sending, which:
  • Fixes iPad Safari HEIC upload failures
  • Reduces upload size (HEIC → compressed JPEG)

Files Changed

Modified (3):
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-picture-upload.tsx
  • ~ src/components/settings/avatar-upload.tsx

Version 0.2.83

Add HEIC support and extension fallback to all image upload endpoints

March 20, 2026 at 3:56 PM GMT+0
6630f27
Added
  • Add HEIC support and extension fallback to all image upload endpoints
  • iPad Safari sends empty file.type for HEIC/HEIF photos. All 6 image
  • upload endpoints now check file extension as fallback and accept HEIC/HEIF
  • (Sharp converts to JPEG on output).
  • Endpoints fixed:
  • /api/person/profile-picture

Files Changed

Modified (6):
  • ~ src/app/api/admin/profile-picture/route.ts
  • ~ src/app/api/choreographers/[id]/logo/route.ts
  • ~ src/app/api/coaches/[id]/photo/route.ts
  • ~ src/app/api/person/profile-picture/route.ts
  • ~ src/app/api/upload/profile/route.ts
  • ~ src/app/api/user/avatar/route.ts

Version 0.2.82

Fix server-side photo upload rejecting iPad files with empty MIME type

March 20, 2026 at 3:48 PM GMT+0
ef41cc8
🐛Fixed
  • Fix server-side photo upload rejecting iPad files with empty MIME type
  • iPad Safari sometimes sends empty file.type for HEIC photos. The server
  • now also checks file extension (.heic, .heif, etc.) as fallback when
  • MIME type is missing.

Files Changed

Modified (1):
  • ~ src/app/api/person/photos/route.ts

Version 0.2.81

Fix iPad Safari upload failures ("string did not match expected pattern")

March 20, 2026 at 3:10 PM GMT+0
eb2d784
🐛Fixed
  • Fix iPad Safari upload failures ("string did not match expected pattern")
  • Add file extension fallback for MIME type detection — iPad Safari reports
  • empty file.type for HEIC photos and MOV videos
  • Add try/catch around URL.createObjectURL() calls which throw on Safari
  • Add img.onerror handler so HEIC files that can't preview still open crop dialog

Files Changed

Modified (2):
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-video-manager.tsx

Version 0.2.80

Optimize page loads: lazy team search, HEIC uploads, mobile crop dialog, hydration fixes

March 20, 2026 at 2:26 PM GMT+0
26c958f
🔄Changed
  • Optimize page loads: lazy team search, HEIC uploads, mobile crop dialog, hydration fixes
  • Profile experience: replace 52K preloaded teams with debounced API search
  • Person photos: accept HEIC/HEIF, validate empty files, improve error logging
  • Image crop dialog: mobile-responsive layout with proper viewport handling
  • Team page: remove fallback to gym-level uniformBrand (use season data only)
  • Gym form: remove gym-level uniform brand field, add season data rollover

Files Changed

Modified (11):
  • ~ scripts/maintenance/backfill-competition-locations.ts
  • ~ scripts/maintenance/backfill-gym-locations.ts
  • ~ src/app/api/person/photos/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/admin/gym-form.tsx
  • ~ src/components/people/person-experience.tsx
  • ~ src/components/settings/image-crop-dialog.tsx
  • ~ src/components/teams/competition-analysis/competition-analysis-wrapper.tsx
  • ~ src/components/teams/competition-analysis/head-to-head-table.tsx
  • ~ src/lib/auto-discover.ts

Version 0.2.79

Fix dance teams in feed 404 and video upload rejection for HEVC codecs

March 20, 2026 at 2:05 PM GMT+0
21a629d
🐛Fixed
  • Fix dance teams in feed 404 and video upload rejection for HEVC codecs
  • Add activeDisciplineFilter to dashboard feed query so inactive
  • disciplines (Dance) no longer appear in the feed
  • Allow video uploads when browser can't decode the codec (HEVC/H.265);
  • Mux handles all formats server-side so client-side rejection was wrong

Files Changed

Modified (4):
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/components/dashboard/post-content.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-video-manager.tsx

Version 0.2.78

Replace Google Drive scorecard upload with direct browser download

March 20, 2026 at 4:41 AM GMT+0
11de730
🔄Changed
  • Replace Google Drive scorecard upload with direct browser download
  • Scorecards now download directly — single division as PNG, full
  • competition as ZIP organized by level folders. Eliminates recurring
  • Google OAuth token expiration issues. Also added fallback from OAuth
  • to service account in google-drive.ts for any remaining Drive usage.

Files Changed

Created (1):
  • + src/app/api/admin/competitions/[id]/scorecards/download/route.ts
Modified (4):
  • ~ src/app/api/admin/competitions/[id]/scorecards/download/route.ts
  • ~ src/components/admin/competition-scorecards-button.tsx
  • ~ src/lib/competition-scorecards.ts
  • ~ src/lib/google-drive.ts

Version 0.2.77

Fix semifinals being treated as finals across the codebase

March 20, 2026 at 4:02 AM GMT+0
f15a908
🐛Fixed
  • Fix semifinals being treated as finals across the codebase
  • .includes("final") also matches "semifinal", causing semifinal
  • placements/scores to be used instead of actual finals results.
  • Added shared isFinalRound() utility that excludes "semi" and
  • fixed all 15+ affected locations: gym stats, KPIs, competitions,
  • coach/choreographer pages, brand battle, NCA utils, and exports.

Files Changed

Modified (16):
  • ~ src/components/choreographers/choreographer-credits-section.tsx
  • ~ src/components/choreographers/choreographer-season-stats.tsx
  • ~ src/components/coaches/coach-credits-section.tsx
  • ~ src/components/coaches/coach-season-stats.tsx
  • ~ src/components/competitions/brand-battle-card.tsx
  • ~ src/components/competitions/es-bands-tab.tsx
  • ~ src/components/competitions/gym-wins-chart.tsx
  • ~ src/components/competitions/gyms-tab.tsx
  • ~ src/components/gyms/gym-season-competitions.tsx
  • ~ src/components/gyms/gym-season-kpis.tsx
  • ~ src/components/gyms/gym-season-stats.tsx
  • ~ src/lib/competition-analysis.ts
  • ~ src/lib/competition-google-sheets-export.ts
  • ~ src/lib/competition-scorecards.ts
  • ~ src/lib/nca-utils.ts
  • ~ src/lib/utils.ts

Version 0.2.76

Hide legacy "Prep" tier label from sidebar for free users

March 20, 2026 at 3:54 AM GMT+0
1d8ed2e
🔄Changed
  • Hide legacy "Prep" tier label from sidebar for free users
  • Free tier was being displayed as "Prep" (a deprecated tier name) under
  • the avatar in the sidebar. Only show tier labels for paid tiers and admins.

Files Changed

Modified (1):
  • ~ src/app/layout.tsx

Version 0.2.75

Add data quality infrastructure: quality score, All Star filter, PDF completeness loop

March 19, 2026 at 3:09 PM GMT+0
4902225
Added
  • Add data quality infrastructure: quality score, All Star filter, PDF completeness loop
  • Add quality-score.ts: weighted 0-100 score (event coverage, perf match, PDF integrity, validation)
  • Add dry-run-test.ts: read-only safety test for pipeline changes
  • Add pdf-completeness-loop.ts: iterative PDF backfill with batch pre-filtering
  • Add perfection-loop.ts: automated audit→remediate→backfill orchestrator for Railway
  • Add All Star filter to data-audit.ts and rescrape-orchestrator.ts (skip Game Day, Dance, etc.)

Files Changed

Created (4):
  • + scripts/maintenance/dry-run-test.ts
  • + scripts/maintenance/pdf-completeness-loop.ts
  • + scripts/maintenance/perfection-loop.ts
  • + scripts/maintenance/quality-score.ts
Modified (7):
  • ~ scripts/maintenance/dry-run-test.ts
  • ~ scripts/maintenance/pdf-completeness-loop.ts
  • ~ scripts/maintenance/perfection-loop.ts
  • ~ scripts/maintenance/quality-score.ts
  • ~ src/lib/data-audit.ts
  • ~ src/lib/rescrape-orchestrator.ts
  • ~ src/lib/validation/competition-validator.ts

Version 0.2.74

Add inline caption editing for photos and videos in feed

March 19, 2026 at 1:32 PM GMT+0
e99f724
Added
  • Add inline caption editing for photos and videos in feed
  • Pencil button on each feed item opens inline CaptionInput for editing.
  • Supports @-mention tagging, 280 char limit, optimistic UI updates.
  • New PATCH /api/person/content endpoint handles caption/description
  • updates with auth/ownership checks.

Files Changed

Created (1):
  • + src/app/api/person/content/route.ts
Modified (2):
  • ~ src/app/api/person/content/route.ts
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.73

Add followers/following list dialogs to profile page

March 19, 2026 at 5:21 AM GMT+0
551e05a
Added
  • Add followers/following list dialogs to profile page
  • Click the follower/following counts on any profile to see the full
  • list. Followers shows people with avatar + username. Following shows
  • people, teams, and gyms with type badges. Data fetched on-demand via
  • new /api/person/follow-list endpoint.

Files Changed

Created (2):
  • + src/app/api/person/follow-list/route.ts
  • + src/components/profile/follow-list-dialog.tsx
Modified (3):
  • ~ src/app/api/person/follow-list/route.ts
  • ~ src/components/profile/follow-list-dialog.tsx
  • ~ src/components/profile/profile-card-clean.tsx

Version 0.2.72

Unify feed to single column, add delete button to post page

March 19, 2026 at 5:13 AM GMT+0
4689969
🔄Changed
  • Unify feed to single column, add delete button to post page
  • Change feed grid from 2-column to single-column layout
  • Remove separate ProfileVideoManager section from Feed tab
  • Add MediaDeleteButton component for post page delete with redirect
  • Add delete button to /post/[id] page (owner + admin only)

Files Changed

Created (1):
  • + src/components/profile/media-delete-button.tsx
Modified (4):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/post/[id]/page.tsx
  • ~ src/components/profile/media-delete-button.tsx
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.71

Add profile tab navigation and highlights feature

March 19, 2026 at 4:26 AM GMT+0
bf9290a
Added
  • Add profile tab navigation and highlights feature
  • Replace vertically-stacked CollapsibleSections with URL-based tabs
  • (Feed | Experience | Skills | Timeline | Highlights). Add isHighlighted
  • boolean to PersonPhoto and ProfileVideo models with star/pin toggle
  • in the feed. Highlights tab shows pinned content grid plus social links.

Files Changed

Created (3):
  • + src/app/api/person/highlights/route.ts
  • + src/components/profile/profile-highlights-tab.tsx
  • + src/components/profile/profile-tabs.tsx
Modified (7):
  • ~ prisma/schema.prisma
  • ~ src/app/api/person/highlights/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-highlights-tab.tsx
  • ~ src/components/profile/profile-tabs.tsx
  • ~ src/types/person-photos.ts

Version 0.2.70

Fix home feed missing media, add content delete buttons, clarify cover photo

March 19, 2026 at 3:51 AM GMT+0
0eb5dad
🐛Fixed
  • Fix home feed missing media, add content delete buttons, clarify cover photo
  • Add mediaPhotos + mediaVideos queries to SSR feed page (were missing,
  • causing only performance scores to show on initial load)
  • Add delete buttons (trash icon) on photos and videos in profile Content feed
  • Update edit profile modal label to clarify photo is used as cover photo
  • Delete calls existing API endpoints with confirmation dialog

Files Changed

Modified (3):
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/components/people/person-profile-edit.tsx
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.69

Simplify cover photo, unified upload, captions & @-mention tagging (Phase 7)

March 19, 2026 at 2:14 AM GMT+0
48053b6
🔄Changed
  • Simplify cover photo, unified upload, captions & @-mention tagging (Phase 7)
  • Replace photo carousel with single static cover photo (ProfileCoverPhoto)
  • Remove ProfilePhotoManager from profile page
  • Merge photo+video upload into single "Add Content" file picker
  • Add caption field (280 chars) to PersonPhoto schema
  • Add CaptionInput with @-mention autocomplete via /api/people/search

Files Changed

Created (3):
  • + src/components/profile/caption-display.tsx
  • + src/components/profile/profile-cover-photo.tsx
  • + src/components/ui/caption-input.tsx
Modified (12):
  • ~ prisma/schema.prisma
  • ~ src/app/api/feed/route.ts
  • ~ src/app/api/person/photos/route.ts
  • ~ src/app/api/person/videos/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/components/dashboard/post-content.tsx
  • ~ src/components/profile/caption-display.tsx
  • ~ src/components/profile/profile-content-feed.tsx
  • ~ src/components/profile/profile-cover-photo.tsx
  • ~ src/components/ui/caption-input.tsx
  • ~ src/types/person-photos.ts

Version 0.2.68

Add feed upload tabs, profile content section, and collapsible sections (Phase 6)

March 19, 2026 at 12:19 AM GMT+0
c32c14c
Added
  • Add feed upload tabs, profile content section, and collapsible sections (Phase 6)
  • Replace PostHighlight with tabbed PostContent (Link/Photo/Video) on feed page
  • FREE users see link-only input; Elite+ see all three tabs with upload gate
  • Add ProfileContentFeed component merging photos+videos sorted by date
  • Add CollapsibleSection wrapper; wrap Experience, Skills, Timeline, Highlights
  • Content section is default-expanded; others collapsed to reduce page length

Files Changed

Created (3):
  • + src/components/dashboard/post-content.tsx
  • + src/components/profile/collapsible-section.tsx
  • + src/components/profile/profile-content-feed.tsx
Modified (5):
  • ~ src/app/dashboard/feed/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/dashboard/post-content.tsx
  • ~ src/components/profile/collapsible-section.tsx
  • ~ src/components/profile/profile-content-feed.tsx

Version 0.2.67

Fix video manager admin bypass and tier config fallback

March 18, 2026 at 11:03 PM GMT+0
250e1d8
🐛Fixed
  • Fix video manager admin bypass and tier config fallback
  • Admin users now see video manager regardless of profile owner's tier
  • Admin viewers get PRO tier limits instead of profile owner's FREE limits

Files Changed

Modified (1):
  • ~ src/app/people/[username]/page.tsx

Version 0.2.66

Add photo/video media to follower feed (Phase 5)

March 18, 2026 at 10:20 PM GMT+0
9431468
Added
  • Add photo/video media to follower feed (Phase 5)
  • Add media_photo and media_video feed item types to feed API
  • Fetch PersonPhoto + ProfileVideo from followed people in parallel with existing queries
  • Render photos with Image component and videos with MuxPlayer in feed cards
  • Add share buttons on feed media items, link to /post/[id] permalinks
  • Existing infinite scroll and cursor pagination handles new types seamlessly

Files Changed

Modified (2):
  • ~ src/app/api/feed/route.ts
  • ~ src/components/dashboard/feed-list.tsx

Version 0.2.65

Fix clean-data loop stage escalation and robust duplicate team merging

March 18, 2026 at 10:19 PM GMT+0
6fcb4f3
🐛Fixed
  • Fix clean-data loop stage escalation and robust duplicate team merging
  • The clean-data loop was stuck at batch size 5 because both code paths
  • in the stage loop broke out instead of escalating. Also hardened the
  • duplicate-teams fix to handle unique constraint conflicts on performances,
  • already-deleted teams in the same batch, and cascading merge failures.

Files Changed

Created (4):
  • + scripts/maintenance/clean-data-loop.ts
  • + src/lib/data-quality/assertions.ts
  • + src/lib/data-quality/fixes.ts
  • + src/lib/data-quality/reporter.ts
Modified (4):
  • ~ scripts/maintenance/clean-data-loop.ts
  • ~ src/lib/data-quality/assertions.ts
  • ~ src/lib/data-quality/fixes.ts
  • ~ src/lib/data-quality/reporter.ts

Version 0.2.64

Add permalinks, upload gate, share/report buttons, admin media review (Phase 4)

March 18, 2026 at 10:14 PM GMT+0
2ea4fb9
Added
  • Add permalinks, upload gate, share/report buttons, admin media review (Phase 4)
  • /post/[id] permalink page with OG meta tags for rich social previews
  • Upload gate dialog: birthdate collection, parental consent for under-13, visibility info for under-18
  • Share buttons: copy link, native Web Share API, Twitter/X, Facebook
  • Report button: dialog with reason text, creates MediaReport record
  • Admin media reports page at /admin/media-reports with review/resolve actions

Files Changed

Created (7):
  • + src/app/admin/media-reports/actions.tsx
  • + src/app/admin/media-reports/page.tsx
  • + src/app/api/admin/media-reports/route.ts
  • + src/app/post/[id]/page.tsx
  • + src/components/profile/media-report-button.tsx
  • + src/components/profile/media-share-buttons.tsx
  • + src/components/profile/upload-gate-dialog.tsx
Modified (9):
  • ~ src/app/admin/media-reports/actions.tsx
  • ~ src/app/admin/media-reports/page.tsx
  • ~ src/app/api/admin/media-reports/route.ts
  • ~ src/app/api/person/[id]/route.ts
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/post/[id]/page.tsx
  • ~ src/components/profile/media-report-button.tsx
  • ~ src/components/profile/media-share-buttons.tsx
  • ~ src/components/profile/upload-gate-dialog.tsx

Version 0.2.63

Add video upload UI and profile gallery (Phase 3)

March 18, 2026 at 10:06 PM GMT+0
36abf7f
Added
  • Add video upload UI and profile gallery (Phase 3)
  • ProfileVideoManager: file picker with duration/size validation, XHR upload with progress bar, drag-to-reorder, delete
  • ProfileVideoPlayer: wraps @mux/mux-player-react with processing/error/ready states
  • Profile page: video manager for Elite+ editors, public video gallery for all viewers
  • Client-side validation enforces tier-based duration and file size limits before upload

Files Changed

Created (2):
  • + src/components/profile/profile-video-manager.tsx
  • + src/components/profile/profile-video-player.tsx
Modified (3):
  • ~ src/app/people/[username]/page.tsx
  • ~ src/components/profile/profile-video-manager.tsx
  • ~ src/components/profile/profile-video-player.tsx

Version 0.2.62

Add Mux video upload API and webhook handler (Phase 2)

March 18, 2026 at 9:56 PM GMT+0
c1c2ab6
Added
  • Add Mux video upload API and webhook handler (Phase 2)
  • Create Mux client singleton (src/lib/mux.ts)
  • POST /api/person/videos: creates Mux direct upload URL with tier/age/consent checks
  • GET/PUT/DELETE /api/person/videos: list, reorder, and delete videos (+ Mux asset cleanup)
  • POST /api/webhooks/mux: handles asset.ready, asset.errored, upload.asset_created events
  • Install @mux/mux-node v12, @mux/mux-player-react

Files Changed

Created (3):
  • + src/app/api/person/videos/route.ts
  • + src/app/api/webhooks/mux/route.ts
  • + src/lib/mux.ts
Modified (3):
  • ~ src/app/api/person/videos/route.ts
  • ~ src/app/api/webhooks/mux/route.ts
  • ~ src/lib/mux.ts

Version 0.2.61

Add direct media upload foundation (Phase 1)

March 18, 2026 at 9:41 PM GMT+0
79a28e2
Added
  • Add direct media upload foundation (Phase 1)
  • Add ProfileVideo model with Mux fields, MediaReport model for content safety
  • Add VideoStatus, MediaVisibility enums and parentalConsentAt on Person
  • Add tier config flags: hasMediaUpload, maxMonthlyUploads, maxVideoDurationSecs, maxVideoFileSizeMB
  • Make photo upload limits dynamic from tier config instead of hardcoded 5
  • Add media-safety.ts: age checks, visibility defaults for minors, parental consent, upload counting

Files Changed

Created (2):
  • + src/app/api/media/report/route.ts
  • + src/lib/media-safety.ts
Modified (6):
  • ~ prisma/schema.prisma
  • ~ src/app/api/media/report/route.ts
  • ~ src/app/api/person/photos/route.ts
  • ~ src/lib/media-safety.ts
  • ~ src/lib/tiers-config.ts
  • ~ src/lib/tiers.ts

Version 0.2.60

Fix Results module showing all rounds instead of only finals

March 18, 2026 at 5:30 PM GMT+0
fb39368
🐛Fixed
  • Fix Results module showing all rounds instead of only finals
  • "Semi-Finals" was misclassified as "Finals" because getRoundLabel checked
  • for "final" before "semi", and "semi-finals".includes("final") is true.
  • Reorder checks so "semi" is matched first in both division page and tab.

Files Changed

Modified (2):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/components/competitions/divisions-tab.tsx

Version 0.2.59

Fix Results module showing all rounds instead of only finals

March 18, 2026 at 5:30 PM GMT+0
998ea8a
🐛Fixed
  • Fix Results module showing all rounds instead of only finals
  • "Semi-Finals" was misclassified as "Finals" because getRoundLabel checked
  • for "final" before "semi", and "semi-finals".includes("final") is true.
  • Reorder checks so "semi" is matched first in both division page and tab.

Files Changed

Modified (2):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/components/competitions/divisions-tab.tsx

Version 0.2.58

Fix division results showing duplicate teams for non-standard round labels

March 16, 2026 at 7:15 PM GMT+0
ef4f7bf
🐛Fixed
  • Fix division results showing duplicate teams for non-standard round labels
  • pickBestRound helper selects the best round (Finals > Semis > Day 2 > last entry)
  • instead of hardcoded "Finals" lookup that fell back to all performances.

Files Changed

Modified (1):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx

Version 0.2.57

Fix division results showing duplicate teams for non-standard round labels

March 16, 2026 at 7:15 PM GMT+0
359140a
🐛Fixed
  • Fix division results showing duplicate teams for non-standard round labels
  • pickBestRound helper selects the best round (Finals > Semis > Day 2 > last entry)
  • instead of hardcoded "Finals" lookup that fell back to all performances.

Files Changed

Modified (1):
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx

Version 0.2.56

Fix round value case mismatch — DB uses "Finals" not "FINALS"

March 15, 2026 at 2:12 AM GMT+0
9595090
🐛Fixed
  • Fix round value case mismatch — DB uses "Finals" not "FINALS"
  • The performance round values in the database are mixed-case ("Finals",
  • "Prelims") not uppercase ("FINALS", "FINAL"). Added "Finals" to all
  • round filters in nca-utils and series page queries.

Files Changed

Modified (2):
  • ~ src/app/competitions/series/[seriesSlug]/page.tsx
  • ~ src/lib/nca-utils.ts

Version 0.2.55

Fix scrape-job-processor build error and commit pending changes

March 15, 2026 at 2:04 AM GMT+0
3e99520
🐛Fixed
  • Fix scrape-job-processor build error and commit pending changes

Files Changed

Modified (1):
  • ~ src/lib/scrape-job-processor.ts

Version 0.2.54

Fix null safety in scratch files to unblock build

March 15, 2026 at 1:56 AM GMT+0
8c1f67e
🐛Fixed
  • Fix null safety in scratch files to unblock build

Version 0.2.53

Fix NCA badge to count all series wins + add series page season filter and analytics

March 15, 2026 at 1:47 AM GMT+0
3b6fdbe
🐛Fixed
  • Fix NCA badge to count all series wins + add series page season filter and analytics
  • Replace in-memory NCA win counting with Prisma queries via CompetitionSeries slug,
  • fixing truncation from take:250 limit on team/gym/coach/choreographer pages
  • Add season filtering to series page via URL search params
  • Add "Wins by Division" table and "Gym Dominance Over Time" stacked area chart
  • Update scorecard backgrounds

Files Changed

Created (3):
  • + src/components/competitions/series-division-wins.tsx
  • + src/components/competitions/series-gym-trend-chart.tsx
  • + src/components/competitions/series-page-client.tsx
Modified (16):
  • ~ scripts/import/review-import-worker.ts
  • ~ src/app/api/live-scores/route.ts
  • ~ src/app/choreographers/[id]/page.tsx
  • ~ src/app/coaches/[id]/page.tsx
  • ~ src/app/competitions/series/[seriesSlug]/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/live/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/competitions/series-division-wins.tsx
  • ~ src/components/competitions/series-gym-trend-chart.tsx
  • ~ src/components/competitions/series-page-client.tsx
  • ~ src/components/live/live-score-card.tsx
  • ~ src/components/ui/nca-champion-badge.tsx
  • ~ src/lib/import/schedule-import.ts
  • ~ src/lib/nca-utils.ts
  • ~ src/lib/scrape-job-processor.ts

Version 0.2.52

Add Competition Series to Explore page search results

March 15, 2026 at 1:46 AM GMT+0
11dada9
Added
  • Add Competition Series to Explore page search results
  • Series now appear in explore results with grid/list views and a category
  • card on the explore landing page linking to /competitions/series.

Files Changed

Modified (2):
  • ~ src/app/explore/page.tsx
  • ~ src/components/explore/explore-results.tsx

Version 0.2.51

Add section headers to search dropdown and tab navigation to search page

March 15, 2026 at 1:23 AM GMT+0
a042f0e
Added
  • Add section headers to search dropdown and tab navigation to search page
  • Dropdown now groups results by type (Gyms, Teams, Competition Series, etc.)
  • with section headers and reduces per-type limit from 5 to 3 so all sections
  • are visible. Search page adds pill-shaped tab filters with result counts.

Files Changed

Modified (3):
  • ~ src/app/api/search/route.ts
  • ~ src/app/search/page.tsx
  • ~ src/components/home-search.tsx

Version 0.2.50

Fix notification click not navigating on iOS PWA

March 14, 2026 at 9:52 PM GMT+0
a21aa88
🐛Fixed
  • Fix notification click not navigating on iOS PWA
  • client.navigate() is not supported on iOS Safari PWA. Now catches the
  • error and falls through to clients.openWindow() which works cross-platform.
  • Also uses full URL to ensure proper routing.

Version 0.2.49

Add Source PDF link to schedule page header

March 14, 2026 at 5:38 PM GMT+0
f0b7ac9
Added
  • Add Source PDF link to schedule page header
  • Shows a link to the original PDF when fileUrl is available on the CompetitionSchedule.

Files Changed

Modified (1):
  • ~ src/app/schedules/[slug]/page.tsx

Version 0.2.48

Move stage before competition name in notifications

March 14, 2026 at 5:33 PM GMT+0
41c8040
🔄Changed
  • Move stage before competition name in notifications
  • "Performs at 1:29 PM EDT in L4.2 Senior on Stage A at Cheer Power Grand Nationals"

Files Changed

Modified (2):
  • ~ src/lib/notifications/reminder-engine.ts
  • ~ src/lib/notifications/score-notifications.ts

Version 0.2.47

Add stage name to end of performance notifications

March 14, 2026 at 5:31 PM GMT+0
cbecb74
Added
  • Add stage name to end of performance notifications
  • Shows stage/panel info at the end like: "Performs at 1:33 PM EDT in L3 - U16 at Cheer Power Grand Nationals (Stage A)"

Files Changed

Modified (2):
  • ~ src/lib/notifications/reminder-engine.ts
  • ~ src/lib/notifications/score-notifications.ts

Version 0.2.46

Add @types/pdf-parse to fix build error

March 14, 2026 at 5:10 PM GMT+0
ccf9aaa
Added
  • Add @types/pdf-parse to fix build error

Version 0.2.45

Exclude root scratch files from TypeScript build

March 14, 2026 at 4:37 PM GMT+0
f359b9f
🔄Changed
  • Exclude root scratch files from TypeScript build

Version 0.2.44

Surface actual push subscription error messages to the user

March 14, 2026 at 4:27 PM GMT+0
536db2f
🔄Changed
  • Surface actual push subscription error messages to the user
  • subscribe() now returns { ok, error } with specific failure reasons:
  • Service worker not supported / failed to register
  • PushManager not available (wrong browser on iOS)
  • Permission denied
  • PushManager.subscribe() failure (with native error message)

Files Changed

Modified (3):
  • ~ src/components/notifications/push-prompt.tsx
  • ~ src/components/settings/notification-preferences.tsx
  • ~ src/hooks/use-push-subscription.ts

Version 0.2.43

Add push subscribe error feedback and better error logging

March 14, 2026 at 4:17 PM GMT+0
9ab65d4
Added
  • Add push subscribe error feedback and better error logging
  • Show toast on success/failure when enabling push
  • Display error message if push subscription fails
  • Log specific failure points (PushManager.subscribe, missing keys, API error)
  • Helps diagnose why push enable appears to do nothing on some devices

Files Changed

Modified (2):
  • ~ src/components/settings/notification-preferences.tsx
  • ~ src/hooks/use-push-subscription.ts

Version 0.2.42

Improve push permission denied message with platform-specific reset instructions

March 14, 2026 at 4:08 PM GMT+0
7e6def7
🔄Changed
  • Improve push permission denied message with platform-specific reset instructions

Files Changed

Modified (1):
  • ~ src/components/settings/notification-preferences.tsx

Version 0.2.41

Fix gym name contamination and improve generic team name validation

March 14, 2026 at 3:58 PM GMT+0
af01386
🐛Fixed
  • Fix gym name contamination and improve generic team name validation
  • Cleaned 205 contaminated gyms: person names, division suffixes, dash artifacts
  • Deleted 13 orphan teams (0 performances)
  • Validator now skips schools/dance programs for GENERIC_TEAM_NAME check
  • (high schools, universities, etc. legitimately have team name == gym name)
  • Bulk scrape re-enabled when RESCRAPE_ENABLED=false

Files Changed

Created (1):
  • + scripts/maintenance/fix-remaining-person-gyms.ts
Modified (3):
  • ~ scripts/maintenance/cleanup-gym-names.ts
  • ~ scripts/maintenance/fix-remaining-person-gyms.ts
  • ~ src/lib/validation/competition-validator.ts

Version 0.2.40

Add explicit Enable Push button to notification settings

March 14, 2026 at 3:57 PM GMT+0
924acf7
Added
  • Add explicit Enable Push button to notification settings
  • Shows push subscription status per device with Enable/Disable button
  • Removes blanket iOS block from PushPrompt — now checks PushManager API directly
  • Users can enable push from settings instead of only via the floating prompt

Files Changed

Modified (2):
  • ~ src/components/notifications/push-prompt.tsx
  • ~ src/components/settings/notification-preferences.tsx

Version 0.2.39

Fix iOS push detection: check actual PushManager support instead of blanket-blocking iOS

March 14, 2026 at 3:49 PM GMT+0
e0e9f8d
🐛Fixed
  • Fix iOS push detection: check actual PushManager support instead of blanket-blocking iOS
  • iOS 16.4+ Safari PWAs support Web Push. The old check blocked all iOS devices.
  • Now only shows the banner when PushManager/Notification APIs are truly unavailable
  • (e.g. Chrome on iOS, older iOS versions, non-standalone mode).

Files Changed

Modified (2):
  • ~ src/components/settings/notification-preferences.tsx
  • ~ src/hooks/use-push-subscription.ts

Version 0.2.38

Fix silent push notification failures: validate subscriptions, fix counting, add logging

March 14, 2026 at 3:45 PM GMT+0
9b57187
🐛Fixed
  • Fix silent push notification failures: validate subscriptions, fix counting, add logging
  • resolveChannelFlags now checks PushSubscription table before marking push=true
  • Users without a registered push subscription are excluded from push attempts
  • Fix push result counting to track per-user delivery (not per-promise)
  • Add logging when user has 0 push subscriptions and when subscriptions expire

Files Changed

Modified (3):
  • ~ src/lib/notifications/preferences.ts
  • ~ src/lib/notifications/score-notifications.ts
  • ~ src/lib/push.ts

Version 0.2.37

Fix SSR crash: wrap useIsIOSPWA in useEffect to avoid window/navigator on server

March 14, 2026 at 3:32 PM GMT+0
8201e29
🐛Fixed
  • Fix SSR crash: wrap useIsIOSPWA in useEffect to avoid window/navigator on server

Files Changed

Modified (1):
  • ~ src/hooks/use-push-subscription.ts

Version 0.2.36

Refactor PWA notifications: iOS detection, reorganize alerts page, improve notification URLs

March 14, 2026 at 3:27 PM GMT+0
592e0a1
🔄Changed
  • Refactor PWA notifications: iOS detection, reorganize alerts page, improve notification URLs
  • Add userScheduleId relation to ScheduleEntryBell for bulk schedule bell management
  • Add useIsIOSPWA() hook to detect iOS PWA and suppress push prompts
  • Move bell/follow management from notifications page to alerts settings page
  • Split subscriptions into follows, saved schedules, and orphan bells sections
  • Score notifications now link to division page instead of team page

Files Changed

Modified (17):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/backfill-scoresheet-pdfs.ts
  • ~ src/app/api/schedule-entry-bell/bulk/route.ts
  • ~ src/app/notifications/page.tsx
  • ~ src/app/settings/alerts/page.tsx
  • ~ src/components/notifications/manage-bells.tsx
  • ~ src/components/notifications/notification-list.tsx
  • ~ src/components/notifications/push-prompt.tsx
  • ~ src/components/pwa/install-prompt.tsx
  • ~ src/components/settings/notification-preferences.tsx
  • ~ src/components/settings/subscriptions-list.tsx
  • ~ src/hooks/use-push-subscription.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/notifications/__tests__/score-notifications.test.ts
  • ~ src/lib/notifications/reminder-engine.ts
  • ~ src/lib/notifications/score-notifications.ts
  • ~ src/lib/push.ts

Version 0.2.35

Fix PDF print: constrain column widths, allow text wrapping

March 14, 2026 at 1:44 PM GMT+0
3a0170b
🐛Fixed
  • Fix PDF print: constrain column widths, allow text wrapping
  • Use table-layout: fixed with explicit column widths (Team 80px,
  • Competition 120px, Division 70px, Round 42px, scores 38px each)
  • Remove white-space: nowrap from data cells so competition names wrap
  • Reduce font sizes (6.5px headers, 7px body) and padding for density
  • Ensures all columns fit on a single landscape page when printing

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard-export.ts

Version 0.2.34

Fix saved schedules not appearing until manual reload

March 14, 2026 at 1:20 PM GMT+0
d13b469
🐛Fixed
  • Fix saved schedules not appearing until manual reload
  • After saving a schedule, router.push() navigated to the schedules page
  • but used stale RSC cache. Add router.refresh() to force data refetch,
  • matching the pattern already used by delete/rename operations.

Files Changed

Modified (1):
  • ~ src/components/schedules/save-schedule-dialog.tsx

Version 0.2.33

Replace SMS notification settings with "Coming Soon" label

March 14, 2026 at 1:13 PM GMT+0
19623f3
🔄Changed
  • Replace SMS notification settings with "Coming Soon" label
  • SMS is not currently functional. Replace the toggle/upgrade/phone
  • verification UI with a simple "Coming soon" message in both the
  • notification preferences table and the settings card.

Files Changed

Modified (2):
  • ~ src/components/settings/notification-preferences.tsx
  • ~ src/components/settings/settings-layout.tsx

Version 0.2.32

Fix push notifications not sent: trigger push subscription on bell toggle

March 14, 2026 at 1:03 PM GMT+0
65ef8df
🐛Fixed
  • Fix push notifications not sent: trigger push subscription on bell toggle
  • Users with belled follows had zero push subscriptions because the push
  • prompt only fired on initial follow and could be permanently dismissed.
  • Now when the bell is toggled ON, we auto-subscribe if permission is
  • already granted, or re-show the push prompt (clearing dismissed state).
  • Also auto-show prompt on page load for users with belled follows but

Files Changed

Modified (2):
  • ~ src/components/follow-button.tsx
  • ~ src/components/notifications/push-prompt.tsx

Version 0.2.31

Add color-coded column groups to PDF export matching website

March 14, 2026 at 2:59 AM GMT+0
0ecc01c
Added
  • Add color-coded column groups to PDF export matching website
  • Add grouped header row with colored backgrounds (Building=blue,
  • Tumbling=orange, Performance=violet) spanning their columns
  • Add left border dividers on first column of each group in data rows
  • Add light tinted backgrounds on column headers per group
  • Two-row thead: group labels on top, column names below

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard-export.ts

Version 0.2.30

Move filter sidebar toggle below folder toggle, remove from card header

March 14, 2026 at 2:56 AM GMT+0
4eb9a56
🔄Changed
  • Move filter sidebar toggle below folder toggle, remove from card header
  • Filter sidebar toggle is now a Filter icon button stacked below the
  • saved scorecards panel toggle. GymScorecard accepts filterSidebarOpen
  • and onFilterSidebarToggle props so the parent controls visibility.

Files Changed

Modified (2):
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/scorecards-client.tsx
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.29

Add toggle to hide/show the scorecard filter sidebar

March 14, 2026 at 2:45 AM GMT+0
6e4b7d3
Added
  • Add toggle to hide/show the scorecard filter sidebar
  • Sidebar toggle button (panel icon) in the scorecard header lets users
  • collapse the entire filter/controls sidebar so the performance table
  • can use the full width. Only visible on desktop (xl breakpoint).

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.28

Move grouping, sorting, and display controls into collapsible sidebar

March 14, 2026 at 1:37 AM GMT+0
2377d8d
🔄Changed
  • Move grouping, sorting, and display controls into collapsible sidebar
  • Move Group by, Sub-group by, Sub-sub-group, Level sort, Averages
  • toggle, and score column group pills from the inline card header
  • into the filter sidebar
  • Sidebar now has two collapsible sections: "Controls" and "Filters"
  • Both sections are collapsible with chevron toggles

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.27

Fix PDF export: wrap score column headers and use landscape layout

March 14, 2026 at 1:31 AM GMT+0
0ab8476
🐛Fixed
  • Fix PDF export: wrap score column headers and use landscape layout
  • Score column headers with full labels (e.g. "Stunt Difficulty") were
  • using white-space: nowrap, making columns too wide to fit on one page.
  • Now headers wrap text with constrained max-width, use smaller font,
  • and the page defaults to landscape orientation for better fit.

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard-export.ts

Version 0.2.26

Show Scorecards link on all analyze modes, apply layout tweaks

March 14, 2026 at 1:21 AM GMT+0
14fe798
🔄Changed
  • Show Scorecards link on all analyze modes, apply layout tweaks
  • Scorecards nav link now falls back to first followed gym when not in
  • gym mode, so it's always visible on Dashboard/Team/Group pages too
  • Apply full-height layout for scorecards page (user styling changes)
  • Use text-foreground for scorecard breakdown column headers

Files Changed

Modified (3):
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/scorecards-client.tsx
  • ~ src/components/gym-analysis/gym-scorecard.tsx
  • ~ src/components/my-teams/my-teams-client.tsx

Version 0.2.25

Fix rescrape: disable bulk scrape when RESCRAPE_ENABLED to prevent month contention

March 13, 2026 at 11:58 PM GMT+0
1701763
🐛Fixed
  • Fix rescrape: disable bulk scrape when RESCRAPE_ENABLED to prevent month contention
  • Bulk scrape and rescrape both competed for PENDING BulkScrapeMonth records.
  • Bulk scrape ran every 5 min and would mark months DISCOVERED without force-rescraping,
  • starving the rescrape timer which only ran every 10 min.

Files Changed

Modified (1):
  • ~ scripts/import/review-import-worker.ts

Version 0.2.24

Add PDF scoresheets feature to PRO tier on pricing page

March 13, 2026 at 11:55 PM GMT+0
8b28c66
Added
  • Add PDF scoresheets feature to PRO tier on pricing page
  • Shows in both the plan card bullet points and the feature comparison
  • table under Pro Intelligence.

Files Changed

Modified (2):
  • ~ src/app/pricing/page.tsx
  • ~ src/lib/pricing-plans.ts

Version 0.2.23

Fix Railway crash: validate Supabase URL before creating client

March 13, 2026 at 9:07 PM GMT+0
be36db9
🐛Fixed
  • Fix Railway crash: validate Supabase URL before creating client
  • The Railway worker had placeholder Supabase env vars (e.g. "https://[project-ref].supabase.co")
  • which caused createClient to throw on module load. Now validates the URL is parseable before
  • attempting to create the client, falling back to a proxy that throws on actual use.

Files Changed

Modified (1):
  • ~ src/lib/supabase.ts

Version 0.2.22

Fix backfill script: correct Varsity API parsing and round stripping

March 13, 2026 at 8:49 PM GMT+0
62ab36a
🐛Fixed
  • Fix backfill script: correct Varsity API parsing and round stripping
  • The API response nests items in container.content.items (initial) and
  • data.data.content.items (partial). Round names are appended without
  • a dash separator (e.g. "L5 Junior Finals" not "L5 Junior - Finals").

Files Changed

Modified (1):
  • ~ scripts/maintenance/backfill-scoresheet-pdfs.ts

Version 0.2.21

Fix broken search: invalid regex character range in REGEXP_REPLACE

March 13, 2026 at 8:24 PM GMT+0
687dfe4
🐛Fixed
  • Fix broken search: invalid regex character range in REGEXP_REPLACE
  • The PostgreSQL regex pattern '[\s\-.'']' had an invalid character
  • range because the hyphen was interpreted as a range operator between
  • \s and the dot. Fix by moving hyphen to end of character class:
  • '[\s.''-]'. This was causing the entire search query to fail silently,
  • returning zero results for all searches.

Files Changed

Modified (2):
  • ~ src/app/api/search/route.ts
  • ~ src/app/search/page.tsx

Version 0.2.20

Add PDF scoresheet storage & PRO-tier access

March 13, 2026 at 8:06 PM GMT+0
10aca34
Added
  • Add PDF scoresheet storage & PRO-tier access
  • Store original Varsity TV score breakdown PDFs in Supabase before they
  • get removed each season. New ScoresheetPdf model keyed by
  • (competition, division, round). Import pipeline downloads PDFs
  • sequentially after division processing. PRO users get a clickable
  • FileText icon to view the original scoresheet via signed URL.

Files Changed

Created (3):
  • + scripts/maintenance/backfill-scoresheet-pdfs.ts
  • + src/app/api/scoresheets/[performanceId]/route.ts
  • + src/lib/import/pdf-upload.ts
Modified (13):
  • ~ prisma/schema.prisma
  • ~ scripts/maintenance/backfill-scoresheet-pdfs.ts
  • ~ src/app/api/scoresheets/[performanceId]/route.ts
  • ~ src/app/competitions/[id]/divisions/[divisionId]/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/components/competitions/division-scorecard.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/lib/import/index.ts
  • ~ src/lib/import/pdf-upload.ts
  • ~ src/lib/import/review-import-processor.ts
  • ~ src/lib/import/types.ts
  • ~ src/lib/tiers-config.ts
  • ~ src/lib/tiers.ts

Version 0.2.19

Fix scorecard column header text color and improve level parsing in import scripts

March 13, 2026 at 7:42 PM GMT+0
2f9cc43
🐛Fixed
  • Fix scorecard column header text color and improve level parsing in import scripts
  • Use text-foreground instead of group textColor for breakdown column
  • full-name headers so they remain readable against tinted backgrounds
  • Switch level parsing from includes() chains to regex for accurate
  • decimal level extraction (L1.1, L4.2, etc.) across all import scripts
  • Skip generic "LEVEL X" Level Finals entries in NCA import

Files Changed

Modified (6):
  • ~ scripts/import/import-legacy-fuzzy.ts
  • ~ scripts/import/import-nca-2025.ts
  • ~ scripts/import/import-november-2025-fuzzy.ts
  • ~ scripts/import/import-october-2025-fuzzy.ts
  • ~ scripts/import/import-varsity-optimized.ts
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.18

Add Scorecards button to gym dashboard, move filters into scorecard panel

March 13, 2026 at 7:27 PM GMT+0
5bef286
Added
  • Add Scorecards button to gym dashboard, move filters into scorecard panel
  • Add Scorecards link button at top of standalone gym dashboard page
  • Move season, gym, and worlds filters from scorecards page header into
  • GymScorecard's existing filter sidebar via new headerFilters prop
  • Remove Pro plan badge from scorecards page

Files Changed

Modified (4):
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/scorecards-client.tsx
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.17

Convert Whole Gym page from tabs to single scrollable page

March 13, 2026 at 7:18 PM GMT+0
fe5ccb7
🔄Changed
  • Convert Whole Gym page from tabs to single scrollable page
  • Remove tab navigation and render Overview, Trends, Deductions, and
  • Consistency sections as one continuous page. This gives a better
  • overview experience now that Scorecards has its own dedicated page.

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-dashboard.tsx

Version 0.2.16

Move Scorecards to top-level navigation, remove from Whole Gym tabs

March 13, 2026 at 7:17 PM GMT+0
d97415b
🔄Changed
  • Move Scorecards to top-level navigation, remove from Whole Gym tabs
  • Add "Scorecards" link in the top nav bar (Dashboard | Single Team | Team Group | Whole Gym | Scorecards)
  • Link navigates to the standalone scorecards page for the selected gym
  • Remove Scorecard tab from Whole Gym dashboard (now 4 tabs: Overview, Trends, Deductions, Consistency)
  • Clean up unused GymScorecard import and gymSlug/username props from GymDashboard

Files Changed

Modified (3):
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/components/gym-analysis/gym-dashboard.tsx
  • ~ src/components/my-teams/my-teams-client.tsx

Version 0.2.15

Pass gymSlug and username to GymDashboard in analyze page

March 13, 2026 at 7:02 PM GMT+0
17afcfc
🔄Changed
  • Pass gymSlug and username to GymDashboard in analyze page
  • The "Open Full Scorecards" link was only showing on the standalone gym page
  • because the analyze page's GymDashboard call was missing the gymSlug and
  • username props needed to build the link URL.

Files Changed

Modified (1):
  • ~ src/components/my-teams/my-teams-client.tsx

Version 0.2.14

Add rt_drivers and st_drivers aliases to score mapper for DOD fields

March 13, 2026 at 6:38 PM GMT+0
e2a3ffe
Added
  • Add rt_drivers and st_drivers aliases to score mapper for DOD fields
  • These keys appear in PDF scorecards from ASC, Spirit Celebration, and
  • other events where the PDF parser produces "rt_drivers"/"st_drivers"
  • instead of "rt_dod"/"st_dod" for tumbling degree-of-difficulty drivers.

Files Changed

Modified (1):
  • ~ src/lib/import/score-mapper.ts

Version 0.2.13

Add standalone scorecards page with saved scorecards & folders

March 13, 2026 at 6:17 PM GMT+0
270e170
Added
  • Add standalone scorecards page with saved scorecards & folders
  • Add ScorecardFolder and SavedScorecard database models with nested folder support
  • Add CRUD API routes for scorecards and folders (/api/scorecards, /api/scorecards/folders)
  • Add last-opened scorecard endpoint for auto-restore on page load
  • Create standalone scorecards page at /[username]/analyze/gym/[slug]/scorecards
  • Add ScorecardLibrary sidebar component with folder tree, save/load/rename/delete

Files Changed

Created (8):
  • + src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • + src/app/[username]/analyze/gym/[slug]/scorecards/scorecards-client.tsx
  • + src/app/api/scorecards/[id]/route.ts
  • + src/app/api/scorecards/folders/[id]/route.ts
  • + src/app/api/scorecards/folders/route.ts
  • + src/app/api/scorecards/last-opened/route.ts
  • + src/app/api/scorecards/route.ts
  • + src/components/gym-analysis/scorecard-library.tsx
Modified (12):
  • ~ prisma/schema.prisma
  • ~ src/app/[username]/analyze/gym/[slug]/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/page.tsx
  • ~ src/app/[username]/analyze/gym/[slug]/scorecards/scorecards-client.tsx
  • ~ src/app/api/scorecards/[id]/route.ts
  • ~ src/app/api/scorecards/folders/[id]/route.ts
  • ~ src/app/api/scorecards/folders/route.ts
  • ~ src/app/api/scorecards/last-opened/route.ts
  • ~ src/app/api/scorecards/route.ts
  • ~ src/components/gym-analysis/gym-dashboard.tsx
  • ~ src/components/gym-analysis/gym-scorecard.tsx
  • ~ src/components/gym-analysis/scorecard-library.tsx

Version 0.2.12

Fix gym scorecard header rendering and readability

March 13, 2026 at 5:53 PM GMT+0
ce94d9d
🐛Fixed
  • Fix gym scorecard header rendering and readability
  • Split sticky colspan cells in group/full-name header rows to prevent
  • blacked-out rendering artifacts from sticky positioning on multi-span cells
  • Increase full-name header font size from 8px to 10px for readability
  • Widen max column width from 48px to 60px for longer category names

Files Changed

Modified (1):
  • ~ src/components/gym-analysis/gym-scorecard.tsx

Version 0.2.11

Improve scraper pipeline: gym name splitting, level parsing regex, program filter sweep, and normalized competition search

March 13, 2026 at 5:51 PM GMT+0
e9e52f8
🔄Changed
  • Improve scraper pipeline: gym name splitting, level parsing regex, program filter sweep, and normalized competition search
  • Scraper: split program_name into gym+team using known prefixes and dash separators
  • Scraper: program filter sweep to catch teams hidden behind pagination
  • Scraper: retry logic for filter sweep queries
  • Scraper: /api/validate endpoint for data validation
  • Import: cleanGymName() strips team suffix from gym names

Files Changed

Created (9):
  • + scripts/check-jobs.ts
  • + scripts/maintenance/cleanup-gym-names-r2.ts
  • + scripts/maintenance/cleanup-gym-names.ts
  • + scripts/maintenance/data-quality-report.ts
  • + scripts/maintenance/delete-orphan-teams.ts
  • + scripts/maintenance/find-orphan-dash-gyms.ts
  • + scripts/maintenance/find-singleton-orphans.ts
  • + scripts/maintenance/inspect-topgun.ts
  • + scripts/rescrape-gym.ts
Modified (18):
  • ~ scripts/check-jobs.ts
  • ~ scripts/import/import-may-2025-fuzzy.ts
  • ~ scripts/import/import-may-2025-optimized.ts
  • ~ scripts/import/import-nca-2025.ts
  • ~ scripts/import/import-varsity-events-fuzzy-complete.ts
  • ~ scripts/import/import-varsity-events-production.ts
  • ~ scripts/import/import-varsity-events.ts
  • ~ scripts/import/import-varsity-optimized.ts
  • ~ scripts/maintenance/cleanup-gym-names-r2.ts
  • ~ scripts/maintenance/cleanup-gym-names.ts
  • ~ scripts/maintenance/data-quality-report.ts
  • ~ scripts/maintenance/delete-orphan-teams.ts
  • ~ scripts/maintenance/find-orphan-dash-gyms.ts
  • ~ scripts/maintenance/find-singleton-orphans.ts
  • ~ scripts/maintenance/inspect-topgun.ts
  • ~ scripts/migrations/fix-division-levels.ts
  • ~ scripts/rescrape-gym.ts
  • ~ src/components/competitions/competitions-list-client.tsx

Version 0.2.10

Handle status poll timeouts gracefully in scrape job processor

March 13, 2026 at 5:42 PM GMT+0
686daaa
🔄Changed
  • Handle status poll timeouts gracefully in scrape job processor
  • Previously a single timeout on the /api/status endpoint would fail the
  • entire scrape job. Now tolerates up to 10 consecutive poll errors before
  • giving up, which handles the case where the scraper is busy processing
  • large events.

Files Changed

Modified (1):
  • ~ src/lib/scrape-job-processor.ts

Version 0.2.9

Add data quality overhaul: validation framework, rescrape orchestrator, and auto-changelog

March 13, 2026 at 5:32 PM GMT+0
da46cff
Added
  • Add data quality overhaul: validation framework, rescrape orchestrator, and auto-changelog
  • CompetitionValidation model + 7 automated post-import checks
  • Rescrape orchestrator for full 2020-present month-by-month re-scraping
  • Python scraper improvements: gym/team name splitting, program filter sweep, retry logic
  • Validation API endpoint for Python scraper
  • Auto-changelog hook for automatic version bumping on every commit

Files Changed

Created (2):
  • + scripts/auto-changelog.sh
  • + src/lib/rescrape-orchestrator.ts
Modified (7):
  • ~ prisma/schema.prisma
  • ~ python-scraper/main.py
  • ~ python-scraper/scraper/varsity_api_scraper.py
  • ~ scripts/auto-changelog.sh
  • ~ scripts/import/review-import-worker.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/rescrape-orchestrator.ts

Version 0.2.8

Scraper & import pipeline improvements, schedule review system

February 20, 2026 at 6:40 PM GMT+0
3950f3f
Added
  • Inline schedule entries preview in event review — expand to see Division, Gym, Team, Time, Day, Session without leaving the page
  • Schedule review & editing admin pages with approve/reject workflow
  • Pending schedules list for quick admin triage
  • Enhanced Python scraper with improved pagination and data extraction
  • Schedule import pipeline now handles staged entries for preview before commit
🔄Changed
  • Import pipeline improvements for better gym and team matching accuracy
  • Schedule import logic expanded with smarter conflict resolution
  • Competition performances component updated with improved display
🐛Fixed
  • Removed problematic Division unique constraint that caused import conflicts
  • Scraper dashboard and event selector UI refinements

Files Changed

Created (7):
  • + src/app/admin/schedules/[scheduleId]/review/page.tsx
  • + src/app/api/admin/schedules/[scheduleId]/approve/route.ts
  • + src/app/api/admin/schedules/[scheduleId]/reject/route.ts
  • + src/app/api/admin/schedules/[scheduleId]/route.ts
  • + src/app/api/admin/schedules/pending/route.ts
  • + src/components/admin/schedules/pending-schedules-list.tsx
  • + src/components/admin/schedules/schedule-review-page.tsx
Modified (12):
  • ~ prisma/schema.prisma
  • ~ python-scraper/scraper/varsity_api_scraper.py
  • ~ src/app/api/admin/scraper/jobs/[id]/review/[eventIndex]/route.ts
  • ~ src/app/api/admin/scraper/schedule-intake/route.ts
  • ~ src/components/admin/scraper/event-selector.tsx
  • ~ src/components/admin/scraper/review/event-detail.tsx
  • ~ src/components/admin/scraper/scraper-dashboard.tsx
  • ~ src/components/competitions/competition-performances.tsx
  • ~ src/lib/import/gym-matcher.ts
  • ~ src/lib/import/index.ts
  • ~ src/lib/import/schedule-import.ts
  • ~ src/lib/import/team-matcher.ts

Version 0.2.7

Admin feedback system, notifications, and map improvements

February 11, 2026 at 6:45 PM GMT+0
0e5b61e
Added
  • Admin feedback dashboard at /admin/feedback with stats cards (New, In Review, Resolved)
  • User feedback submission dialog accessible from navbar
  • Real-time notification system with unread count badge
  • Email notifications for feedback replies using Resend
  • Two-way messaging between users and admins on feedback items
  • Feedback categorization (General, Request Team/Gym, Correct Scores, Upload Logo)
  • Status tracking workflow (New → In Review → Resolved)
  • Sortable table columns on feedback list (Date, User, Type, Subject, Status)
  • Click column headers to toggle ascending/descending sort with visual indicators
  • Search and filter functionality for feedback management
  • Login count tracking in admin analytics dashboard
  • Follows column in admin analytics to track user engagement
  • Graceful map fallback UI for invalid/expired Mapbox tokens
  • Static map placeholder on homepage for local development
🔄Changed
  • Homepage map replaced with static placeholder to eliminate API errors in development
  • Map shows attractive gradient with icon and descriptive text
  • Production environment continues to use real interactive map with valid token
🐛Fixed
  • React key prop warning by using Fragment with proper keys in feedback list
  • Mapbox 403 Forbidden errors on homepage from expired/invalid token
  • Geocoding API errors by detecting token failures and showing fallback UI
  • Console errors from map tile requests with domain-restricted tokens

Files Changed

Created (25):
  • + MESSAGING_SYSTEM_IMPLEMENTATION.md
  • + src/app/admin/feedback/page.tsx
  • + src/app/api/admin/feedback/route.ts
  • + src/app/api/admin/feedback/[id]/route.ts
  • + src/app/api/admin/feedback/[id]/message/route.ts
  • + src/app/api/admin/feedback/[id]/messages/route.ts
  • + src/app/api/feedback/route.ts
  • + src/app/api/notifications/route.ts
  • + src/app/api/notifications/[id]/read/route.ts
  • + src/app/api/notifications/unread-count/route.ts
  • + src/components/admin/feedback/feedback-list.tsx
  • + src/components/admin/feedback/message-thread.tsx
  • + src/components/admin/feedback/send-message-form.tsx
  • + src/components/feedback/feedback-button.tsx
  • + src/components/feedback/feedback-dialog.tsx
  • + src/components/navbar/notification-bell.tsx
  • + src/components/notifications/notification-item.tsx
  • + src/components/notifications/notification-list.tsx
  • + src/lib/emails/feedback-reply-email.ts
  • + src/lib/notifications.ts
  • + src/types/feedback.ts
  • + src/types/notification.ts
  • + ADMIN_ANALYTICS_LOGIN_TRACKING_FIX.md
  • + scripts/migrations/initialize-login-counts.ts
  • + scripts/verify-analytics-columns.ts
Modified (10):
  • ~ prisma/schema.prisma
  • ~ src/app/admin/page.tsx
  • ~ src/app/notifications/page.tsx
  • ~ src/components/navbar.tsx
  • ~ src/components/gyms/gyms-map.tsx
  • ~ src/components/home/gyms-map-section.tsx
  • ~ src/app/admin/analytics/page.tsx
  • ~ src/components/admin/analytics/users-table.tsx
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/lib/auth.ts

Version 0.2.6

Competition schedules feature with PDF import and mobile optimization

February 11, 2026 at 4:00 AM GMT+0
5bb93fa
Added
  • Public competition schedules browser at /schedules with advanced filtering
  • User schedule management at /[username]/schedules for saved custom schedules
  • Schedule PDF import system with timezone-aware parsing (Eastern Time)
  • Custom schedule creator - select specific teams/entries to build personalized schedules
  • Multi-level filtering: gym, team, level, age, size, session, date, and location
  • Schedule grouping and sub-grouping (by stage, team, gym, level, age, size)
  • Collapsible day groups and secondary groups for better mobile navigation
  • Manual timezone calculation for consistent Eastern Time display across all browsers
  • Schedules navigation link in sidebar and mobile drawer
  • Schedules CTA section on home page with dual CTAs for logged out users
  • Signup prompt banner on schedule pages for non-authenticated users
  • date-fns-tz package for reliable timezone handling
🔄Changed
  • Mobile schedule cards redesigned: 50% more compact layout
  • Reduced card padding from 24px to 12px for tighter mobile display
  • Location field moved inline with gym name to save vertical space
  • Smaller text sizes and tighter element spacing on mobile cards
  • Home page pillar section updated to support dual CTAs
  • Navigation sidebar now shows 'Schedules' link dynamically based on auth state
  • Mobile users can now see 2-3 schedule cards per screen instead of 1-1.5
🐛Fixed
  • Timezone display inconsistency - all times now show in Eastern Time regardless of user's local timezone
  • Browser timezone APIs unreliability - replaced with manual UTC offset calculation
  • Mobile schedule grouping and sub-grouping not working (added tertiary group support)
  • Schedule cards too large on mobile - reduced height by 50%
  • Missing collapsible functionality on mobile grouped schedules

Files Changed

Created (22):
  • + src/app/[username]/schedules/page.tsx
  • + src/app/schedules/page.tsx
  • + src/app/schedules/[slug]/page.tsx
  • + src/app/api/schedules/route.ts
  • + src/app/api/schedules/[slug]/entries/route.ts
  • + src/app/api/schedules/[slug]/filter-options/route.ts
  • + src/app/api/schedules/[slug]/metadata/route.ts
  • + src/app/api/user-schedules/route.ts
  • + src/app/api/user-schedules/[id]/route.ts
  • + src/components/schedules/schedule-table.tsx
  • + src/components/schedules/schedule-card.tsx
  • + src/components/schedules/grouped-schedule-table.tsx
  • + src/components/schedules/grouped-schedule-cards.tsx
  • + src/components/schedules/schedule-viewer.tsx
  • + src/components/schedules/schedule-filters-sidebar.tsx
  • + src/components/schedules/schedule-filters-sheet.tsx
  • + src/components/schedules/save-schedule-dialog.tsx
  • + src/components/schedules/saved-schedules-list.tsx
  • + src/components/schedules/searchable-checkbox-list.tsx
  • + src/components/schedules/signup-prompt-banner.tsx
  • + src/components/ui/scroll-area.tsx
  • + scripts/import/import-schedule-pdf.ts
Modified (12):
  • ~ package.json
  • ~ package-lock.json
  • ~ src/components/dashboard/sidebar-nav.tsx
  • ~ src/components/navbar.tsx
  • ~ src/app/page.tsx
  • ~ src/components/home/pillar-section.tsx
  • ~ src/components/home/pillar-visuals.tsx
  • ~ src/components/schedules/schedule-table.tsx
  • ~ src/components/schedules/schedule-card.tsx
  • ~ src/components/schedules/grouped-schedule-table.tsx
  • ~ src/components/schedules/grouped-schedule-cards.tsx
  • ~ src/components/schedules/schedule-viewer.tsx

Version 0.2.5

Groups dashboard redesign and multi-day competition date fixes

February 10, 2026 at 2:30 AM GMT+0
de77096
Added
  • Root-level /groups redirect page for proper authenticated routing
  • Zoom functionality on comparison line chart with interactive Brush component
  • Column sorting with visual indicators (arrows) on all comparison table columns
  • Custom tooltip for line chart showing team colors, C.PS scores, competition names, and rounds
  • Year display on line chart X-axis dates (e.g., 'Jan 31, 2025')
  • performedAt field to Performance model for accurate multi-day competition dates
  • Database index on performedAt for efficient date-based queries
🔄Changed
  • Replaced bar and radar charts with continuous line chart showing C.PS progression over time
  • Comparison table now shows only C.PS in collapsed view (removed ES, PS, Total columns)
  • Column order updated to: RS → DED → C.PS → detailed score columns
  • Each score component displayed as single sortable column instead of combined Diff/Exec
  • Line chart maximized to fill full section width (500-600px height)
  • Y-axis domain adjusted to actual data range with 5% padding for better visualization
  • Sidebar sticky behavior with max-height constraint and internal scrolling
  • Rankings now based on C.PS (calculatedPerformanceScore) instead of Total score
  • Team page Athletes section moved to bottom, Division History section removed
  • Chart displays use performedAt for accurate dates on multi-day competitions
🐛Fixed
  • Avatar component missing 'use client' directive causing page crashes and 404 errors
  • Multi-day competition dates showing duplicates (now displays unique performedAt per round)
  • Missing calculatedPerformanceScore in analysis panel scoreFields array for proper averaging
  • Missing performedAt field in groups page performance data transformation
  • Date formatting with UTC timezone to prevent timezone shifting issues
  • Groups page 404 error with proper authentication and redirect handling
  • Recent performances showing incorrect dates due to missing performedAt data
  • Line chart width constraint preventing full section display

Files Changed

Created (2):
  • + src/app/groups/page.tsx
  • + scripts/fix-aca-2025-dates.js
Modified (17):
  • ~ prisma/schema.prisma
  • ~ src/middleware.ts
  • ~ src/lib/auth.ts
  • ~ src/lib/utils.ts
  • ~ src/types/next-auth.d.ts
  • ~ src/types/charts.ts
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/app/[username]/groups/page.tsx
  • ~ src/components/ui/avatar.tsx
  • ~ src/components/app-shell.tsx
  • ~ src/components/my-teams/analysis-panel.tsx
  • ~ src/components/compare/comparison-charts.tsx
  • ~ src/components/compare/comparison-table.tsx
  • ~ src/components/teams/team-ps-chart.tsx
  • ~ src/components/teams/team-ps-chart-wrapper.tsx
  • ~ src/components/teams/score-trend-chart.tsx
  • ~ src/components/teams/competition-performance-table.tsx

Version 0.2.4

Account switcher, email verification, and UI enhancements

February 9, 2026 at 3:15 PM GMT+0
bba9135
Added
  • Twitter-style instant account switching without re-authentication
  • Account switcher dialog accessible from navbar user menu
  • Account storage system with session token management (max 5 accounts)
  • Email verification system with verification badges and banners
  • Email verification API endpoints (verify-email, resend-verification)
  • Account sync component for multi-device session management
  • Session token API endpoint for secure token retrieval
  • Verification banner on unverified accounts
  • Profile creation utility library for streamlined onboarding
  • Feature gates system for tier-based feature access
  • Season filter UI component for unified filtering
  • Max points calculation library for score normalization
🔄Changed
  • Login page enhanced with account switcher integration
  • Signup flow updated to support account switching
  • Onboarding profile page streamlined with new utilities
  • Dashboard layout updated with account sync component
  • Navbar user menu now includes account switcher option
  • Auth system extended to store session tokens in JWT
  • Registration endpoint enhanced with email verification
  • User model extended with email verification fields
🐛Fixed
  • Competition performances component data loading and error handling
  • Explore results component search and filtering logic
  • Gym PS chart data fetching and display issues
  • Team PS chart rendering and data transformation
  • Competition performance table sorting and display
  • Admin analytics users table pagination and filtering
  • Performance API routes authorization and data validation

Files Changed

Created (14):
  • + src/app/api/auth/get-session-token/route.ts
  • + src/app/api/auth/switch-account/route.ts
  • + src/app/api/auth/verify-email/route.ts
  • + src/app/api/auth/resend-verification/route.ts
  • + src/app/verify-email/page.tsx
  • + src/components/account-sync.tsx
  • + src/components/verification-banner.tsx
  • + src/components/ui/season-filter.tsx
  • + src/lib/email-verification.ts
  • + src/lib/feature-gates.ts
  • + src/lib/max-points.ts
  • + src/lib/profile-creation.ts
  • + docs/EMAIL_VERIFICATION.md
  • + docs/EMAIL_TEMPLATE_CUSTOMIZATION.md
Modified (19):
  • ~ prisma/schema.prisma
  • ~ src/app/api/auth/register/route.ts
  • ~ src/app/api/performances/[id]/route.ts
  • ~ src/app/api/performances/route.ts
  • ~ src/app/dashboard/layout.tsx
  • ~ src/app/login/page.tsx
  • ~ src/app/onboarding/profile/page.tsx
  • ~ src/app/signup/page.tsx
  • ~ src/components/account-switcher/account-switcher-dialog.tsx
  • ~ src/components/admin/analytics/users-table.tsx
  • ~ src/components/competitions/competition-performances.tsx
  • ~ src/components/explore/explore-results.tsx
  • ~ src/components/gyms/gym-ps-chart.tsx
  • ~ src/components/navbar.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/components/teams/team-ps-chart.tsx
  • ~ src/lib/account-storage.ts
  • ~ src/lib/auth.ts
  • ~ src/types/next-auth.d.ts

Version 0.2.3

Prisma relation naming fixes and type safety improvements

February 9, 2026 at 1:30 AM GMT+0
6304b2c
🐛Fixed
  • 180+ TypeScript compilation errors from Prisma Client relation naming conventions
  • All Prisma relation names capitalized in includes/selects (Team, Gym, Person, etc.)
  • Field IDs normalized to lowercase camelCase (teamId, personId, etc.)
  • Added required id and updatedAt fields to all create operations
  • Data transformation for components expecting lowercase property names
  • Complex Prisma relation names in self-referential models
Added
  • npm run type-check script for quick TypeScript validation
  • GitHub Actions CI workflow for automated type checking on PRs
  • Comprehensive PRISMA_CONVENTIONS.md documentation guide
  • Documentation of all Prisma naming patterns and transform strategies
  • Troubleshooting guide for common Prisma type errors
🔄Changed
  • Standardized all Prisma queries to use capitalized relation names
  • Implemented data transformation layer for client components
  • Enhanced build process to include Prisma generate automatically

Files Changed

Created (2):
  • + .github/workflows/type-check.yml
  • + docs/PRISMA_CONVENTIONS.md
Modified (26):
  • ~ package.json
  • ~ src/app/admin/gyms/page.tsx
  • ~ src/app/admin/performances/page.tsx
  • ~ src/app/admin/users/page.tsx
  • ~ src/app/api/admin/users/[id]/route.ts
  • ~ src/app/api/admin/users/route.ts
  • ~ src/app/api/competitions/[id]/route.ts
  • ~ src/app/api/competitions/route.ts
  • ~ src/app/api/gyms/[id]/route.ts
  • ~ src/app/api/gyms/route.ts
  • ~ src/app/api/teams/route.ts
  • ~ src/app/competitions/[id]/page.tsx
  • ~ src/app/competitions/page.tsx
  • ~ src/app/gyms/[id]/page.tsx
  • ~ src/app/gyms/page.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/people/page.tsx
  • ~ src/app/search/page.tsx
  • ~ src/app/teams/[id]/page.tsx
  • ~ src/app/teams/page.tsx
  • ~ src/app/settings/page.tsx
  • ~ src/app/onboarding/profile/page.tsx
  • ~ src/components/competitions/competitions-list-client.tsx
  • ~ src/components/gyms/gym-teams-section.tsx
  • ~ src/components/dashboard/feed-list.tsx
  • ~ src/lib/analytics/division-benchmarks.ts

Version 0.2.2

Blog system, username search, and profile enhancements

February 8, 2026 at 7:00 PM GMT+0
4d51bbd
Added
  • Complete blog system with MDX support and React component embedding
  • Admin interface for creating, editing, and managing blog posts
  • Public blog listing page with search, filtering by category/tag
  • Blog post pages with SEO optimization and Open Graph metadata
  • Username search functionality in main search and people search
  • Profile picture upload system separate from cover photos
  • Scalloped circle tier badge design with enhanced visual hierarchy
  • Blog link in footer navigation for easy access
🔄Changed
  • Profile page mobile layout and module ordering improved
  • Competition performance table simplified (removed redundant Total column)
  • Tier badge design updated to scalloped circle style
🐛Fixed
  • Hydration error in VerificationBadgeIcon component
  • Profile page loading performance optimized
  • Admin permissions for profile picture management

Files Changed

Created (23):
  • + BLOG_SYSTEM.md
  • + content/blog/welcome-to-cheer-data-blog.mdx
  • + content/blog/understanding-performance-metrics.mdx
  • + content/blog/getting-started-guide.mdx
  • + src/app/blog/page.tsx
  • + src/app/blog/[slug]/page.tsx
  • + src/app/admin/blog/page.tsx
  • + src/app/admin/blog/new/page.tsx
  • + src/app/admin/blog/[slug]/edit/page.tsx
  • + src/app/api/admin/blog/save/route.ts
  • + src/app/api/admin/blog/[slug]/route.ts
  • + src/components/blog/blog-card.tsx
  • + src/components/blog/blog-filters.tsx
  • + src/components/blog/blog-post-layout.tsx
  • + src/components/blog/author-card.tsx
  • + src/components/admin/blog/blog-editor.tsx
  • + src/components/admin/blog/delete-post-button.tsx
  • + src/lib/blog.ts
  • + src/types/blog.ts
  • + mdx-components.tsx
  • + src/app/api/person/profile-picture/route.ts
  • + src/components/profile/profile-picture-upload.tsx
  • + src/lib/roles.ts
Modified (14):
  • ~ src/app/layout.tsx
  • ~ src/app/people/[username]/page.tsx
  • ~ src/app/api/search/route.ts
  • ~ src/app/api/people/search/route.ts
  • ~ src/components/navbar.tsx
  • ~ src/components/home-search.tsx
  • ~ src/components/teams/competition-performance-table.tsx
  • ~ src/components/ui/verification-badge-icon.tsx
  • ~ src/components/profile/tier-verification-badge.tsx
  • ~ src/components/profile/profile-photo-manager.tsx
  • ~ src/components/profile/profile-card-clean.tsx
  • ~ src/app/api/person/photos/route.ts
  • ~ next.config.js
  • ~ package.json

Version 0.2.1

Profile photo upgrades and explore polish

February 6, 2026 at 10:12 PM GMT+0
0afef81
Added
  • Profile photo management with cropping and aspect ratio controls
  • Tier badges on profile headers and tier-aware avatars
  • City display for gym/team explore cards when available
  • Athlete avatars and alphabetized athlete lists on team/gym pages
  • PersonPhoto model to support multi-photo profiles
🔄Changed
  • Profile header layout refinements for clearer identity and actions
  • People list uses photoUrl for more consistent profile imagery
🐛Fixed
  • Competition performances payload serialization for detail pages
  • Profile admin form twitter handle typo
  • Tier gating and typing issues in profile photo flows

Version 0.2.0

Major Feature Expansion - Monetization, Exports, Glossary

February 5, 2026 at 6:00 AM GMT+0
8949a30
Added
  • 4-tier monetization system (Novice/Prep/Elite/Pro) with feature gating
  • PDF export for team comparisons and profile reports (Prep tier)
  • Division benchmarks analytics API and Prep-tier access
  • Public glossary with admin management and supplemental terms
  • Admin tools for profile photos, score maximums, and analytics
🔄Changed
  • Homepage redesign and navigation updates for clearer conversion flow
  • People/teams/gyms views with richer filters and profile visuals
🐛Fixed
  • Production build issues across API routes and PDF rendering
  • TypeScript and ESLint errors in UI and export flows

Version 0.1.0

Initial Release - Analytics Dashboard

February 4, 2026 at 6:00 AM GMT+0
695a050
Added
  • Public changelog page at `/changelog` with version history
  • Version display in footer (v0.1.0) with link to changelog
  • Changelog data structure in CHANGELOG.json with full type safety
  • Comprehensive user analytics dashboard at `/admin/analytics`
  • Login tracking system with `lastSeenAt` field in User model
  • 10 key metrics including WAU, conversion rate, and retention
  • Daily signups bar chart showing last 30 days of user growth
  • Tier growth stacked area chart for free vs paid user trends
  • Throttled activity tracking (updates once per hour max)
  • 5-minute API response cache for analytics endpoint
  • Reusable metric card component for admin dashboards
  • Helper script for adding changelog entries (npm run changelog:helper)
🔄Changed
  • Updated JWT callback to include lastSeenAt tracking
  • Enhanced Prisma schema with user activity tracking
  • Added index on lastSeenAt field for query performance
🐛Fixed
  • ESLint error with apostrophes in landing page copy
  • Profile picture display issues in settings
  • Score maximums API routes for static generation

Files Changed

Created (11):
  • + CHANGELOG.json
  • + CHANGELOG_GUIDE.md
  • + src/app/changelog/page.tsx
  • + src/types/changelog.ts
  • + scripts/add-changelog-entry.ts
  • + src/types/analytics.ts
  • + src/app/api/admin/analytics/users/route.ts
  • + src/app/admin/analytics/page.tsx
  • + src/components/admin/analytics/metric-card.tsx
  • + src/components/admin/analytics/daily-signups-chart.tsx
  • + src/components/admin/analytics/tier-growth-chart.tsx
Modified (10):
  • ~ prisma/schema.prisma
  • ~ src/lib/auth.ts
  • ~ src/types/next-auth.d.ts
  • ~ src/app/admin/page.tsx
  • ~ src/app/layout.tsx
  • ~ src/components/navbar.tsx
  • ~ package.json
  • ~ README.md
  • ~ docs/CLAUDE.md
  • ~ DOCUMENTATION_INDEX.md

About This Changelog

This changelog follows the format inspired by Keep a Changelog. All notable changes to FullOut are documented here.

Each release includes the version number, release date with timezone, git commit hash, and a detailed summary of all changes organized by type.