E-Ticketing Platform

A full-stack travel e-ticket platform built from scratch, multi-step declaration form, Stripe payment processing, auto-generated PDF delivery by email, and a searchable admin panel. Built with Laravel, Livewire, and FilamentPHP.

The brief

This project started from a job listing on Upwork that caught my attention, a client needed a travel e-ticket platform similar to the Dominican Republic e-ticket system. Users fill in a multi-step form with their travel details, pay a fee, and receive a completed PDF e-ticket by email. I found the problem interesting and built the full platform myself as a portfolio piece.

The core challenge was stitching together several independent concerns, a user-friendly multi-step form, server-side payment verification, deterministic PDF generation from user input, and reliable email delivery, into a single seamless flow where failure at any step is handled gracefully and the user always knows where they stand.

Project details

Industry Travel/Tourism
Timeline 6 weeks
Type Full Stack
Stack
FilamentPHP Laravel

Need something similar?

Let's discuss your project

What was built

The platform serves three distinct user types, public visitors, registered travellers, and admin staff, each with a separate interface and a clearly defined set of actions.
Landing page
  • Public-facing page built to GOV.UK design standards
  • Explains the service clearly and lists what the traveller needs before starting
  • SEO-optimised structure with clean meta, heading hierarchy, and fast load times
  • Single call-to-action linking through to registration
Multi-step submission wizard (4 steps)
  • Step 1: General Information: address, country of residence, travel direction (arrival / departure)
  • Step 2: Personal & Travel Information: full name, date of birth, passport number, airline, and flight details
  • Step 3: Customs Declaration: goods being carried, animals, and currency amounts
  • Step 4: Payment: Stripe card payment inline on the form, no redirect
Submission processing
  • Payment intent verified server-side before any record is created, the submission cannot exist without a confirmed payment
  • Unique reference number generated on confirmation (format: TKT-XXXXXXXX)
  • PDF e-ticket generated from the submitted data and attached to the confirmation email
  • Confirmation email sent to the traveller immediately after successful submission
User portal
  • Registered users can log back in and view all previous submissions
  • Each submission shows reference number, travel details, and current payment status
  • PDF download available for any completed submission
Admin panel
  • Full submissions table: reference number, passenger name, travel direction, airline, flight number, submission date, and payment status
  • Search and filter across all submitted records
  • Direct link to the Stripe receipt for each submission
  • Admins view submissions only, creation and editing are intentionally restricted to user-submitted forms

Screenshots

Screenshots of the live application.

Admin panel showing a table of submitted tickets with reference numbers, passenger names, travel direction badges, airline, flight number, flight date, and payment status
Admin panel: submitted tickets table with reference numbers, passenger details, and payment status
Step 2 of the ticket creation wizard showing personal details, contact information, and flight details fields including passport number, airline name, and flight date
Ticket wizard: Step 2: Personal & Travel Information with passport, contact, and flight detail fields
Step 1 of the ticket creation wizard showing address fields, country of residence, and travel type selection (arrival or departure)
Ticket wizard, Step 1: General Information with address fields and travel type selection
E-Ticketing Platform landing page showing the service overview, processing fee, and step-by-step instructions for completing a travel e-ticket
Landing page, service overview, $50 processing fee, and four-step instructions built to GOV.UK design standards

Technical notes

Payment-first record creation
The submission record is only written to the database after the Stripe PaymentIntent status is verified server-side as "succeeded". The form collects all data client-side across the four steps, but nothing is persisted until payment is confirmed. This prevents orphaned records from abandoned checkouts and means the admin panel only ever shows completed, paid submissions.
PDF generation
PDFs are generated using spatie/laravel-pdf with the DomPDF driver. Each e-ticket is rendered from a Blade view that receives the submission data as typed variables. The PDF is generated synchronously on submission — not queued — because the traveller expects to receive it immediately. The generated file is streamed as an email attachment and not stored on disk.
Multi-step form state with Livewire
The four-step wizard is a single Livewire component. Form state is held in the component's public properties for the lifetime of the request session. Each step has its own validation rules that run on "next" without validating the full form, so the user only sees errors relevant to the step they're on. Moving backwards preserves all previously entered data in component state.
Filament for both panels
Both the user portal and the admin panel are built on Filament v5, using separate panel configurations with different middleware, guard, and route prefix settings. The user panel exposes only the submission wizard and submission history. The admin panel uses a separate guard and is not accessible to registered users. Sharing the Filament base keeps the UI consistent without duplicating layout code.
SQLite for MVP simplicity
The database is SQLite — a deliberate choice for an MVP where deployment simplicity matters more than concurrent write performance. A single-file database eliminates the need to provision and configure a database server for early-stage validation. Migrating to MySQL or PostgreSQL later requires only a driver swap and data export, with no schema changes needed.

Have a similar project?

Get in touch with a brief description of what you need and I'll come back to you within 24 hours.