Case studies/A headless booking platform for a luxury hotel, built around the limits of its PMS
HospitalityHeadless commerceNext.jsCloudbeds integration

A headless booking platform for a luxury hotel, built around the limits of its PMS

Avenue Coral Gables

A custom Next.js and Sanity platform that replaces the rigid PMS booking widget for Avenue Coral Gables with a bespoke luxury interface, while keeping pricing, inventory, reservations and payments in sync with Cloudbeds.

The experience

A booking journey that looks like the hotel, not like the PMS.

Room galleries, amenities and copy come from the CMS; live rates, inventory and reservations come from the PMS, merged on the fly.

Suite presentation

High-resolution galleries, live availability.

Cloudbeds returns thumbnails and generic descriptions. The platform leads with the hotel’s own gallery and uses PMS images only as a fallback.

Suite living room with a balcony door overlooking Coral Gables buildings
Guest experience

Custom booking and checkout

A fast React 19 interface with fluid motion, promo handling that tells the truth, and a partial-deposit checkout.

Promo codesvalidated against baseline
Paymenttokenized deposit
Maps and videoMapbox + Mux
Operations

CMS-led control

Marketing and operations manage copy, galleries, promotions and tax rules in Sanity, with instant cache revalidation.

Contentrooms + galleries
Rulestaxes + excluded fees
Roomsauto-created stubs
Industry
Luxury hospitality
PMS
Cloudbeds API v1.3
CMS
Sanity, GROQ
Payments
Cloudbeds SDK, Authorize.Net
01 / THE CHALLENGE

The booking widget was the easy part to replace.

Going headless meant owning behaviour the PMS widget used to hide. Six limits of the API shaped the architecture.

01

Silent promo failures

Invalid codes return standard rates with no error.

02

Partial payments

A first-night deposit and a vaulted card had to land in the PMS folio.

03

Rigid tax model

Suite-specific fees and selective tax bases did not fit the PMS structure.

04

Occupancy truncation

Multi-room searches hid room types that could sleep the whole party.

05

Composite room IDs

Front-end keys like property-room caused authorisation errors in the API.

06

Thin room content

Low-resolution thumbnails and generic text fell short of a luxury brand.

02 / ARCHITECTURE

Architecture

Next.js route handlers sit between the interface, the CMS and the PMS, each decision answering one specific limit of the PMS API.

Decision 01

The PMS silently ignores invalid promo codes.

Run two availability requests in parallel, one with the code and one without, then compare per-night rates and rate-plan names. A lower rate or an explicit promo rate plan returns applied; identical rates return invalid, so the interface can tell the guest instead of showing unchanged prices.

The PMS silently ignores invalid promo codes. A promo code enters the availability route, which runs a promo fetch and a baseline fetch in parallel. Both feed a per-night rate comparison, which returns a promo status of applied or invalid. Guest enters promo code Availability route Promo fetch Baseline fetch Per night rate comparison Promo status applied or invalid

Architecture Narrative

A promo code enters the availability route, which runs a promo fetch and a baseline fetch in parallel. Both feed a per-night rate comparison, which returns a promo status of applied or invalid.

A partial deposit and a vaulted card had to land in the PMS folio together. A tokenized card is authorized for the deposit and logged to the Sanity audit ledger. The reservation is then posted. On success the deposit is captured and posted to the folio and the reservation is marked completed. On failure the card hold is voided. SDK card token Authorize deposit Sanity audit log postReservation Capture and postPayment Void card hold Reservation completed
A partial deposit and a vaulted card had to land in the PMS folio together. A tokenized card is authorized for the deposit and logged to the Sanity audit ledger. The reservation is then posted. On success the deposit is captured and posted to the folio and the reservation is marked completed. On failure the card hold is voided. SDK card token Authorize deposit Sanity audit log postReservation Capture and postPayment Reservation completed Void card hold

Architecture Narrative

A tokenized card is authorized for the deposit and logged to the Sanity audit ledger. The reservation is then posted. On success the deposit is captured and posted to the folio and the reservation is marked completed. On failure the card hold is voided.

Decision 02

A partial deposit and a vaulted card had to land in the PMS folio together.

