Skip to content
Adil Farooq, home
Menu

Full-Stack App · Travel · client · 2026

FlyLoveHolidays

A live travel website for a UK holiday company: packages across 20 countries, quote requests and WhatsApp enquiries, plus a staff portal for packages, enquiries, bookings and finance.

Role
Design & full-stack development
Built with
Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · Prisma · PostgreSQL (Neon) · Zod · Resend · React-PDF

Screens

4 screenshots · 1920 × 1080

Overview

FlyLoveHolidays is a UK holiday company selling tailored package holidays. Visitors browse packages by country, city and holiday type, see the hotel, flights and inclusions for each one, and ask for a quote by form, phone or WhatsApp. Staff sign in to a separate portal to manage the catalogue, follow up enquiries and record bookings, payments and invoices.

Objective

Present the company’s packages in a browsable catalogue that leads to enquiries, and give staff one place to manage packages, enquiries and bookings.

The solution

A Next.js 16 site that reads its catalogue from a Neon PostgreSQL database through Prisma, with typed static data as a fallback, and a staff portal with role-based permissions behind its own login.

What I built

  • Package catalogue

    Packages organised by country, city and holiday type. Each package page lists the hotel, room and board, flight details and what is included, with Product and breadcrumb structured data.

  • Enquiries by form or WhatsApp

    Quote forms are validated with Zod, normalise phone numbers to international format, and use a honeypot field, a minimum-time check and per-IP rate limiting against spam. Each enquiry is saved to the database, with an optional email notification through Resend. WhatsApp buttons open a message pre-filled with the package details.

  • Enquiry pipeline (CRM)

    Staff move each enquiry through New, Contacted, Follow-up, Quoted, Booked, Lost or Closed, and every status change is written to the audit log.

  • Staff sign-in

    A separate staff login with Argon2-hashed passwords, a 30-minute account lockout after five failed attempts, per-IP login throttling and 8-hour database-backed sessions in an HttpOnly cookie.

  • Roles and audit log

    Five staff roles mapped to 40 permissions, checked in the admin API. Sign-ins, package changes, bookings, payments and expenses are written to an audit log.

  • Bookings, payments and invoices

    Staff record bookings with passengers, flights and hotels, track full payments or instalment plans, and generate PDF invoices. Payments are recorded by staff; the site does not take payments online.

  • Finance and marketing tools

    Expenses with categories and approval statuses, CSV export, and PDF receipts and reports, plus a canvas tool that turns package data into social posts in three sizes.

How it’s built

  • On 1 October 2026 the live homepage listed 120 packages across 20 destinations, with 16 holiday types. The catalogue is stored in PostgreSQL behind a 41-model Prisma schema.
  • Catalogue pages are cached and refreshed every five minutes, and saving or publishing a package in the portal refreshes the affected pages straight away. If the database cannot be reached, pages fall back to typed static data.
  • Content Security Policy, HSTS and frame-blocking headers on public pages; staff pages are sent with noindex and no-store headers.
  • Flight deals are entered by staff and searched from the database. There is no live airline fare feed.