Clinique El Yasmine
A multidisciplinary clinic in Sahloul, Sousse, built on Next.js 16: a four-step booking flow validated against each doctor's schedule, trilingual FR/EN/AR content, and accessibility engineered throughout.
Visit live site
03
Languages
04
Booking steps
07
Routes
Clinique El Yasmine is a private multidisciplinary clinic in the Sahloul district of Sousse, Tunisia, covering eight departments: cardiology, paediatrics, gynaecology and obstetrics, medical imaging, laboratory analysis, round-the-clock emergency care, dental medicine and ophthalmology. The site had to do two jobs at once: present a reassuring, unhurried institutional face, and act as a working front desk that turns an anxious visitor into a booked appointment without a phone call.
The build is a Next.js 16 App Router application on React 19 and Tailwind CSS v4, written in TypeScript. All editorial content lives in typed data modules rather than in markup, which is what makes the trilingual layer possible: services, doctors, price tables, opening hours, testimonials and even image alt text are stored as localised records with French guaranteed and English and Arabic layered on top. A client-side i18n provider swaps locale, persists the choice, and flips the document to right-to-left for Arabic, with the layout mirroring through logical properties and RTL variants.
Motion is deliberately restrained and entirely opt-out. GSAP with ScrollTrigger and SplitText drives the hero word reveal, the clip-path curtain on the hero photograph, the staggered specialty grid and the parallax bands; Lenis provides smooth scrolling synchronised to the GSAP ticker with an anchor offset tuned to the sticky header. Every one of those effects sits behind a prefers-reduced-motion match, and Lenis does not initialise at all for users who ask for less movement. The result reads as composure rather than showmanship, which is the correct register for a medical brand.
The Challenge
A clinic website is read under stress. Someone comparing emergency numbers at two in the morning, a parent checking whether the paediatrician consults on Saturdays, an expatriate family reading in Arabic or English rather than French, a patient using a screen reader to find a consultation price. Each of those journeys has to complete without a phone call and without a dead end, on a single codebase serving three languages and two writing directions. The brief also required a booking path that could not produce impossible requests, since a clinic secretariat absorbs the cost of every appointment submitted for a day the doctor does not consult.
What We Built
The site ships as a Next.js 16 App Router application on React 19, Tailwind CSS v4 and TypeScript, with eight route surfaces including statically generated per-doctor profile pages. The centrepiece is a four-step appointment flow that walks specialty, practitioner, slot and patient details, validating each step client-side and revalidating the whole payload in a route handler that cross-checks the doctor against the chosen specialty, rejects past dates and dates beyond a ninety-day window, enforces the Tunisian mobile and landline number format, and refuses days the selected doctor does not consult, naming the days they do. A parallel contact route applies the same validation discipline. Localisation runs through a typed dictionary and a per-record localised-string helper, with a language switcher that persists the choice and sets document direction for Arabic. Accessibility is engineered rather than retrofitted: a skip link, focus moved to the step heading on every transition, aria-live error summaries and confirmations, a focus-trapped mobile drawer, and a gallery lightbox with its own focus trap, Escape and arrow-key handling. Structured data, a sitemap that enumerates every doctor URL, robots rules and per-route canonical metadata complete the search layer.
The Outcome
What shipped is a complete eight-route clinic site, deployed on Vercel, that handles the clinic's public-facing work end to end: department detail with procedures and equipment, eight filterable practitioner profiles with training timelines and consultation days, a published price table with CNAM and private-insurance context, a contact page with a hand-drawn Sousse map card linking straight into Google Maps directions, and a booking flow that returns a reference on success. Because every string, price line and alt text is a typed localised record, the clinic can extend or correct content in one place and have it propagate across French, English and Arabic simultaneously. The accessibility and reduced-motion work means the same build serves keyboard users, screen-reader users and motion-sensitive visitors without a separate path, and the MedicalClinic structured data plus per-doctor sitemap entries give each practitioner an indexable surface of their own.
Four-step booking with per-doctor availability
Specialty, practitioner, date and slot, then patient details. src/components/booking/BookingForm.tsx validates each step before advancing and src/app/api/rendez-vous/route.ts revalidates the full payload server-side: the doctor must belong to the chosen specialty, the date must fall within ninety days and land on a day that doctor actually consults, and the phone number must match the Tunisian format. Emergency care is excluded from bookable specialties by design.
Trilingual French, English and Arabic with RTL
src/i18n holds a typed dictionary plus a Localized record type used across services, doctors, price tables, hours and image alt text. LanguageProvider persists the locale, sets document lang and dir, and Arabic flips the layout to right-to-left; dates and numbers format through per-locale Intl tags. French remains the guaranteed base language.
Accessibility engineered into every flow
A skip link to main content, focus moved to the step heading on each booking transition, aria-live regions for error summaries and confirmations, aria-current on active navigation, a focus-trapped mobile drawer with Escape and scroll lock, and screen-reader announcements of filter result counts on the doctors grid.
Reduced-motion-first GSAP and Lenis layer
src/lib/gsap.ts registers ScrollTrigger and SplitText; the hero reveals its title word by word behind a mask, opens the photograph with a clip-path curtain and a slow Ken Burns push, and parallaxes on scrub. Lenis smooth scrolling is synchronised to the GSAP ticker with an anchor offset for the sticky header, and does not initialise at all under prefers-reduced-motion. Every effect is wrapped in a gsap.matchMedia motion query.
Accessible full-screen gallery viewer
src/components/home/Galerie.tsx reveals tiles through five clip-path mask variants driven by scroll, then opens a dialog with its own focus trap, Escape to close, arrow-key navigation, body scroll lock, a Lenis prevent boundary, focus return to the trigger, and an aria-live caption. Built on GSAP with no lightbox dependency.
Search and structured-data layer
The home route emits MedicalClinic JSON-LD carrying address, geo coordinates, opening-hours specifications, specialties, procedures and each physician as an employee node. sitemap.ts enumerates the six static routes plus every doctor profile, robots.ts disallows the API namespace, and each route declares its own title, description and canonical.
Live in production
Clinique El Yasmine 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.
BNR-CF-06Café Sidra
A scroll-driven day cycle for a tea salon on the Boujaafar corniche in Sousse. The sky is interpolated from dawn to dusk as you read, above a hand-drawn SVG seafront in parallax.
Open fileBeef & Buns
A cinematic single-page site for a Sousse smash burger house, built around a scroll-driven 3D burger that opens layer by layer, with a WhatsApp order flow and phone-wallet loyalty passes.
Open file