Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Set Up an Event Ticketing System in FlutterFlow

Create an event ticketing system by building a Firestore-backed seat map Custom Widget with color-coded availability, connecting Stripe Checkout via a Cloud Function for payment, generating unique QR code tickets with qr_flutter, and scanning them at the door with mobile_scanner. A seat hold mechanism prevents double-booking during checkout.

What you'll learn

  • How to model events, ticket types, and individual tickets in Firestore
  • How to build a venue seat map Custom Widget with color-coded availability
  • How to implement a seat hold timer to prevent double-booking during checkout
  • How to process ticket payments through Stripe Checkout via Cloud Function
  • How to generate QR code tickets and scan them for check-in
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read40-55 minFlutterFlow Free+ (Cloud Functions and Stripe require Firebase Blaze plan)March 2026RapidDev Engineering Team
TL;DR

Create an event ticketing system by building a Firestore-backed seat map Custom Widget with color-coded availability, connecting Stripe Checkout via a Cloud Function for payment, generating unique QR code tickets with qr_flutter, and scanning them at the door with mobile_scanner. A seat hold mechanism prevents double-booking during checkout.

Building a Full Event Ticketing Flow with Seat Selection and QR Check-In

Event ticketing requires coordinating seat inventory, payment processing, ticket generation, and check-in validation. This tutorial walks through each piece using FlutterFlow's visual builder, Custom Widgets for the seat map and QR codes, Cloud Functions for payment and ticket generation, and mobile_scanner for staff check-in.

Prerequisites

  • A FlutterFlow project with Firestore and Firebase Authentication configured
  • Firebase Blaze plan for Cloud Functions deployment
  • A Stripe account with API keys stored in Cloud Function environment config
  • Basic understanding of Firestore collections and document structure

Step-by-step guide

1

Create the Firestore data model for events, ticket types, and tickets

Create an events collection with fields: title (String), date (Timestamp), venue (String), description (String), imageUrl (String), and a ticketTypes array of maps, each containing name (String like General Admission or VIP), price (Double), totalSeats (Int), availableSeats (Int). Create a tickets collection with fields: eventId (Reference), userId (Reference), ticketType (String), seatNumber (String like A12), qrCodeData (String, unique UUID), status (String enum: held/purchased/used/cancelled), heldUntil (Timestamp, null after purchase). Add a Firestore composite index on tickets for eventId + status to support seat availability queries.

Expected result: Firestore has events and tickets collections with the proper schema, and seat availability can be queried efficiently by event and status.

2

Build the venue seat map Custom Widget with color-coded seats

Create a Custom Widget named VenueSeatMap with parameters: eventId (String), rows (Int), seatsPerRow (Int), and an Action Parameter callback onSeatsSelected that returns the selected seat list. Inside the widget, query all tickets for the event. Build a GridView where each cell is a GestureDetector Container representing a seat. Color code: green for available, red for sold (status purchased or used), orange for held (status held and heldUntil is in the future), blue for user-selected. Tapping a green seat adds it to a local selectedSeats list and turns it blue. Tapping a blue seat deselects it. Display a legend Row at the top explaining the colors. Pass the selected seats list back via the callback when the user taps a Confirm Selection button below the grid.

Expected result: The seat map renders the venue layout with real-time color coding, and users can select multiple available seats that get passed to the parent page.

3

Implement a 10-minute seat hold to prevent double-booking during checkout

When the user confirms seat selection and taps Proceed to Checkout, run a Cloud Function holdSeats(eventId, seatNumbers, userId). The function uses a Firestore batch write: for each seat, check if a ticket doc already exists with status held or purchased. If not, create a ticket doc with status held, heldUntil set to now + 10 minutes, and the userId. If any seat is already taken, abort the entire batch and return an error. On success, navigate to the checkout page. A scheduled Cloud Function runs every 5 minutes to find tickets where status is held and heldUntil is in the past, then deletes them to release expired holds.

Expected result: Selected seats are temporarily reserved for 10 minutes during checkout, and expired holds are automatically released.

4

Process payment through Stripe Checkout and generate QR tickets

On the checkout page, show the selected seats, ticket type, and total price. On Pay Now button tap, call a Cloud Function createTicketCheckout(eventId, ticketDocIds, totalAmount). The function creates a Stripe Checkout Session with the line items and a success_url pointing back to your app. Return the Checkout URL and open it in a WebView or browser. On Stripe webhook checkout.session.completed, a separate Cloud Function updates each held ticket to status purchased, generates a unique UUID for qrCodeData, decrements the event's availableSeats, and sends a confirmation email with ticket details.

Expected result: Payment completes through Stripe, ticket statuses update to purchased, each ticket gets a unique QR code identifier, and the user receives confirmation.

5

Display tickets with QR codes and build the staff check-in scanner

Create a My Tickets page querying tickets where userId equals current user and status is purchased. Display each ticket in a Card with event name, date, seat number, and a QR code rendered by a Custom Widget using qr_flutter: QrImageView(data: ticket.qrCodeData, size: 200). For staff check-in, create a separate Check-In page with a Custom Widget using mobile_scanner. When a QR is scanned, call a Cloud Function validateTicket(qrCodeData). The function finds the ticket by qrCodeData, checks status is purchased (not already used), updates status to used, and returns the ticket details. Display a green checkmark with seat info on valid scan, or a red X for invalid or already-used tickets.

Expected result: Attendees see their tickets with scannable QR codes, and staff can scan tickets at the venue entrance with instant validation feedback.

Complete working example

