Product · Two worlds
Staff sees Offsides. Members see the club.
One backend. Two surfaces. Staff is co-branded Offsides × Club. The member app wears the club's kit — Offsides only as a powered-by line in the club's text colour.
Staff admin
Web. The full board. Owners, managers, front desk.
- Nº 01 Today board and walk-ins
- Nº 02 Calendar and recurring blocks
- Nº 03 Members and tiers
- Nº 04 Pricing rules
- Nº 05 Floor layout
- Nº 06 QR codes
- Nº 07 Classes and events
- Nº 08 Reports and export
- Nº 09 Stripe Connect
Member app
One Flutter binary. Theme and labels load at runtime.
- Nº 01 Join by club code
- Nº 02 Waiver gate
- Nº 03 Home and next booking
- Nº 04 Map + grid book
- Nº 05 Classes and events
- Nº 06 QR check-in
- Nº 07 Profile and portal
The engine
Rules live on the server

Bookings
Tier windows, peak pricing, cancellation policy. Price frozen when the row is written. Race-proof conflicts.

Sessions
Classes, events, clinic credits, guest passes. Feature flags hide what a club does not run.

Check-in
QR or manual. Tolerance window. Front desk can still walk someone in.

Money
Stripe Connect Express. Club is merchant of record. Application fee only — see pricing.
Whitelabel
A new vertical is data
Onboarding is a clubs row (labels + flags), resources and tiers, optional floor layout, and a connected Stripe account. No rename. No migration. No redeploy.
User-facing words come from the club. The schema says resource, session, tier.
Proof
Two kits, one codebase
A court club with a floor plan. A gym with mats, classes, and the map switched off. Same app. Different labels.
Want the sheet
Request a pilot
I'm in