Skip to content
Irvs EbajanIrvs
Back to ProjectsWeb Application

Travel Agency Flight Inquiry System

A single-page flight inquiry form with automated email notifications and reCAPTCHA protection for a Montreal-based travel agency

Overview

A Laravel 11 flight inquiry system built for Travel Agency, a Montreal-based travel agency. This is a lead generation tool — not a booking system. Customers fill out a single-page flight inquiry form with their travel details, which triggers automated email notifications to both the customer and agency staff. The system includes REST API access for programmatic inquiry management, secured by Laravel Sanctum.

Problem

The travel agency relied on manual processes for handling flight inquiries:

  • Customers had to call or email travel details, leading to miscommunication
  • No structured format for capturing flight preferences (origin, destination, dates)
  • Manual data entry was error-prone and time-consuming for staff
  • No audit trail or reference system for tracking inquiries
  • Spam and bot submissions clogged manual processes

Solution

A comprehensive flight inquiry platform with three main layers:

ComponentStackRole
Web FormBlade + Vite + Vanilla JSSingle-page inquiry form with airport autocomplete, country code selector, and AJAX submission
BackendLaravel 11 + PHP 8.2Inquiry processing, validation, reCAPTCHA verification, email dispatch (Brevo SMTP)
APILaravel + SanctumRESTful endpoints for programmatic inquiry creation, lookup by reference, and admin listing

Request Lifecycle

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  Submit  │───►│  Throttle│───►│ Validate │───►│  Process │───►│  JSON   │
│ Inquiry  │    │ 10/hr IP │    │+reCAPTCHA│    │ + Emails │    │ Response │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘

Key Features

  • Single-page flight inquiry form with real-time validation
  • Google reCAPTCHA v3 + honeypot field for bot/spam protection
  • Automated email notifications via Brevo SMTP (user confirmation + admin alert)
  • REST API with Laravel Sanctum authentication for inquiry management
  • Auto-generated reference numbers (BT-YYYYMMDD-NNNNNN format)
  • Encrypted PII at rest via Laravel encrypted casts (7 sensitive fields)
  • Airport autocomplete with static dataset and country code selector
  • Custom rate limiting middleware (10 submissions/hr per IP)
  • Docker multi-stage build with Nginx + PHP-FPM + Supervisor

Security Implementation

ConcernImplementation
PII at restLaravel encrypted casts on 7 sensitive fields (names, email, phone, IP, UA)
CSRF@csrf directive in form, Laravel automatic protection
XSSBlade auto-escaping
SQL injectionEloquent ORM with parameterized queries
Rate limitingCustom middleware: 10/hr per IP (web); Laravel throttle: 10/min (API store)
Spam/botreCAPTCHA v3 (score thresholds 0.3–0.5) + honeypot field

Deployment & CI/CD

  • Hosting: Render (Docker, free tier, Oregon) + PostgreSQL (bta-db)
  • Container: PHP 8.2-fpm-alpine + Nginx + Supervisor multi-stage Docker build
  • CI/CD: GitHub Actions — lint, tests, Docker buildx, Render deploy
  • Health check: /health.php endpoint for Render monitoring

Technology Stack

LayerTechnology
BackendLaravel 11 / PHP 8.2
DatabasePostgreSQL 16 / MySQL 8.0
FrontendBlade / Vite / Vanilla JS
SecurityreCAPTCHA v3 / Laravel Encrypted Casts / Sanctum
TestingPHPUnit / SQLite in-memory
ContainerDocker / Alpine / Nginx / PHP-FPM
CI/CDGitHub Actions / Render

Notable Design Decisions

  • Single table design — inquiries stored in one table with no relationships for simplicity and fast queries
  • Encrypted casts for all PII — leverages Laravel's built-in encryption (depends on APP_KEY), keeping sensitive data encrypted at rest
  • After-response email dispatch — emails sent after the HTTP response to avoid blocking the user
  • ThrottleInquiries middleware — custom rate limiter with configurable limit via INQUIRY_RATE_LIMIT env variable (default 10/hr)
  • reCAPTCHA v3 double validation — score threshold of 0.3 in form request (lenient) vs 0.5 in service (strict), with action name verification
  • Honeypot field — invisible website field that must remain empty, catching basic bots without user friction
  • Auto-generated reference numbers — collision-resistant BT-YYYYMMDD-NNNNNN format for easy customer lookup