Skip to content
Rapcsány Krisztián
hu
← All projects Web application and API

Ticketing and community platform for clubs and events

This is the biggest system I have built so far: a ticketing platform for clubs and events. Catalogue, cart, payment, ticket issuing, invoicing, a mobile API and everything that goes around them. I have been building it since February 2025, and it keeps growing.

PHP 8.3 Laravel 12 MySQL Redis Queue workers WebSockets REST API Online payments Feature flags
The challenge
My role

I have designed and built it from the start.

Selling a ticket is only the first step. After that the buyer needs the ticket by email, an invoice, entry at the door, and ideally a reminder before the event. These are usually separate systems, and that is where data gets lost.

My goal was to make all of it one system. The website, the mobile app, the app used at the door, the admin and the point-of-sale systems all work from the same place, and when something breaks, there is one place to look.

The solution
01

Catalogue and SEO

Clubs, organisers, events, line-ups and search. The URLs are search-friendly, the sitemap is automatic, and the content is multilingual, with machine translation to help.

02

Cart and payment

Guest and signed-in carts (merged on login), coupons. With payment the revenue goes straight to the organiser, and the order is closed on the payment provider callback.

03

Tickets and invoices

PDF tickets by email, tickets can be passed on to someone else, invoicing is automatic through the provider each organiser uses, and failed invoices are retried.

04

Mobile API and push

A versioned API for the mobile app: sign-up, catalogue, cart, tickets, push notifications, deep links, and a jump from the app to web checkout.

05

Loyalty and VIP cards

Discount cards with their own landing pages, a loyalty wallet with balance and transactions, and lookups and charges tied to the external point-of-sale system.

06

Community layer

Friends, following, posts, 24-hour stories, real-time chat. Behind a feature flag, so it can be switched on gradually per user.

Screenshots
Home page

Search by time and place, quick access to your own QR codes, featured events.

Events

A calendar, venue, category and organiser filters, and events as cards with date and music styles.

Venue page

The venue presented with rating, music styles, age limit, opening hours and a gallery.

Event page

Description, dress code, age limit, the tickets and the venue in one place.

With brand and customer names and personal data removed (except the app store screenshots).

What makes it special

Many clients, one system

The website, the customer mobile app, the check-in app, the admin and an external point-of-sale system all use the same API and data model.

The money goes to the organiser

I built payments so that revenue goes straight to the organiser or the club. An order is closed by the payment callback. I cannot count on the buyer returning to the site, because they do not always do.

Gradual rollout

I put the community features (friends, posts, stories, chat) behind a feature flag. I can switch them on per user, and if something is wrong I do not have to roll back a whole release.

Challenges I ran into
01

VIP tickets vanished from the admin statistics

At one point I noticed the VIP ticket was missing from the per-event statistics in the admin. A guest checked in with a VIP card went in on a ticket type the admin did not know yet. Now the ticket type is synced automatically at the first VIP entry. I filled in the earlier gaps with two recovery commands.

02

A zero-forint order needs no invoice

At first the invoicing job threw an error for every on-site sale, because those have no billing address, and it also tried to invoice fully discounted orders. Now the amount actually paid decides, not the list price, and on-site sales take a separate path.

03

Anything slow or external goes on a queue

Invoicing, email, push and sync run on a queue, with retries, not inside the user's request. If an external provider does not answer, the purchase still goes through, and the invoice follows later.

Under the hood

Background jobs that lose nothing

Whatever is slow or depends on an external provider (invoicing, email, push, sync) runs on a queue, with retries on failure. If something was missed, I fill it in with recovery commands.

Connecting systems

Two-way sync with the admin interface, a separate media server, a door-check API and an external point-of-sale partner interface, all on one shared data model.

Emails that arrive

Email log and suppression list, delivery tracking, reminders for abandoned carts, push before the event, a rating request afterwards.

Operability

Health monitoring and alerts, scheduled maintenance, a documented API and feature flags, so new features can go live without risk.

Live code

Guarding against a wrong invoice

Before invoicing, it checks in order whether an invoice is needed at all. What counts is the amount actually paid, not the list price, so a fully discounted order never produces a pointless invoice.

CreateInvoiceJob.php
public function handle(): void
{
    $order = Order::with(['billingAddress', 'user', 'items'])->find($this->orderId);

    // On-site (POS) sales are invoiced through another flow and have no billing address.
    if (Str::startsWith($order?->order_number ?? '', 'POS-')) {
        return;
    }

    // What was actually paid is authoritative, not the list price of the items:
    // a fully discounted order has total_amount = 0 and must not be invoiced.
    if ((float) ($order?->total_amount ?? 0) <= 0) {
        Log::info('Invoice skipped: order total is zero', ['order_id' => $this->orderId]);
        return;
    }

    if (empty($order?->billingAddress)) {
        Log::error('Invoice skipped: billing address is empty', ['order_id' => $this->orderId]);
        return;
    }

    // ... build the invoice and hand it to the provider configured for this organiser
}
Result

A live system that has served hundreds of events and keeps growing. The mobile API, the loyalty programme, the community layer and the recommendation system were all added later, without having to take it down.

Would you build a ticketing or events system?

Tell me about the plan, and we will work out what it takes and what to build first.

More projects

Write to me →