FlutterFlow Event Ticketing System Setup
1FIRESTORE DATA MODEL:
2 events/{eventId}
3 title: String
4 date: Timestamp
5 venue: String
6 description: String
7 imageUrl: String
8 ticketTypes: Array of Maps
9 [{ name: 'General', price: 25.00, totalSeats: 200, availableSeats: 147 },
10 { name: 'VIP', price: 75.00, totalSeats: 50, availableSeats: 32 }]
11
12 tickets/{ticketId}
13 eventId: Reference (events)
14 userId: Reference (users)
15 ticketType: String
16 seatNumber: String (e.g., 'A12')
17 qrCodeData: String (UUID)
18 status: String (held | purchased | used | cancelled)
19 heldUntil: Timestamp (null after purchase)
20 purchasedAt: Timestamp
21
22PAGE: EventDetailPage
23 Backend Query: single event doc
24 Column
25 Image (event imageUrl)
26 Text (title, titleLarge)
27 Row: Icon calendar + Text (formatted date) | Icon location + Text (venue)
28 Text (description, bodyMedium)
29 VenueSeatMap Custom Widget
30 params: eventId, rows: 10, seatsPerRow: 20
31 callback: onSeatsSelected update Page State selectedSeats
32 Button "Proceed to Checkout" (enabled when selectedSeats not empty)
33 On Tap Cloud Function holdSeats Navigate CheckoutPage
34
35PAGE: CheckoutPage
36 ListView (selected seats with ticket type + price per seat)
37 Divider
38 Row: Text "Total" + Text (formatted total)
39 Button "Pay Now"
40 On Tap Cloud Function createTicketCheckout Open Stripe URL
41
42PAGE: MyTicketsPage
43 Backend Query: tickets where userId == currentUser, status == purchased
44 ListView
45 Card (padding 16)
46 Text (event title, titleMedium)
47 Row: Text (date) + Text (seat number)
48 Center: QrImageView Custom Widget (data: qrCodeData, size: 200)
49
50PAGE: StaffCheckInPage
51 Custom Widget: mobile_scanner
52 onScan Cloud Function validateTicket(qrCodeData)
53 Success green Container with checkmark + ticket details
54 Failure red Container with X + error message
55
56SEAT MAP LEGEND:
57 Row (mainAxisAlignment: spaceEvenly)
58 Container(green, 16x16) + Text "Available"
59 Container(red, 16x16) + Text "Sold"
60 Container(orange, 16x16) + Text "Held"
61 Container(blue, 16x16) + Text "Selected"

Common mistakes

Why it's a problem: Not locking selected seats during checkout with a hold timer

How to avoid: Implement a 10-minute seat hold: mark seats as held with an expiry timestamp when checkout begins. A scheduled Cloud Function releases expired holds automatically.

Why it's a problem: Generating QR codes with predictable sequential data instead of UUIDs

How to avoid: Generate a random UUID (v4) for each ticket's qrCodeData. The Cloud Function validates the exact UUID against Firestore on scan.

Why it's a problem: Decrementing availableSeats on hold instead of on purchase

How to avoid: Only decrement availableSeats in the Stripe webhook handler after confirmed payment. Release holds restore availability automatically.

Best practices

  • Use Firestore batch writes for seat holds to ensure all-or-nothing reservation of multiple seats
  • Store the Stripe Checkout Session ID on ticket docs to reconcile payments with tickets
  • Run a scheduled Cloud Function every 5 minutes to clean up expired seat holds
  • Add Firestore Security Rules preventing users from modifying ticket status directly — only Cloud Functions should change status
  • Include event name, date, and seat number in the QR code display so attendees can verify details without scanning
  • Cache the seat map query result in Page State and refresh on navigation return to avoid excessive Firestore reads
  • Show a countdown timer on the checkout page so users know how long their seats are held

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I need to build an event ticketing system in FlutterFlow with a visual seat map, Stripe payment, QR ticket generation, and a staff check-in scanner. Show me the Firestore data model, seat hold logic, and the full page flow.

FlutterFlow Prompt

Create an event detail page with event image, title, date, venue, and description. Below the description, add a grid representing a venue seating chart where each cell is a tappable seat. Add a Proceed to Checkout button at the bottom.

Frequently asked questions

How do I prevent the same seat from being sold to two people?

Use a Cloud Function with Firestore batch writes to create held ticket documents atomically. The batch checks if a ticket already exists for each seat before writing. If any seat is taken, the entire batch aborts. A separate scheduled function releases expired holds.

Can I support general admission tickets without assigned seats?

Yes. Skip the seat map widget entirely and use a quantity selector instead. Each ticket gets a unique QR code but no seatNumber. Decrement the availableSeats count atomically in the Cloud Function on purchase.

How do I handle refunds and ticket cancellations?

Create a Cloud Function that calls Stripe's refund API, updates the ticket status to cancelled, and increments the event's availableSeats. Trigger it from an admin panel or a user-facing Cancel Ticket button.

Can I email the QR code ticket to the attendee?

Yes. In the Stripe webhook Cloud Function, after generating the QR code data, use a mail service like SendGrid to send an email containing the ticket details and a QR code image generated server-side using a Node.js QR library.

What if a ticket QR code is shared or screenshotted?

The validateTicket Cloud Function marks the ticket as used on first scan. Any subsequent scan of the same QR code returns an already-used error. This prevents duplicate entry from shared screenshots.

What if I need help building a complex ticketing system with multiple venues?

RapidDev has built event ticketing platforms with dynamic venue maps, multi-tier pricing, waitlists, and real-time capacity management across 600+ FlutterFlow projects. They can handle the full build.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.