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