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.