Feature Matrix
So what: OpenRally's v0.1-v0.5 plan covers ~40% of wecourts's shipped organizer surface and ~25% of the player surface. The biggest functional gaps are bracket-format breadth (Groups+KO, Americano, KOC, Leagues), the WPPR-style rating moat (OpenRally explicitly out-of-scope), in-platform messaging / WhatsApp deep-linking, the TV / venue-display product, the public developer API, and the identity-graph / cross-tournament player profile. The deepest gap with the smallest engineering cost-to-close is WhatsApp-context-aware deep links + LFP (Looking-for-Partner).
OpenRally source: /Users/mrmading/Desktop/Cowork/openrally/apps/web/DECISIONS.md (web-side) + sister openrally-backend/DECISIONS.md referenced.
Legend in "Wecourts" col: ✅ shipped / 🔧 in progress / 📅 planned (public roadmap) / ❌ not shipped. Legend in "OpenRally" col: ✅ in plan (with version) / 🚫 explicitly out-of-scope / ⚠️ not in plan / 🔧 partial.
Update 2026-05-22 post-onboarding walk — rows updated below to upgrade inference → observation where the onboarding walk produced new evidence. The actual create-tournament wizard remains gated by manual approval; some "?" rows still resolved by other evidence sources (redesigned WPPR page, federation partnerships, smart-court integrations).
Tournament formats & bracket types
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Single-elimination | ✅ R32→R16→QF→SF→F observed | ✅ v0.4 (W33-W41), v0.5 bracket UI (W46-W51) | 13-sample-event.text.txt; DECISIONS §v0.5 W46 |
Parity expected at v0.5 |
| Groups + Knockout (configurable Top-N qualifies) | ✅ "Top 2" and "Top 3" variants both shipped | ⚠️ Not in v0.5 plan | 29-event-5GLP.text.txt (Top 2) + 30-event-N3UE.text.txt (Top 3) |
Functional gap |
| Direct Advance (uneven groups auto-qualify) | ✅ shipped Apr 22 2026 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 22 entry |
Sophistication gap |
| Minimum Games Guarantee (MGG, ≥3 matches via Pre-rounds for 12/14/18 teams) | ✅ shipped Apr 17 2026 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 17 entry |
Sophistication gap |
| Round Robin (full pool) | ✅ nav lists "Round Robin" | ⚠️ Not in plan | nav extract "Run TournamentsGroup Stage / Knockouts, Round Robin, King of Court, Americano and more" |
Functional gap |
| King of Court (KOC) | ✅ Operator Console has KOC tab | ⚠️ Not in plan | 34-featurebase-changelog.text.txt 2026-05-04 ("KOC") |
Functional gap |
| Americano | 🔧 live-testing in prod (/t/33F8) |
⚠️ Not in plan | 45-americano-event.text.txt; founder-submitted test event |
Both incomplete — winnable wedge |
| Mexicano | ❌ not advertised | ⚠️ Not in plan | absent from nav extract | Neutral |
| Swiss | ❌ not advertised | ⚠️ Not in plan | absent | Neutral |
| Leagues (weekly openrallys, cumulative standings, promotion/relegation, playoffs) | 📅 Planned | ⚠️ Not in plan | 32-featurebase.text.txt "WeCourts League Support" |
Both incomplete — strategic question |
| Consolation Draw (second-chance for group losers) | 📅 Planned | ⚠️ Not in plan | 32-featurebase.text.txt "Match Center — Consolation Draw Support" |
Both incomplete |
| Private / invite-only tournaments | 📅 Planned | ⚠️ Not in plan | 32-featurebase.text.txt "Private Tournaments" |
Both incomplete |
| Match scoring (best-of-3 sets, set scores) | ✅ shipped (e.g., 7-5, 6-4, 6-3) | ✅ v0.4 plan implies scoring; v0.5 Generate buttons → bracket finalization | 13/29/30/31-event-*.text.txt; DECISIONS §v0.5 W48 |
Parity expected |
| Tournament status states (Draft → Open Reg → Live → Ended → Results Submitted → Published to WPPR) | ✅ all observed | 🔧 v0.4 has draft/open/closed/published; "Awaiting verification" state absent | DECISIONS §v0.4 W41 status_transition.tsx mentions Open/Close Registration | Sophistication gap (verification queue) |
Player identity & rating
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Proprietary rating algorithm (WPPR) | ✅ 13-tier letter bands D- → A+, 0.0-8.0 numeric, 4 dimensions, updates every 20 matches, AI calc | 🚫 Explicit non-goal: "No OpenRally-built rating algorithm (v3 integrates external)" | 06-rating-levels.text.txt; DECISIONS apps/web/DECISIONS.md anti-patterns block |
Strategic divergence — by choice |
| External rating ingestion (5-7 day review SLA) | ✅ /drop-in Submit Results |
⚠️ Not in plan | 07-drop-in.text.txt |
Likely will need this when v3 integrates external |
| Player profile with match history + career stats + win rate + gold/silver medal count | ✅ shipped Mar 13 2026 | 🔧 v0.4 W33 player tournament detail exists; cross-tournament profile not yet | 34-featurebase-changelog.text.txt Mar 13 entry; DECISIONS §v0.4 W33 |
Functional gap (cross-tournament aggregation) |
| Rating Progression chart (per-match cycle view, projected next rating) | ✅ shipped May 13 2026 | ⚠️ N/A while rating algorithm is out-of-scope | 34-featurebase-changelog.text.txt May 13 entry |
Will reappear when v3 external rating integrates |
| Shareable rich-preview profile URL (WhatsApp / social) | ✅ shipped | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Mar 13 entry |
Functional gap (cheap, high-leverage) |
| Player search by name, country, rating tier (fuzzy match) | ✅ global, including non-account-holders | ⚠️ Not in plan | 02-wppr.text.txt Players Hub |
Functional gap |
| Country / nationality on player card | ✅ shipped + flag icon | ⚠️ Not in plan ("Match Center — Nationalities Module" still planned for wecourts) | 02-wppr.text.txt player cards show nationality + flag |
Functional gap (both incomplete — but wecourts is closer) |
| Hand (R/L) + Side (R/L/Both) + Years experience | ✅ shipped on player cards | ⚠️ Not in plan | 02-wppr.text.txt; 43-may-grand-clash.text.txt LFP cards |
Functional gap (padel-domain detail) |
| Duplicate-profile merge UI | ❌ broken / regressed | ⚠️ Not in plan | Featurebase: Jiten 8 days ago, "could not find a way to merge or link the duplicate profile" | Wedge opportunity — ship cleanly from day 1 |
Registration & partner-matching
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Solo registration | ✅ | ✅ v0.4 W34 register-solo-button | 34-featurebase-changelog.text.txt Apr 30; DECISIONS §v0.4 W34 |
Parity |
| Doubles registration (with partner) | ✅ partner search modal, WPPR-filter, invite | ✅ v0.4 W35 partner-search-modal, W36 register-doubles-launcher, W37 invite | DECISIONS §v0.4 W35-W37 | Parity |
| Waitlist | ✅ shipped (LFP, waitlist position visible) | ✅ v0.4 W40 registrations-tab bucket "waitlisted" | DECISIONS §v0.4 W40 | Parity |
| Looking-for-Partner (LFP) public listing | ✅ with WPPR card, hand, side, experience; mobile masked until login | ⚠️ Not in plan | 43-may-grand-clash.text.txt 5-LFP block |
Functional gap (high-impact) |
| "Complete partner's profile" 1-click backfill (auto-detects missing fields) | ✅ shipped Apr 30 2026 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 30 |
Functional gap |
| Partner ≠ self guard (block registering own mobile as partner) | ✅ shipped | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 30 |
Functional gap (cheap) |
| Partner mobile masking (last 4 digits only in some views) | ✅ shipped | ⚠️ Not in plan | same | Functional gap (privacy / cheap) |
| Trusted-name validation (reject "test/tbd/asdf"; allow complex Arabic names) | ✅ shipped | ⚠️ Not in plan | same | Functional gap (cheap) |
| Phone number paste normalization (tel: prefix, country-code etc.) | ✅ shipped | ⚠️ Not in plan | same | Functional gap (cheap) |
| Mixed-doubles tournament category | ✅ explicit 👫 icon in card + filter | ⚠️ Not in plan | 43-may-grand-clash.text.txt "👫 Mixed" |
Functional gap |
| Kids / youth segmentation (U12 / U14 / U16 / U18) | ✅ visible (DSG U14 Boys, U16 Boys, U18-Mothers Day) | ⚠️ Not in plan | 16-results-tracker.text.txt DSG entries |
Functional gap |
| Cancelled tournament handling | ✅ shipped (status state + UI) | 🔧 v0.4 W41 has Close Registration (close-registration body mentions "pending invites will be expired") but no full-cancel flow | DECISIONS §v0.4 W41 F08 amendment | Sophistication gap |
| Waiver / resubmit results | ✅ shipped Apr 30 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 30 |
Functional gap |
Organizer power-user features
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| AI poster-to-form extraction (upload tournament poster → autofill) | ✅ marketed | ⚠️ Not in plan | 15-new-tournament.text.txt |
Sophistication gap |
| Tournament duplication (with trust-tier auto-approval) | ✅ shipped | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 30 |
Functional gap (cheap) |
| Multi-organizer collaboration on single tournament (RBAC) | ✅ shipped | ⚠️ Not in plan | 32-featurebase.text.txt "Collaboration Accounts" (Completed) |
Functional gap |
| Organizer Hub Mega Menu | ✅ shipped May 4 | 🔧 OpenRally v0.3 admin surface exists (W19-W23); organizer surface v0.3 W25-W31; "Hub" concept distinct | 34-featurebase-changelog.text.txt May 4 entry; DECISIONS §v0.3 admin/organizer |
Parity-ish |
| Organizer Command Palette (Ctrl+K to find actions, players, tournaments) | ✅ shipped May 4 | ⚠️ Not in plan | same | Functional gap |
| SOS Console (emergency actions: Add/Replace/Change/Move/Swap/Restart...) with 3 outcome modes on disqualification | ✅ shipped Apr 18 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 18 entry |
Major functional gap — operator-trust feature |
| Improved Team Removal & Incident Controls (forfeit-wins / zero-unplayed / void-all) | ✅ shipped May 4 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt May 4 entry |
Functional gap |
| Top-seed picker (instant team list on "+ Add") | ✅ shipped Apr 30 | 🔧 v0.5 W47 seeding-panel does drag-drop seeding | 34-featurebase-changelog.text.txt Apr 30; DECISIONS §v0.5 W47 |
Sophistication gap (OpenRally is more axe-friendly via D13 KeyboardSensor — actually a wecourts gap) |
| Magic links (shareable, auth-less access to tournament views) | ✅ shipped | ⚠️ Not in plan | 34-featurebase-changelog.text.txt May 4 entry "magic links" |
Functional gap |
| Public roadmap + changelog | ✅ Featurebase tenant publicly viewable | ⚠️ Not in plan; PRs + DECISIONS.md tracked internally only | 32/34-featurebase*.text.txt |
Strategic gap (perception / trust) |
| Operator trust ladder (probation → standard → trusted; affects auto-approval) | ✅ inferred from "Trusted organizers skip approval" + Community Guidelines "organizer restrictions" | 🔧 v0.3 W18-W23 admin surface has organizer-applications approve/reject (binary, not tiered) | 34-featurebase-changelog.text.txt Apr 30; DECISIONS §v0.3 W20-W21 |
Sophistication gap |
| "Overdue Results" public shame board (organizers with overdue published results) | ✅ shipped | ⚠️ Not in plan | 04-organizers.text.txt "Organizers with Overdue Results" section |
Functional gap (accountability moat) |
| Multi-Branch Clubs (one account, multiple physical locations) | 📅 Planned | ⚠️ Not in plan | 32-featurebase.text.txt "Multi-Branch Clubs" |
Both incomplete |
Venue / club management
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Club directory with map embed | ✅ Google Maps, Get Directions, Send to WhatsApp/Call | 🔧 v0.3 W26 venue creation with court_names per D-spec | DECISIONS §v0.3 W26 venue/new; 20-club-detail.text.txt |
Sophistication gap |
| Per-club page with hours, facilities (changing rooms, lighting, equipment, coaching, parking, shower, snack bar, wheelchair access) | ✅ shipped, auto-tagged | ⚠️ Not in plan beyond venue creation form | 20-club-detail.text.txt (10 courts, 13 facilities, hours per day) |
Functional gap |
| Club + tournament cross-link (tournament card shows venue; club page links tournaments) | ✅ both directions | 🔧 v0.4 W33 tournament page shows venue; reverse link not in plan | DECISIONS §v0.4 W33 | Sophistication gap |
| Federation integration (Jordan Tennis Fed, UAEPA, Pakistan Padel Fed listed as organizers) | ✅ shipped | ⚠️ Not in plan | 04-organizers.text.txt WPPR Verified Organizers list |
Strategic gap |
| Court / time-slot allocation (specific court assignment per match) | ❓ not directly observed in public surface; SOS "Move Team to Group" implies group-level only | ⚠️ Not in plan ("Scheduling UI" reserved for v0.5.0+ per AGENTS.md) | DECISIONS §v0.5+ note re dnd-kit for scheduling |
Both incomplete |
Communications
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Email (registration confirms, WPPR updates) | ✅ implied (verify-email observed; SLA emails inferred) | ✅ OpenRally-backend Edge Functions own all email (Resend SDK) | 28-post-signup.png; DECISIONS apps/web/DECISIONS.md "Email: Sent server-side from openrally-backend Edge Functions" |
Parity |
| In-app messaging widget (Featurebase) | ✅ live on every page (/v1/messenger/widget/*) |
⚠️ Not in plan | network capture | Functional gap |
| WhatsApp deep-linking with context-aware CTAs (Solo→Add partner; LFP→Manage; Waitlist→Position; Match day→Schedule) | ✅ shipped Apr 30 | ⚠️ Not in plan | 34-featurebase-changelog.text.txt Apr 30 |
Functional gap (huge in MENA; relevant in SEA too — WhatsApp dominant in Thailand/Indonesia) |
| WhatsApp verification on partner mobile add | ✅ shipped | ⚠️ Not in plan | same | Functional gap |
| SMS / OTP authentication for players | ✅ shipped (player Continue with Mobile path) | 🔧 v0.2.0 brings Facebook/Google/Apple OAuth per DECISIONS; SMS OTP not in plan | 14-matches-create.text.txt; DECISIONS apps/backend/CLAUDE.md Auth note |
Functional gap (player-acquisition friction) |
| Push notifications to "relevant players" | ✅ marketed (/new page) |
⚠️ Not in plan | 15-new-tournament.text.txt |
Functional gap |
| Public roadmap discussion / feedback collection | ✅ Featurebase (vote, comment, status) | ⚠️ Not in plan | 32-featurebase.text.txt |
Strategic gap |
Payments & monetization
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| In-platform fee collection | 🔧 In Progress | 🚫 Explicit non-goal v1: "No payment processing (offline collection in v1; v5 introduces payments)" | 32-featurebase.text.txt In Progress; openrally-backend/CLAUDE.md "What this repo does NOT contain" |
Both incomplete; OpenRally explicit non-goal v1-v4 |
| Refunds | 🔧 In Progress | 🚫 v1 non-goal | same | Both incomplete |
| Payouts to organizers | 🔧 In Progress | 🚫 v1 non-goal | same | Both incomplete |
| Multi-currency display (AED, JOD observed) | ✅ shipped | ⚠️ Not in plan ("Thailand-first" implies THB only initially) | 43-may-grand-clash.text.txt AED + 46-jordan-drawer.text.txt JOD |
Functional gap (foreseeable for SEA + global) |
| Conditional / escalating prize-pool clauses ("Full prize granted only when reaching at least 30 out of 32 teams") | ✅ shipped (free-text in description) | ⚠️ Not in plan as structured field | 43-may-grand-clash.text.txt |
Sophistication gap |
| Prize-pool field as structured first-class data | ⚠️ free-text in About; structured prize tiers (1st/2nd/3rd) shown in registration drawer | ⚠️ Not in plan | 43-may-grand-clash.text.txt "🏆 1st AED 5000" block |
Both partial |
Developer / integration layer
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Public REST API for partners | ✅ "Now Live" at developers.wecourts.com (Bearer token, gated) |
⚠️ Not in plan | 12-dev-api.text.txt |
Strategic gap |
| Anti-sandbagging API (fair-play matchmaking lookup) | ✅ marketed as use case | 🚫 No rating algorithm = no anti-sandbagging lens | same | Strategic divergence by choice |
| Player search API (by name, fuzzy, contextual within club/org) | ✅ shipped | ⚠️ Not in plan | same | Strategic gap |
| Webhook outbound to organizers / clubs | ❓ not directly observed | ⚠️ Not in plan | dev API page only describes inbound calls | Both unknown |
Venue display / live-events product
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| WeCourts TV (full-screen live results + brackets, big-screen venue display, QR pairing, 30s auto-refresh, fullscreen, poster mode) | ✅ shipped | ⚠️ Not in plan | 10-tv.text.txt |
Major strategic gap (revenue lever for venue partnerships) |
| Real-time bracket updates pushed to TV view | ✅ implied (30s auto-refresh + Operator Console "TV" tab) | 🔧 v1 includes Realtime channel tournament:{id}:bracket per openrally-backend/README.md |
10-tv.text.txt; openrally-backend/README.md Stack |
OpenRally has primitive; product layer missing |
| Watch Recap on WeCourts TV (post-tournament replay) | ✅ shipped (link on every event page) | ⚠️ Not in plan | 13-sample-event.text.txt "WATCH RECAP ON WECOURTS TV" |
Functional gap |
Community / engagement
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| WhatsApp-curated community pages (level-matched matchmaking, member approval, anti-spam) | ✅ surface built (1 community publicly listed) | ⚠️ Not in plan | 09-communities.text.txt |
Functional gap (MENA-native; relevant SEA too) |
| Player matchmaking (find partners / opponents at level + availability) | ✅ shipped | ⚠️ Not in plan (TPS owns mobile player surface per AGENTS.md) | 32-featurebase.text.txt "WeCourts Matchmaking" (Completed) |
Functional gap |
| Path to Victory (per-team narrative summary, auto-generated) | ✅ shipped | ⚠️ Not in plan | 13/29-event-*.text.txt "Path to Victory" + "Key Stat" auto-text |
Functional gap (delightful but low-priority) |
| Tournament "celebration" animation (post-win confetti / shareable card) | ✅ shipped | ⚠️ Not in plan | 13-sample-event.text.txt "Tap to view celebration" |
Functional gap |
| Live broadcast badge ("BROADCASTED LIVE") | ✅ shipped (free-text in title) | ⚠️ Not in plan | 01-home.text.txt "BPT 2.0 BROADCASTED LIVE" |
Both partial |
Platform / hygiene
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| i18n (multi-language UI) | ❌ English only despite locale dropdown | ✅ TH + EN bundles in v0.1.0 + RTL-ready architecture | every footer; DECISIONS apps/web/DECISIONS.md gate Q3 | OpenRally ahead — i18n is a moat |
| Multi-tenant white-label / branding | ❓ not observed | ⚠️ Not in plan | absent from surfaces walked | Both unknown |
| GDPR data export / deletion | ✅ stated in privacy policy | ✅ stated in TPS standards (cross-app rule) | 22-privacy.text.txt; TPS CLAUDE.md Security Standards |
Parity |
| Cookie consent banner | ❓ not observed (none triggered on plain visit) | ⚠️ Not in plan | none seen in browser | Both partial |
| Bot protection (Cloudflare Turnstile) | ✅ active on all routes | ⚠️ Not in plan | initial 403 from curl | Functional gap |
| Apple / Google / Facebook SSO | ✅ Google OAuth on signup form | ✅ v0.2.0 social providers (DECISIONS apps/backend/CLAUDE.md Auth) | 11-signup-organizer.text.txt; openrally-backend/CLAUDE.md |
Parity at v0.2 |
Summary by gap class
Functional gaps we should consider closing in v0.2-v0.5:
- WhatsApp-context-aware deep linking (cheap, high-leverage in SEA + MENA)
- Looking-for-Partner (LFP) listings with structured player meta (hand, side, exp)
- Shareable rich-preview player profile URL
- Tournament duplication
- Name validation + phone normalization + partner-≠-self guard (each <1 day eng)
- Mixed-doubles + kids/youth tournament category fields
- Magic links (auth-less shareable views)
- Multi-organizer collaboration on a single tournament (RBAC)
Sophistication gaps (OpenRally has primitive, lacks polish):
- Tournament status states need explicit "Awaiting verification" / "Results submitted" / "Published" once rating integrates v3
- Bracket-format breadth (Groups+KO, Direct Advance, MGG, Round Robin, KOC) — OpenRally only ships single-elim in v0.5
- Venue facilities catalogue (auto-tagged amenities) richer than current v0.3 W26 venue form
- Organizer trust ladder (probation → standard → trusted)
Strategic gaps (require explicit Nestor decision):
- Bracket-format breadth (Groups+KO, Americano, KOC, Leagues) — do we close to v1 / v2 ship, or stay single-elim?
- TV / venue-display product — yes/no/when?
- Federation integration — partner with TLPA (Thai Lawn Tennis & Padel Association) or equivalent?
- Public developer API — open ourselves to partners or stay closed?
- Public roadmap (Featurebase or similar) — do we ship a public roadmap to compete on trust?
- In-platform messaging widget (Featurebase or Plain or Crisp) — yes/no?
- Identity-graph / WPPR-style rating — DECISIONS.md says no in v1-v2; revisit?
Already-strong OpenRally positions (do not weaken):
- i18n from day 1 (TH + EN) — wecourts is English-only after 4 years; this is a real moat for SEA expansion
- Bracket library:
@g-loot/react-tournament-brackets(not hand-rolled) — bracket UI polish at low cost - Drag-drop seeding with
dnd-kit+ KeyboardSensor + native<select>fallback (D13) — wecourts's top-seed picker doesn't appear to ship explicit keyboard fallback - Lint zero-warnings + Lead + Security PR gate — wecourts's velocity is high but the user-reported regressions (duplicate profiles, lost merge UI) suggest weaker quality gates
Post-onboarding-walk additions (2026-05-22)
The Phase 3 partial walk surfaced new evidence on the rows below. Some are entirely new capabilities not in the original matrix.
Onboarding / signup flow (new section)
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
Role-split signup URL (/signup/organizer vs /signup/player) |
✅ shipped (separate routes, separate forms) | 🔧 v0.3 W20-W21 has organizer-application admin path; signup-role-split not in plan | onboarding walk; screenshots/11-signup-organizer.png + login screenshots/52 |
Sophistication gap |
Role-split login URL (/login/organizer vs /login/player) |
✅ shipped (different fields per role) | ⚠️ Not in plan | login walk this session | Sophistication gap (small) |
| Email verification (6-digit code) | ✅ shipped, 60s resend cooldown | ⚠️ Not in plan; OpenRally uses Supabase magic-link (different model) | screenshots/28-post-signup.png |
Functional gap (intentional — different auth model) |
| Onboarding state machine: signup → verify-email → /onboarding (path choice) → entity-create → /onboarding/pending-review → approval → Dashboard | ✅ shipped, all states observed | 🔧 v0.3 W20-W21 admin can approve/reject organizer-applications but the player-facing onboarding state machine doesn't have these intermediate states yet | this session's screenshots/51, 52, 53, 59, 60, 62, 63, 64 | Major sophistication gap |
| Two-persona organizer split (Padel Club vs Organizer Company) | ✅ shipped (different downstream entity types) | ⚠️ Not in plan; OpenRally currently has single Organizer model |
screenshots/52-onboarding-root.png |
Conceptual gap (worth importing) |
| Dedupe-search-before-create pattern (org list shown before "Create new") | ✅ shipped on both org-company and club paths | ⚠️ Not in plan; OpenRally's v0.3 organizer-applications doesn't show existing orgs to applicant | screenshots/53, 59 |
UX gap (cheap, anti-duplicate) |
| Manual organizer-approval gate (human review, WhatsApp notification) | ✅ shipped (SLA: "usually a few hours") | 🔧 v0.3 W20-W21 admin has Approve/Reject flow for organizer_application rows — but OpenRally's notification is email, not WhatsApp |
DECISIONS §v0.3 W20-W21; this session's screenshots/51-onboarding-pending.png |
Conceptual gap — OpenRally has the schema but not the WhatsApp-native approval moment |
| Auto-resolved phone via identity graph (pre-fills phone for known players) | ✅ shipped (Nestor's +66 number appeared without input) | ⚠️ Not in plan; requires identity graph (out-of-scope per "no rating algorithm" — but data graph is adjacent) | this session's screenshots/52 showing "✓ WhatsApp verified" |
Sophistication gap (depends on identity graph existing) |
| Dual-mode logo upload (file OR URL) on Company create | ✅ shipped | ⚠️ OpenRally v0.3 W11 logo cropper uses cropperjs+react-cropperjs (file upload only) | DECISIONS §v0.3 D1; screenshots/64-create-company-form.png |
Functional gap (cheap; URL-input as alt path) |
| Full ISO-3166 country list on signup | ✅ all countries selectable | ⚠️ Not directly observed in DECISIONS; v0.3 W26 venue form likely defaults Thailand-first | screenshots/61-country-dropdown.png (Afghanistan...Cambodia visible) |
Strategic gap — wecourts is technically global from day 1 even though they market MENA |
| Country-coupled City dropdown | ✅ shipped (City list depends on Country) | ⚠️ Not in plan; v0.3 W26 venue form is unclear | onboarding form structure | Functional gap (small) |
Player surface (new findings)
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Match Express (BETA) — single casual matches (not tournaments) with WPPR rating impact | ✅ shipped BETA — /matches route |
🚫 Out-of-scope ("TPS owns mobile player surface" per AGENTS.md) | screenshots/57-matches-beta.png |
Strategic divergence by choice (player surface = TPS's lane) |
| Filter tabs: All / WPPR / Open / Today / Free on match feed | ✅ shipped | N/A | 57-matches-beta.png |
N/A |
| Player can register provisional/initial rating ("IR" status) before 20-match cycle closes | ✅ shipped — "WPPR INITIAL RATING 7.587 IR A+ Provisional 10 matches" | 🚫 No rating algorithm in plan | raw-html/67-rating-wppr.text.txt |
Strategic divergence |
| Match Express filtering by "Free" — implies a paid-match type also exists | ✅ inferred from filter | ⚠️ N/A | 57-matches-beta.png |
N/A |
Federation & integration ecosystem (new section)
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Official rating partner for federations (Egypt Padel Federation, Jordan Tennis Federation) | ✅ shipped | ⚠️ Not in plan; partnerships strategy is GTM, not product | raw-html/67-rating-wppr.text.txt "OFFICIAL RATING PARTNER FOR Egypt Padel Federation, Jordan Tennis Federation" |
Strategic gap (BD/partnerships) |
| Booking-system API integrations (PadelOS, Epic Padel live; "and more") | ✅ shipped | ⚠️ Not in plan | raw-html/67-rating-wppr.text.txt "Booking Systems — Full APIs ready. Live with booking systems like PadelOS, Epic Padel, and more." |
Strategic gap (ecosystem play) |
| AI camera feeds (smart courts) auto-syncing match results | ✅ shipped/claimed | ⚠️ Not in plan | raw-html/67-rating-wppr.text.txt "AI Camera Feeds — Tracking match results and analytics seamlessly from smart courts powered by AI-powered smart courts." |
Functional gap (advanced, optional) |
| External rating aggregation ("WPPR Watch": FIP, Premier Padel, RankedIn, Winner App, Tournify) | ✅ shipped/claimed | 🔧 v3 will integrate external — direction matches | raw-html/67-rating-wppr.text.txt "WPPR Watch — Aggregating global data from FIP, Premier Padel, RankedIn, Winner App, and Tournify." |
Sophistication gap (OpenRally will need this for v3) |
| Whiteboard photo / Excel ingestion ("Zero Tech Barrier") | ✅ shipped/claimed (AI extraction) | ⚠️ Not in plan; could use Claude Vision | raw-html/67-rating-wppr.text.txt "Zero Tech Barrier — We accept WeCourts Match Center data, Excel sheets, or even photos of whiteboards." |
Functional gap (high-leverage for low-tech organizers) |
Tools / surfaces (new/updated)
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| ExpressEntry Registration (1-tap / short-form registration) | ✅ marketed as one of "state-of-the-art tools" | ⚠️ Not in plan | raw-html/67-rating-wppr.text.txt "ExpressEntry Registration" listed under "State-of-the-Art Engine" |
Functional gap (player UX) |
| Referee App & Scoring (dedicated referee mobile app) | ✅ marketed as one of "state-of-the-art tools" | ⚠️ Not in plan | raw-html/67-rating-wppr.text.txt "Referee App & Scoring" |
Functional gap (operator product) |
| Automated Brackets (auto-generation) | ✅ marketed | 🔧 v0.5 W48 generate-buttons does this | raw-html/67-rating-wppr.text.txt; DECISIONS §v0.5 W48 |
Parity |
| Global Directory (search any player, verify credibility) | ✅ shipped | 🔧 v0.4 W29 has organizer public profile; player directory not in plan | raw-html/67-rating-wppr.text.txt; DECISIONS §v0.4 W29 |
Functional gap |
| Team Level Formats (combined-rating events, e.g., 5.0 + 4.0 = 9.0 team rating gate) | ✅ shipped, marketed explicitly | ⚠️ Not in plan; requires rating algorithm | raw-html/67-rating-wppr.text.txt "A 5.0 player and a 4.0 player combine for a 9.0 team rating" |
Strategic divergence (rating-dependent) |
Stack / infrastructure (post-walk confirmations)
| Capability | Wecourts | OpenRally | Evidence | Gap class |
|---|---|---|---|---|
| Supabase backend | ✅ confirmed — project URL uptheqepffmurgysqzal.supabase.co exposed in HTML preconnect |
✅ OpenRally is also Supabase | _buildManifest.js fetch revealed in this session |
Parity (stack confirmed) |
| Asset CDN | DigitalOcean Spaces (BLR1 — Bangalore region) | ⚠️ OpenRally plan implies Supabase Storage (RLS-gated bucket) | _buildManifest.js revealed wecourts.blr1.cdn.digitaloceanspaces.com |
Stack divergence (OpenRally likely cheaper at scale via Supabase Storage) |
| Cloudflare CDN edge | ✅ confirmed (CF-Ray BKK = Bangkok PoP serves global) | ✅ OpenRally plans Vercel (edge) — same general capability | network header captures | Parity-ish |
| Next.js Pages Router (not App Router) | ✅ — /pages/_app-*.js confirmed |
✅ OpenRally is Next.js 16 App Router | network capture | OpenRally ahead (App Router is the modern path) |
| Featurebase SSO via JWT | ✅ shipped (HS256 JWT, src: "sso", iss: "production:backend") |
⚠️ OpenRally has no public-feedback tool yet | cookie decode this session | Functional gap |
| Lexend / Lexend Exa font family | ✅ Lexend (400/500/600) + Lexend Exa (500/600/700) loaded from Google Fonts | ✅ OpenRally uses Inter (per design system) | _buildManifest.js head extract |
Design choice |
| PWA configured (manifest, apple-touch-icon, 32/180/192 sizes) | ✅ | 🔧 OpenRally v0.x doesn't explicitly call out PWA install path | _buildManifest.js head extract |
Functional gap (small) |
Stats / claims updated (vs the original matrix)
- "25K+ players" → "20,000+ verified players" on redesigned WPPR page — they corrected DOWN, suggesting the 25K was loose
- "3,500+ tournaments" → "5,000+ tournaments" on redesigned WPPR page — UP by ~40% (or different counting method)
- NEW metric: "250K+ matches played" — match-level corpus size, important for the data moat narrative
- "8+ countries" remains consistent
- "450+ clubs" (footer) and "200+ clubs" (
/newmarketing) remain inconsistent — they haven't reconciled
Updated gap-class summary
New functional gaps to add to v0.6-v0.8 consideration:
- Onboarding state machine with intermediate states (verify-email → onboarding choose-path → org-create → pending-review) — even self-serve OpenRally should have explicit states
- Two-persona organizer split (Club vs Company)
- Dedupe-search-before-create pattern on org/club creation
- Dual-mode logo upload (file OR URL)
- Full ISO-3166 country support
- Country-coupled City dropdown
- Role-split signup/login URLs
New strategic gaps requiring Nestor decision:
- Manual approval gate yes/no — wecourts has one; do we?
- Federation partnership strategy — wecourts has 2 federations on board (Egypt, Jordan); should we line up TLPA / national federation for Thailand?
- Booking-system integration as a play — wecourts has PadelOS + Epic Padel live; should OpenRally integrate with PlayTomic / Booking Bug / similar SEA-native booking systems?
- Smart-court / AI-camera ingestion — wecourts claims this; OpenRally v0.x is silent
- Whiteboard-photo + Excel ingestion ("Zero Tech Barrier") — wecourts's funnel-broadening play; OpenRally could match via Claude Vision
Wecourts pattern that OpenRally is now ahead on:
- App Router (Next.js 16) vs wecourts's Pages Router — OpenRally is on the modern stack, can use Server Components, Streaming, partial prerendering. Real (small) eng advantage.