My Motoclub
Event access control, in the hands of the people on the gate.
iOS · Android

Live event list 
Registration form 
Entry pass 
Rider applications 
Guest list 
Access roles 
Digital licence
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.
Product definition, interface design, application architecture, the Flutter app for both stores, the Supabase backend and data model, the access, licence and scrutineering rules, thermal printing, notifications — and continuous releases since.
- App Store
- Google Play
Both listings are being published under the app’s current name. The app itself is built and running.
- iOS
- Android
- Application
- Flutter
- Dart
- BLoC
- Clean Architecture
- Backend
- Supabase
- PostgreSQL
- Row Level Security
- Postgres RPC
- Infrastructure
- Firebase Cloud Messaging
- Supabase Storage
- Product strategy
- UI/UX design
- Technical architecture
- Mobile development
- Backend development
- Database design
- Integrations
- Testing & QA
- Deployment
- Maintenance
What it does
Each part was built for a real job on the day, not for a feature list. The product’s own site walks through them in full.
Events
Created with their date, capacity, classes and fees, then counting admissions up live as people come through the gate.
Entries & classes
Riders enter themselves — name, age, ID number, blood group, emergency contact — under auto or moto, in proto, promosport, maxisport or supersport. A co-pilot can be added later from the event page.
Fees & deadlines
The participation fee and transponder price for the chosen class are shown before the entry is made, and it only completes once the rider accepts them. Each event carries a closing date, after which the form shuts itself.
Signed QR passes
Every pass carries a cryptographically signed code, validated server-side and spendable once. A screenshot does not walk a second person in.
Gate scanning
The phone camera reads the code and answers accept or reject in one motion, with the reason shown. Built for a queue at the gate, not a desk.
Wristband printing
A Bluetooth or USB thermal printer pairs to the phone and prints an access wristband on the spot, as each rider or guest is admitted.
Vehicle scrutineering
Suspension, steering, wheels, tyres, battery and driving licence worked through beside the car, with make, model and declared horsepower recorded alongside. The scrutineer and the participant both sign on the device, then the car is assigned its group.
Digital licences
Issued, renewed, revoked and reinstated in the app, with the full history, the validity dates and the race-number checks.
Guest registration
Guests register themselves, with companions attached to the participant who brought them, numbers pulled straight from contacts, and every head counted against event capacity.
Access roles
Nine distinct permissions — events, licences, users, scanning, pricing, manual verification, car verification, group assignment and notifications — granted person by person.
Push notifications
An approved licence, a new invitation, a changed event: riders and staff are told what moved instead of being chased.
Exports & records
Guest lists, licences and member directories exported to CSV or PDF and shared straight from the phone.
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.
- 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
- 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
- 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.
- 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.
- 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
- 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.
- 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.
- 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
- 26 tracked migrations covering the licence lifecycle, revocation history, renewals, entry deadlines, fee acceptance, wristband prints, manual admission and realtime
- Device capabilities
- Camera scanning, QR generation, brightness control, screenshot protection, Bluetooth and USB thermal printing, PDF generation, contact import
- Notifications
- Firebase Cloud Messaging for push, with local notifications on device
- Release
- One Flutter codebase for 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.
