Studio Meridian

Aurelia

A twenty-two room hotel that needed to take bookings without handing the guest experience to a third-party widget.

Role
Design system, front end, booking engine
Pages
15
Signature system
Accessible date-range booking engine

Open the live site

The brief

Boutique properties almost always outsource booking to an embedded widget. It works, and it is also the moment the site stops being the property's and starts being the vendor's — different typography, different colours, an iframe that cannot be styled, and a guest who has visibly left the hotel's website halfway through paying it money. Aurelia wanted the whole journey to stay inside its own design.

Constraints

  • The booking flow had to look and behave as though it were part of the site, because it is.
  • Rates move with season and day of week; the published rate table and the quoted price must never disagree.
  • It had to be fully operable by keyboard and screen reader — a date picker is the single most commonly broken widget on the web.
  • No date library, no form library, no framework.

What we did

01

One rate engine, two consumers

Rate, availability and quoting logic lives in a single dependency-free module that the build imports to print "from $X" on room pages and the browser imports to quote the actual stay. There is no second implementation to drift, so the table on the rooms page is arithmetically the same as the number at checkout.

02

The calendar is a real grid

Not a listbox pretending to be a calendar. A role="grid" with roving tabindex, arrow / Home / End / PageUp / PageDown navigation, and an accessible name per cell giving the full date, its selection state and its availability — a bare day number tells a screen-reader user nothing.

03

Availability that does not lie

Choosing an arrival computes the furthest reachable departure — the night before the next sold-out night — and disables everything past it. The alternative is letting someone assemble a range that cannot be fulfilled and telling them so three steps later.

04

Deterministic, not random

Occupancy is a seeded hash of room and date rather than Math.random(), so the calendar is stable across reloads instead of rearranging itself under the guest.

What it cost

The booking flow needs JavaScript, because availability is computed in the browser. Rather than pretend otherwise, the page ships a noscript block with the phone number and email — which is what a twenty-two room property would actually want.

Every project trades something away. A case study that does not say what is a brochure.

How it was checked

  • A booking driven end to end in Chromium: dates, room, validation rejection, guest details, review, confirmation.
  • Keyboard model asserted directly — one cell in the tab order, arrows moving exactly one day and one week, PageDown changing month.
  • Every page checked for console errors, broken links, metadata and unlabelled graphics.