Event check-in mobile app
The mobile check-in app that staff use at the door to validate tickets. QR scanning, entry, exit, on-site ticket sales and live statistics, on iOS and Android.
I designed and built it, from the first version to 2.0.
At the entrance every second counts. If the queue is slow, guests get impatient, and the organiser watches revenue slip away. The door staff need fast, clear feedback: green or red, done.
Before this there was a browser-based scanner. I replaced it with an app that is faster, and where everyone only sees what their job needs.
Camera ticket validation
It reads the QR code with the phone camera and shows the result in colour: the ticket is valid, already used, expired or unknown. VIP guests get a separate mark.
Fast check-in
An automatic mode you can switch on: if the ticket is valid, the scan admits the guest straight away, with no extra tap.
Check-out
There is a separate exit flow too, so you always see how many people are inside.
On-site ticket sales
With a cart and payment, so tickets can also be bought at the door.
Live statistics
Arrival chart in 10-minute buckets, the number of sold, checked-in and no-show tickets by ticket type, and a chronological list.
Roles and users
There are five roles: admin, validator, exit staff, gatehouse and viewer. Everyone sees only the screens their job needs, and users are managed from within the app.
Staff sign in with their own account, and the sign-in persists.
Only valid events are listed, so door staff cannot start on the wrong one.
The camera waits for a QR code. The event name is shown at the top and can be switched with one tap.
Ticket types at door and member price, with a quantity picker and a running total.
A QR code or email for every ticket, with payment and check-in in a single step.
With brand and customer names and personal data removed (except the app store screenshots).
One scan, done
There is a fast mode: for a valid ticket the scan itself admits the guest, with no extra tap.
Five roles
Admin, validator, exit staff, gatehouse and viewer. The gatehouse role, for example, only sees live statistics, and exit staff only see the exit screen.
It measures itself
For every guest it times the scan to the result and to the check-in. It summarises the last fifty on the phone and sends the rest to the server in batches. From those I can see how fast it is.
Weak signal, and nobody gets in twice
On a network error I retry the call once, but only if repeating it cannot do harm. Anything that only reads, or is idempotent on the server, may be retried. Anything that is not, I do not call a second time.
The first guest is the slowest
On the first scan, setting up the connection eats the time (name lookup, encryption). So the app warms up the connection in the background before the first guest arrives, at most once a minute.
The selected event got stuck
In version 1.1.1 I fixed a bug where the selected event stayed in place even when it was no longer selectable. Now the app checks at launch and every time it comes to the foreground, and if the event is no longer valid it sends you back to the event picker.
Tuned for speed
The connection is already set up before the first guest gets there. I measure the time from scan to result for every guest, so a slowdown shows up quickly.
Works on weak networks
On a network error, repeatable calls retry by themselves. Non-repeatable ones never do, so nobody can be admitted twice.
Security
The login sits in encrypted storage, and longer sessions are protected by biometric authentication. The app keeps checking that the selected event is still valid.
Operability
Automatic error reporting, fixes without waiting for a store update, and role-based access on the server too.
A retry that does no harm
On a weak signal the call is repeated once, but only when that is safe. Non-repeatable write calls deliberately have no automatic retry, so nobody can be admitted twice.
/** No response at all = network failure (offline, timeout). A 4xx/5xx reply is not. */
function isNetworkError(error: unknown): boolean {
return axios.isAxiosError(error) && !error.response;
}
/**
* Retries a call once on a network failure. ONLY use it for calls that are
* safe to repeat: reads, or writes that are idempotent on the server.
*/
async function withNetworkRetry<T>(call: () => Promise<T>, retries = 1): Promise<T> {
try {
return await call();
} catch (error) {
if (retries > 0 && isNetworkError(error)) {
await new Promise((resolve) => setTimeout(resolve, 700));
return withNetworkRetry(call, retries - 1);
}
throw error;
}
}
The app is a released, production-grade version (2.0) on both iOS and Android. Admission is down to a single scan, and organisers see arrivals in real time.
Do you need a mobile app or an entry-check solution?
I build mobile apps for iOS and Android, together with their backend.
More projects
Admin and analytics interface
Events, orders, marketing and traffic data in one place, with in-house analytics and reports, on the web and on a phone.
How it was built → Self-service platformWholesaler integration platform
Connects online stores to over 400 wholesalers, with automatic price, stock and order handling, no developer needed. Behind it, it processes up to millions of records per second, reshapes and saves them by rules with no room for error, keeping states and statistics too.
How it was built → Marketing automationStatistics, SEO and email campaigns
In-house web analytics, SEO monitoring and email campaigns that are measurable, protected, and do the routine work on their own.
How it was built →