Live / Case study
The House of Chai Platform
Production web platform for a hospitality brand: a Vite/React frontend, a domain-driven backend-for-frontend, and Terraform-managed asset infrastructure, each deployed and released independently.
- Live production site· Verified 2026-05-24
- Private client project
- Case study available
- Architecture available
Overview
The House of Chai needed a production site that could take contact and booking requests without a database, a generic contact form, or a single point of failure between marketing content and request handling. The frontend (React, Vite, Tailwind) ships to Cloudflare Pages. A separate backend-for-frontend handles every contact and booking submission, built as small, ordered layers: domain entities and value objects with no framework dependencies, a thin application layer for orchestration, and an infrastructure layer that adapts to Resend for email. Brand assets are served from a Cloudflare R2 bucket behind a custom CDN domain, provisioned through Terraform rather than configured by hand in a dashboard.
Problem
The brand needed a reliable web experience that could ship independently across frontend and backend services without tying releases to one hosting provider, and every request handler had to resist the obvious abuse vectors: spoofed form submissions, scraped HMAC keys, and unbounded request volume.
My role
Frontend implementation, backend-for-frontend design, asset infrastructure (Terraform), deployment, and production verification.
Stack
- React
- Vite
- Fastify
- Cloudflare Pages
- Cloudflare R2
- Railway
- Terraform
Architecture
Domain-driven BFF with Terraform-managed asset CDN
The React frontend on Cloudflare Pages talks to a Fastify backend-for-frontend on Railway over HMAC-SHA256-signed requests. The BFF's domain layer never imports from infrastructure: a contact or booking submission moves through validation, an application use case, and only then an adapter that calls the Resend API. Brand assets bypass the BFF entirely, served straight from a Terraform-provisioned R2 bucket behind its own CDN domain.
01 Visitor
Browser session
HTTPS
02 React frontend
Vite, Cloudflare Pages
HMAC-signed request
03 Fastify BFF
Domain-driven, Railway
Contact / booking email
04 Resend
Branded transactional email
05 R2 asset CDN
Terraform-managed
Key features
- • Domain-driven BFF: entities and value objects with zero framework dependencies, dependencies only flow inward
- • HMAC-SHA256 request signing, rate limiting, and CSRF protection on every contact/booking submission
- • Branded HTML email templates rendered server-side and sent via Resend, no client-exposed API keys
- • Terraform-managed R2 bucket with a custom CDN domain for brand assets, version-controlled rather than dashboard-configured
Deployment
The frontend deploys through Cloudflare Pages and the Fastify BFF deploys independently on Railway. Asset infrastructure is provisioned through Terraform against a Cloudflare R2 backend, so the CDN domain and CORS rules live in version control instead of a dashboard someone has to remember to update.
Results
- • Live in production at thehouseofchai.co.za, independently verifiable via the link above
- • Frontend and BFF ship and release independently, with no shared deploy step blocking either side
- • BFF test coverage at 86.6%, frontend at 94.1%, both enforced in CI rather than measured occasionally
Security
Every contact and booking request is authenticated with an HMAC-SHA256 signature shared between frontend and BFF, then passed through rate limiting and CSRF checks before it reaches a handler. Input is validated against Zod schemas shared between layers, so a malformed or malicious payload never reaches the domain layer. Backend configuration and the Resend API key stay server-side; nothing related to email delivery ships in the client bundle.
Challenges
- • Keeping the domain layer pure, no Fastify types or Resend SDK calls leaking into entities or value objects
- • Signing every request without adding latency a visitor would notice on a contact form
- • Moving asset hosting from manual dashboard configuration to Terraform without downtime on the live CDN domain
What I learned
- • A backend-for-frontend earns its layering even at small scale: the email-template change that would have touched a route handler instead touched one adapter
- • Independent services need explicit deployment and health checks, not just independent repos
- • Infrastructure that started as a dashboard click is worth migrating to Terraform before it grows a second environment
Proof and evidence

screenshot
Live production surface
The public production site is available through the verified live link.
View verified evidence ↗private
Private deployment evidence
Additional deployment evidence is available on request.