Ritz-Carlton Riyadh
Guest-experience platform for the Ritz-Carlton Riyadh property: bilingual booking flow, room services, AWS-backed analytics, integrated with the brand corporate site.
About the project.
A guest-experience platform for the Ritz-Carlton Riyadh property, sitting alongside the brand corporate site without breaking its conventions. The build covered a bilingual booking flow, in-room services, and an AWS-backed analytics layer feeding the operations team. I worked across the React front end, the Node services, and the Postgres model that ties room state to guest history. Luxury hospitality is a tough audience; every interaction has to feel calm and never make the guest think about software.
What changed.
Largest Contentful Paint
localized
increase in direct bookings
What we walked into.
A luxury-hospitality property under the Marriott umbrella needed a guest-experience platform that sat alongside the brand corporate site without breaking its conventions: bilingual booking flow, in-room services, and an analytics layer the operations team could actually read at 6am.
What we did.
Next.js front end for the public booking + content surfaces, Node.js services behind for the room-state + guest-history APIs, PostgreSQL as the source of truth, AWS-backed (S3 + CloudFront + RDS + CloudWatch) for the parts that have to never go down. Bilingual ar/en with native RTL typography — luxury Arabic copy is not machine-translated.
What it became.
Shipped on the Ritz-Carlton Riyadh property timeline. Sub-second TTFB on the booking surfaces, analytics dashboards live for the GM's morning huddle.
My role on this project.
Full-stack engineering ownership — I built the React/Next.js front end, the Node services, the Postgres schema, and the AWS deployment. Worked alongside a Marriott brand designer (who owned visual identity) and the property's operations stakeholder (who owned business rules). I did not own the corporate brand site itself; the integration boundary is documented in the contract.
Front-end engineer
Next.js 13, App Router, RSC for the public surfaces, bilingual ar/en with RTL-first typography in both Latin and Arabic faces. Hit luxury-grade animation budgets (no jank on iPad in-room devices).
Back-end engineer
Node.js (Fastify) + Postgres schema for room state, guest history, in-room service requests. Snapshotted PMS feed via scheduled job.
DevOps + AWS
CloudFront CDN, S3 for static assets, RDS Postgres, CloudWatch alarms tied to PagerDuty. Multi-AZ for the ops API. Daily snapshots, restore-tested.
Arabic-first localisation
Native Arabic UX copy + RTL design pass on every screen. No machine translation; reviewed against Marriott brand voice in Arabic.
The numbers that matter.
- <800msTTFB · booking pagep75, CloudFront-cached static + RSC-rendered shell. Measured from KSA edges.
- 99.9%Booking-API uptimeCloudWatch over 12 months. Multi-AZ RDS + dual ECS tasks behind ALB.
- BilingualAR + EN nativeHand-written Arabic; RTL passes on every screen; brand-voice-reviewed.
- LiveOps dashboard refreshSub-minute refresh from PMS snapshot → CloudWatch → ops UI.
- WCAG AAAccessibility auditTested against AXE + manual keyboard nav + iOS VoiceOver for the in-room iPad flow.
- 0Brand-site regressionsIntegration boundary held — no shared-CSS bleed into the Marriott corporate surfaces.
What was actually broken.
Luxury hospitality is not e-commerce. A guest who is paying $1,200 a night will not forgive a 700ms button delay, an Arabic word broken across the wrong line, or a checkout that shows the wrong currency for two seconds. The brand site has decades of conventions (typography, animation budget, photography treatment) that any property-level extension must respect without copying them poorly. The brief: build a property-specific guest layer that feels like Ritz-Carlton, not like a SaaS plugin on top of Ritz-Carlton.
The hard surface area.
- 01Brand integration without brand pollution: property pages must share the corporate header/footer without inheriting any custom CSS that would later drift when corporate updates.
- 02RTL parity: every layout, every animation, every gradient direction tested in Arabic. Luxury Arabic typography requires custom kerning + line-height tuning that defaults from Tailwind cannot deliver.
- 03In-room iPad surfaces: ageing devices, cracked screens, sticky touch — UI must remain usable at 30fps on 5-year-old iPads in real housekeeping conditions.
- 04PMS (Property Management System) integration without becoming a PMS clone: read-mostly, snapshot-based, never the source of truth for reservation state.
- 05Operations dashboard the GM actually reads at 6am — printable, glanceable, no chart that requires hover-interaction.
Engineering wins worth naming.
Two CSS reset systems coexisting
Corporate site ships its own normalize. Property extension must isolate via shadow-DOM-style scoping (CSS Modules + a strict prefix) so corporate updates never break property pages and vice-versa.
Arabic numeric tabular alignment
Booking flow shows prices + dates + room counts in dense tables. Arabic-Indic digits render at different widths than Latin in some font families — settled on `font-feature-settings: "tnum"` plus Hindi-Arabic fallback chain.
PMS snapshot consistency
PMS feed updates every 5 minutes; UI must reflect "last refreshed 3m ago" honestly without showing stale-data UI as confident. Built a freshness pill on every room-availability call.
How the system is wired.
Edge tier
Application tier
Data tier
Observability + alerting
The decisions behind each choice.
Next.js 13 (front end)
- App Router + RSC gives sub-second TTFB without a separate static-site generator pipeline.
- i18n routing with locale subpath (/ar, /en) is first-class — no third-party translation framework.
- Server actions handle form submissions without the API round-trip JavaScript would normally require.
Postgres + RDS Multi-AZ
- Multi-AZ is the only way to give a 24/7 property platform the uptime its SLA implies. Failover under 60 seconds, automated.
- JSONB columns store the wildly variable PMS payloads without a migration per upstream field change.
AWS over GCP/Azure
- Marriott IT already speaks AWS — Route 53 zones, IAM federation, billing consolidation all pre-existed.
- KSA region (me-south-1 Bahrain + me-central-1 UAE) gives sub-50ms latency to property guests.
What the build taught us.
- Luxury is consistency, not flash. Every animation budget exists to make the guest forget software is present.
- PMS integrations are read-mostly. Never become a second source of truth for reservations; you will lose every reconciliation argument with the front desk.
- RTL is not a configuration flag — it is a design discipline you apply at every layout decision, every animation curve, every gradient direction.
