Back to Case Files
BNR-CF-01Hotel · Scroll Story·Hospitality·Sousse, Tunisia·2026

Dar Azur Hôtel & Spa

A Next.js 16 showcase site for a five-star boutique hotel on the Boujaafar corniche in Sousse, built as a GSAP scroll narrative with a four-step booking wizard and five-language support including Arabic RTL.

Visit live site
Dar Azur Hôtel & Spa — Hotel · Scroll Story homepage built by BreakNRoot

07

Routes

05

Locales

05

Room pages

Dar Azur Hôtel & Spa is a five-star boutique property on the Boujaafar corniche in Sousse, Tunisia, presenting thirty-two rooms and suites, a spa, a private beach, a rooftop lounge and the Le Safran restaurant. The brief was a marketing site that reads like an editorial piece rather than a booking-engine landing page: the visitor should move through the house the way a guest would, chapter by chapter, before ever reaching a form.

The home page is built as a numbered scroll story. A full-bleed hero holds a Ken Burns photograph under a GSAP scrub parallax with a SplitText character reveal on the wordmark, then five chapters alternate with full-width parallax breathers. Chapter two pins the viewport and drives the room catalogue sideways as a horizontal track, with each photograph counter-sliding inside its own frame through a ScrollTrigger containerAnimation. Chapter five pins again and cross-fades a three-part day-in-the-life sequence against a synchronised timeline gutter. Lenis drives the whole page and is wired into the GSAP ticker so ScrollTrigger and the smooth-scroll loop share one frame.

The interaction layer is an in-house component kit written in the React-Bits idiom rather than pulled from a dependency: scroll-scrubbed clip-path mask reveals in three shapes, line-by-line split-text headings, a scroll-triggered count-up, a cursor-magnetic button wrapper, a pointer-tracked spotlight card and a fade-on-enter wrapper. Every one of them checks prefers-reduced-motion and returns early, and the two pinned chapters fall back to plain vertical stacks through gsap.matchMedia. The content itself is French-first and fully localised into English, Arabic, Russian and German through a client-side dictionary provider that stores the choice locally and flips the document direction for Arabic.

// challenge

The Challenge

A five-star property competes on atmosphere, and atmosphere is the one thing a conventional hotel template flattens. The site had to sustain a cinematic, scroll-driven sense of place across an entire home page while still doing the practical work of a hotel site: presenting five distinct room types with real surfaces, capacities and TND rates, giving a guest a booking path that quotes a total before they commit, and serving an international clientele that arrives in French, English, Arabic, Russian and German. Heavy pinning and scrubbing also had to degrade honestly, so that a visitor on a phone or with reduced-motion enabled gets a readable document rather than a broken one.

// solution

What We Built

The site is a Next.js 16 App Router build on React 19 and Tailwind CSS v4, with GSAP ScrollTrigger and SplitText for motion and Lenis for smooth scroll, deployed on Vercel. Room pages are statically generated from a typed content model via generateStaticParams, each carrying its own Schema.org HotelRoom JSON-LD alongside a Hotel graph on the home page and a Restaurant graph on the Le Safran page. Reservations run through a four-step wizard that computes nights, room subtotal and the Tunisian city tax at 12 TND per adult per night capped at seven nights, validates each step client-side and posts to a Next.js route handler that re-validates server-side and returns a booking reference. A second route handler backs the contact form. All five locales are served from a single client dictionary with an RTL switch for Arabic, and imagery is served locally from the repository with credits and licences documented in the tree.

// outcome

The Outcome

What shipped is a live, statically generated seven-route site with per-room detail pages, a working four-step reservation flow with server-validated submissions, a contact channel, structured data across the hotel, room and restaurant entities, and a generated sitemap and robots policy. The scroll story runs at full fidelity on desktop and collapses cleanly to a linear document on mobile and under reduced-motion, and the whole editorial content set is addressable in five languages from a single dictionary, so the hotel can extend copy or add a locale without touching the motion layer. The room, service and menu data all live in typed content files, which means rates, rituals and dishes are editable in one place and flow through to the pricing engine, the JSON-LD and the sitemap at once.

Engineering log
[01]

Pinned horizontal room chapter

The room catalogue chapter pins the viewport and translates a horizontal track under scroll, with each photograph counter-sliding inside its frame through a ScrollTrigger containerAnimation. Above 1024px only, and only when reduced motion is off; below that it becomes a snap-scroll carousel. src/components/home/RoomsChapter.tsx

[02]

Pinned day-in-the-life sequence

A second pinned stage cross-fades three moments (morning beach, afternoon spa, evening pool) over a 220 percent scroll distance while a text gutter and its rule markers animate in step. Falls back to a stacked list of figures on mobile. src/components/home/JourneeSequence.tsx

[03]

Four-step booking wizard with live TND totals

Dates, guests, room selection, guest details and confirmation, with per-step validation, room capacity checks and a running total that adds the city tax at 12 TND per adult per night capped at seven nights. Submits to a route handler that re-validates and issues a reference. src/components/reservation/BookingWizard.tsx, src/app/api/reservation/route.ts

[04]

Five-language runtime i18n with Arabic RTL

French, English, Arabic, Russian and German served from a nested dictionary through a context provider, with a header language switcher, locale persisted to localStorage, document lang and dir flipped for Arabic, and per-locale Intl date formatting inside the wizard. src/i18n/

[05]

In-house motion component kit

Eight primitives written in the React-Bits idiom rather than installed: clip-path mask reveals in curtain, circle and diagonal variants, split-text line reveals, a scroll-triggered count-up, a magnetic button, a pointer-tracked spotlight card, a CSS shine text and a fade-on-enter wrapper. Each guards prefers-reduced-motion. src/components/bits/

[06]

Hand-drawn SVG artwork and map

Per-room generative SVG scenes with five palettes, dusk variants and a zellige pattern, plus a bespoke stylised map of Sousse in the brand palette with a SMIL-animated marker halo that links straight to Google Maps directions. No image or map SDK dependency. src/components/art/RoomArt.tsx, src/components/contact/SousseMap.tsx

Stack
Framework
Next.js 16React 19TypeScript
Motion
GSAP ScrollTriggerGSAP SplitTextLenis
Styling & infra
Tailwind CSS v4Lucide ReactVercel
See it in production

Live in production

Dar Azur Hôtel & Spa is running in production today. Open it, then tell us what you want built — BreakNRoot engineers systems like this one from first prototype to production.

Adjacent records
>_ BREAKNROOT//SYSTEM.ONLINE