Client project · Ref. CW-01

MotoGate

Event access control, in the hands of the people on the gate.

Platforms

iOS · Android

  • The MotoGate event list with one round live: 1,248 of 1,600 admitted on a 78 percent capacity bar, and the next rounds below it.
    Live event list
  • The car registration form for an autocross round, filled in for a turbocharged four-wheel-drive entry with the transponder and the entry fee accepted.
    Registration form
  • A rider's entry pass for the live round — the QR the gate scans, with its ticket code, date and holder.
    Entry pass
  • Rider applications with an expired-licence warning, entry fee and accept or reject actions.
    Rider applications
  • The guest list, showing invite codes, companion counts and colour-coded access roles.
    Guest list
  • Access roles configuration, with eleven colour-coded roles and enable switches.
    Access roles
  • A digital racing licence card showing the licence number, blood group and race number.
    Digital licence
Screens from the shipped Android build, running on a demo database of fictional riders and events.

Access at a motorsport event is not one list. Riders with valid licences, their companions, officials, pit crew and spectators are each allowed into different areas — verified by someone at a gate with a phone and no time to argue.

StyloTech’s role

Product definition, interface design, application architecture, the Flutter app for both stores, the Supabase backend and data model, the access and licence rules, notifications — and continuous releases since.

Platforms
  • iOS
  • Android
Built with
Application
  • Flutter
  • Dart
  • BLoC
  • Clean Architecture
Backend
  • Supabase
  • PostgreSQL
  • Row Level Security
  • Postgres RPC
Infrastructure
  • Firebase Cloud Messaging
  • Supabase Storage
What StyloTech delivered
  • Product strategy
  • UI/UX design
  • Technical architecture
  • Mobile development
  • Backend development
  • Database design
  • Integrations
  • Testing & QA
  • Deployment
  • Maintenance

What it does

01

Events

Capacity, pricing, and admissions counting up live as people come through.

02

QR verification

One scan confirms identity, entitlement and area. The pass brightens the screen so it reads in daylight.

03

Digital licences

Issued, renewed, revoked and reinstated in the app, with the full history and race-number checks.

04

Guest registration

Guests register themselves, with companions attached to the participant who brought them.

05

Access roles

Nine distinct permissions, granted person by person.

06

Participation & results

Entries, participation fees and vehicle verification, alongside championships and results.

One entry, traced

A rider walks up to the gate with a pass on their phone. This is everything that happens between the camera seeing it and the barrier opening — or not.

Read from scan_ticket_page.dart, participation_repository.dart and the Supabase function list. Every name below appears in the source exactly as written.

  1. 01

    The pass sits on the rider’s phone

    The code carries three fields and nothing else: which event, which ticket, whose phone number. The screen goes to full brightness so it still scans in direct sun, and the operating system is told to refuse screenshots of it.

    • qr_flutter
    • screen_protector
    • FLAG_SECURE
  2. 02

    A marshal scans it

    The camera reads the code and the phone buzzes the moment it has something — before any verdict. That first buzz tells the marshal to hold still rather than keep re-aiming, which is most of what makes a gate queue move.

    • mobile_scanner
  3. 03

    Two checks before the network is touched

    A code missing any of its three fields is refused on the spot, and so is a perfectly valid pass for a different event. Neither needs a round trip, so the common mistakes are answered instantly.

    • eventId
    • ticketCode
    • phoneNumber
    What it says when it refuses

    “Invalid ticket”, or “Ticket does not belong to this event”. Both are refusals, and both are written to the log.

  4. 04

    The event is read back from the server

    The decision is never made from whatever the scanning phone happens to be holding. The event is fetched with its invites, their companions, its teams, their members and its scan log — all under row-level security, so a marshal’s own permissions decide what comes back.

    • events
    • event_invites
    • event_invite_companions
    • event_teams
    • event_team_members
    • event_scan_logs
    What it says when it refuses

    After twelve seconds, “Verification timeout”. It fails closed: a slow network never becomes an open gate.

  5. 05

    The holder is resolved

    The ticket code and phone number are matched against the invites, the companions attached to them, and the team members. If that number belongs to a registered account, the name on file replaces the one typed onto the invite — so the marshal reads the person’s real name.

    • profiles
  6. 06

    The ticket’s own history is checked

    Every previous scan of this code is examined. One earlier success, or one earlier supervisor override, and the pass is spent. This is what stops a screenshot of a valid QR walking three friends in.

    • event_scan_logs
    What it says when it refuses

    “Ticket already used” — shown with who scanned it and when, so the marshal can settle the argument on the spot.

  7. 07

    The licence rule is asked of the database

    For a competitor, the licence has to be valid on the day of the event. That rule is a stored procedure, not app code: it cannot be argued with at the gate, and it cannot be bypassed by an old build still on someone’s phone.

    • participation_entry_check
    What it says when it refuses

    “Licence not valid on the event date”, with the reason the database gave.

  8. 08

    The verdict, and the record

    Granted or denied, with any companions the holder is entitled to bring listed underneath. A light haptic for allow, a heavy one for deny, so it can be felt without looking. Then every attempt is written down — refusals included, and a supervisor override recorded as its own status rather than quietly as a success.

    • record_scan_log
    • success
    • failed
    • overriden

Engineering detail

Taken from the project source, not from marketing material.

Architecture
Clean Architecture with BLoC state management, feature-first structure, repository pattern
Backend
Supabase — PostgreSQL with row-level security policies and server-side RPCs for licence and admission rules
Data model
21 tracked migrations covering licence lifecycle, revocation history, renewals, manual admission and realtime
Device capabilities
Camera scanning, QR generation, brightness control, screenshot protection, PDF generation, contact import
Notifications
Firebase Cloud Messaging for push, with local notifications on device
Release
Shipping on iOS and Android; version 1.5.1, build 59 at the time of writing

Event access control, in the hands of the people on the gate.

MotoGate — Client project — StyloTech