Cookie Preferences
We use cookies to keep the site running and improve your experience.
Learn more in our privacy policy .
Home About Portfolio Blog Contact
9

Nestovia - A Luxury Stay Website for a Dubai Property Brand

Nestovia
Year

2024

Status

Archived

Tech Stack
Laravel Filament Livewire Tailwind CSS PHP Alpine.js Vite MySQL Turnstile

Gallery

Nestovia is a Laravel-based luxury stay website for a Dubai property brand. The public side presents featured homes, location-aware browsing, individual property pages, and direct enquiry flows. Under that sits an internal operations layer for managing listings, booking requests, reviews, content blocks, subscriber records, and core company information from one admin panel.

This is not an online travel marketplace with instant checkout, and it is not a brochure site. The codebase sits between those two shapes. Visitors browse curated properties, filter by location, guest count, and nightly price, then submit a structured booking request tied to a specific property and stay period. The admin team picks that up inside Filament, where each booking moves through a status flow from pending to confirmed, cancelled, or completed.


Core Capabilities

The site covers the full guest journey and gives the operations team one place to run the business:

  • A content-led homepage built around featured properties, editorial feature blocks, partner logos, and testimonials, plus an about page that continues the brand story with feature highlights and company values

  • A filterable properties index with URL-bound state for text search, location, guest capacity, and price range, which keeps the listing flow shareable and stateful without adding SPA complexity

  • Slug-based property detail pages with categorized gallery sections (living room, bedroom, kitchen, outdoor) powered by a dedicated media filter layer

  • A request-driven booking flow with Cloudflare Turnstile protection, automatic night calculation, and stored subtotal and total values against each booking record

  • Guest-submitted reviews that stay unpublished until the admin team approves them, so social proof stays curated rather than open

  • Two secondary lead paths: a contact form that queues an email notification to [email protected], and a newsletter form with token-based email verification and rate-limited resend behaviour

  • Bilingual English and Arabic content across properties, testimonials, amenities, media filter labels, and company information


Architecture

Server-rendered Laravel stack

The application runs on Laravel 12 with PHP 8.2 on a server-rendered stack: Blade for page composition, Livewire for interactive forms and filters, Alpine.js for lighter client-side behaviour, Tailwind CSS for the UI layer, and Vite for asset delivery. That stack fits the product. Most of the interaction is around forms, filtering, and media presentation, not a JavaScript-heavy application shell.

Domain model around properties and bookings

properties carry translated title and description fields, pricing in minor units, a publish state, and soft deletes. They belong to locations, attach to amenities through a pivot table, collect reviews through a one-to-many relation, and use a separate property_media_filters layer for categorized galleries.

bookings are first-class records with guest identity, stay dates, guest count, stored pricing, internal notes, and an explicit status enum. The booking entity owns its own lifecycle instead of being derived from another model.

Integrated content model

Features, testimonials, partners, values, company info, media filters, locations, amenities, reviews, and subscribers all live inside the Laravel codebase and are exposed through Filament resources. There is no separate CMS or second admin to keep in sync with the application.

Bilingual data and money handling

I built localization into the data layer using translatable models and Filament's translation tooling, with English and Arabic configured as the working locales. Property copy, testimonials, amenity names, media filter labels, and company information all support translated values. Money is stored in minor units through a dedicated money field, with formatting tuned to the UAE locale instead of being formatted at the view layer.


Admin Experience

Role-based access with Filament Shield

The admin panel is grouped around operations rather than generic CRUD screens. Access is role-based: the panel uses Filament Shield on top of Spatie's role and permission layer, so each Filament resource and action can be gated by role instead of giving every admin account the full surface.

Property management

Each property record exposes translated titles and descriptions, generated slugs, location assignment, pricing, occupancy details, featured toggles, publication status, amenities, a featured image, and repeatable gallery sections mapped to media filter categories. Listings can also be reordered manually through the table view.

Booking request queue

Admins review guest details, dates, guest count, pricing, and notes, then change status directly from the table with dedicated actions for confirm, cancel, and complete. Pending bookings surface through a navigation badge, which turns the dashboard into a lightweight operational inbox.

Review moderation

Reviews are moderated instead of being published blindly. The dashboard supports approve and reject actions per review, plus bulk moderation. Pending reviews are flagged with their own navigation badge.

Content and subscriber operations

Contact submissions are stored as records and surfaced inside the panel. Subscribers can be filtered by status and date range. Site-wide company information such as address, phones, emails, social links, and business hours is editable from the same panel, alongside the editorial content blocks that the homepage and about page render.


Performance

Cached homepage content

Public homepage content runs through cache-focused services for properties, features, testimonials, partners, values, and company information, with different cache durations depending on the content type. That keeps the editorial homepage cheap to render without locking the team into stale data on the pieces that need to refresh quickly.

Optimized media pipeline

Property media is converted to optimized WebP derivatives, thumbnail variants, and responsive image sets through Spatie Media Library. The visual side stays light without pushing media handling into a separate pipeline.

Queued background work

Operational actions that do not need to block the request are queued. Contact notifications and newsletter verification emails go through Laravel's queue system, and the application schedules queue:work --stop-when-empty every minute. On the listing side, properties are paginated rather than returned in one response, and the property detail page only loads approved reviews with a fixed limit.


My Role

  • Designed the Laravel application as one system covering the public website and the internal operations layer

  • Built the property data model, the categorized media gallery layer through property_media_filters, and the slug-based detail pages

  • Built the request-based booking flow with night calculation, stored subtotal and total pricing, and the four-state lifecycle (pending, confirmed, cancelled, completed)

  • Built the Filament admin panel with Filament Shield role-based access across every resource

  • Implemented bilingual data handling for properties, testimonials, amenities, media filter labels, and company information

  • Integrated Cloudflare Turnstile on the public booking, contact, and newsletter forms

  • Built the moderated review flow, the contact pipeline, and the token-verified newsletter with rate-limited resend behavior

  • Set up the cache layer, the queued mail and notification flows, and the scheduled queue worker

Chat on WhatsApp