Tokenize the card in the browser with the PMS payment SDK so card numbers never reach application servers, authorize the deposit, then post the reservation. Only after the reservation succeeds is the deposit captured and posted to the folio; if it fails, the hold is voided and the guest is not charged.

Decision 03

The PMS tax model could not express suite-specific fees.

The PMS tax model could not express suite-specific fees. Cloudbeds taxes and fees flow through an automated sync route into Sanity site settings. The tax and fee engine combines those rules with the guest cart to produce suite-specific totals. Cloudbeds taxes and fees Automated sync route Sanity site settings Tax and fee engine Guest cart Suite specific totals
The PMS tax model could not express suite-specific fees. Cloudbeds taxes and fees flow through an automated sync route into Sanity site settings. The tax and fee engine combines those rules with the guest cart to produce suite-specific totals. Cloudbeds taxes and fees Automated sync route Sanity site settings Tax and fee engine Suite specific totals Guest cart

Architecture Narrative

Cloudbeds taxes and fees flow through an automated sync route into Sanity site settings. The tax and fee engine combines those rules with the guest cart to produce suite-specific totals.

Move tax and fee rules into the CMS. Hotel managers set rates, bedroom-count rules and excluded fees in a custom Sanity Studio control, and a sync route imports baseline rates from the PMS so the two stay aligned.

Decision 04

Per-room occupancy checks hid room types that could sleep the whole party.

Search with a normalised occupancy of one adult to see all inventory, then split the real guest count across the selected cart lines when the reservation is posted, keeping each line within its capacity.

Per-room occupancy checks hid room types that could sleep the whole party. A discovery query with one adult returns the full room inventory. Selected cart lines then receive a proportional split of the guests, which is sent with the reservation. Discovery query with one adult Full room inventory Selected cart lines Proportional guest split postReservation occupancy

Architecture Narrative

A discovery query with one adult returns the full room inventory. Selected cart lines then receive a proportional split of the guests, which is sent with the reservation.

03 / EXECUTION

Content in one system, commerce in the other.

Sanity-first merging keeps the presentation luxurious. The PMS stays the system of record for everything that moves money.

FOR GUESTS

Feature Showcase

High-resolution galleries and amenity copy from Sanity lead every room; PMS images are appended only as fallbacks.

Suite kitchen with navy cabinets, a patterned tile backsplash and two windows
  • GalleriesCMS first, PMS fallback
  • Searchlive rates + inventory
  • Checkoutpartial deposit
FOR THE HOTEL

Operations in the CMS

Managers control pricing rules, promotional copy and tax exclusions without a deployment, and new PMS room types appear as stubs ready for enrichment.

Suite bathroom with a black marble shower wall and a lit mirror
  • Rulestaxes, fees, exclusions
  • SyncPMS tax import route
  • Roomsauto-created stub documents
04 / OUTCOMES

What the platform makes possible.

Branded

A bespoke interface replaces the widget

The booking journey matches the hotel’s visual identity end to end.

Honest

Promo codes report their real effect

Guests are told when a code is invalid instead of seeing unchanged rates.

Deposit

Partial payments with a vaulted card

The deposit posts to the folio and the balance stays due at check-in.

Safe

A failed reservation never charges the guest

Holds are voided automatically and every step is logged.

Editable

Staff manage rules and content themselves

Pricing rules, galleries and tax exclusions change without engineering.

Resilient

The PMS limits no longer reach the guest

Promo, tax, occupancy and key issues are handled behind the interface.

05 / STACK

A modern front end on a proven back office.

Decoupling lets each layer use the tool that suits it.

Experience

Server and client rendering with fluid motion.

  • Next.js 15
  • React 19
  • TypeScript
  • Tailwind CSS
  • Framer Motion

Content

Structured content and custom Studio controls.

  • Sanity
  • GROQ
  • Draft previews

Hotel operations

System of record for rates, inventory and folios.

  • Cloudbeds API v1.3
  • Cloudbeds SDK
  • Authorize.Net

Media and quality

Rich media and tested pricing logic.

  • Mux
  • Mapbox GL
  • Vitest
Next

Putting a custom front end on a rigid back-office system?

Headless booking, content-led commerce and payment flows can sit on top of an existing PMS or ERP without replacing it.