Back to portfolio
Case Study

PureZen

A full-stack spa booking platform on AWS - a natural-language concierge that books appointments for guests, and an operations console with an AI assistant for staff, on a fully serverless backend.

A concept build for a fictional spa brand, architected and built solo. Fully serverless on AWS API Gateway, Lambda, S3, CloudFront, and DynamoDB using Anthropic's Claude powering the conversational and agentic layers, all defined in AWS CDK.

The problem

Spa booking is a transactional domain where wrong answers have real cost. A concierge inventing availability or double-booking is worse than no concierge at all. The goal: a natural-language booking experience that feels effortless for guests, but is grounded in live data and structurally unable to confirm a slot that doesn't exist.

PureZen runs the full lifecycle: browse services, check availability, book, reschedule, cancel, and look up history through conversation, with a separate administrative console for schedule management and operational insight.

Two products, one backend

Guest concierge

A chat-first booking experience. Guests describe what they want in plain language (“A deep-tissue massage next Tuesday afternoon”); the system resolves the service against the real catalog, checks live availability, and walks them through booking, rescheduling, cancelling, or reviewing past appointments. The conversation state persists per session.

Administrative console

A staff portal with dashboards for daily overview, schedule, guests, users, and analytics. plus an AI assistant that answers operational questions by querying live data (“How many bookings tomorrow?”, “What are this week’s trends?”, “Show me this guest’s history”). Each answer is produced from a real database query, not the model’s memory.

You can explore it yourself - the admin console opens in a read-only demo: every dashboard and the AI assistant are live, while changes are disabled so the shared data stays intact.

Architecture

A serverless design on AWS with no always-on application compute to maintain. The static frontend is delivered from S3 via CloudFront; API traffic flows through API Gateway to a containerized Lambda.


Present State in AWS

Browserguest & admin UI
static · HTTPS
CloudFrontglobal CDN · TLS
S3static frontend
/api calls
API GatewayREST · LambdaRestApi
AWS Lambdacontainer · FastAPI + Mangum
Anthropic - Claudeconcierge & admin agent
DynamoDBbookings · services · staff · sessions
CloudWatchlogs · metrics
AWS CDK  infrastructure as code · least-privilege IAM roles · scales to zero

Highlights

AI design - grounded, not guessing

The model formats data; it never invents it

The concierge never answers from training knowledge. Services are resolved against the real catalog, availability and bookings come straight from DynamoDB, and the booking, reschedule, and cancel flows are deterministic state machines. Claude’s job is to understand intent and phrase the response when it physically can’t surface a slot the database didn’t return. That keeps every booking action traceable back to a specific query.

Deterministic routing first, model second

A regex-based intent router handles the common, well-formed requests - dates, times, service names, booking IDs - without a model call, and Claude (Haiku 4.5) is invoked for the genuinely conversational or ambiguous turns. Keeping the model a fallback rather than the front door means lower latency and predictable cost on the hot paths.

An agentic admin assistant - MCP-inspired

The staff assistant is built on Anthropic tool use, in a structure inspired by the Model Context Protocol: a clean separation between the model, a registry of typed tools, and the live data behind them - implemented as a focused in-app tool layer rather than a full MCP server. The tools - get_bookings_by_date, get_staff_roster, get_customer_history, get_trends, get_upcoming_bookings, and more - are typed data operations the model can call to answer a question, then summarize. The model decides which data to fetch; the tools guarantee it’s always real.

Engineering decisions & trade-offs

Decide when not to use the LLM

The most reliable features used the least AI. Anything with an exact answer - availability, trend counts, a guest’s history - is a deterministic function reading live data, which is faster, cheaper, and more predictable than asking a model. The LLM is reserved for language understanding and phrasing, where it’s genuinely the right tool.

Working within - then beyond - AWS Academy

PureZen began as an AWS Academy capstone using the infrastructure available in that environment, including EC2, load balancing, VPC networking, routing tables, and IAM. That first generation gave me hands-on experience with traditional AWS infrastructure, but the Academy environment was intentionally constrained and temporary.

The second generation moved the application outside the Academy environment: the frontend was hosted on Vercel and the FastAPI backend ran on Hetzner. That removed the Academy lifecycle constraint, but it still left the application split across external hosting and persistent backend compute.

The third generation brought the application back to AWS and re-platformed it around managed services: container-image Lambda + API Gateway for the FastAPI backend, DynamoDB for application data, private S3 + CloudFront for frontend delivery, and AWS CDK v2 for reproducible infrastructure. The local Ollama runtime dependency was also removed from the deployment path in favor of managed Anthropic inference.

Infrastructure evolution

Generation 1AWS Academy
EC2 + Load BalancingVPC · routing · IAM
re-host
Generation 2Vercel frontend
Hetzner backendpersistent FastAPI server
re-platform
Generation 3AWS serverless
Lambda + API GatewayS3 · CloudFront · DynamoDB · CDK

Infrastructure as code with CDK

An early environment loss, when the system existed only AWS Academy, made reproducibility a first-class concern. The stack is now declared in AWS CDK, so the entire environment (compute, gateway, CDN, data, IAM, and frontend deploy with cache invalidation) rebuilds from code rather than memory.

Stack at a glance

LayerTech
FrontendVanilla HTML / JS / CSS on S3, served via CloudFront
APIAmazon API Gateway (REST) → AWS Lambda
BackendPython · FastAPI · Mangum, containerized Lambda (Python 3.11)
DataAmazon DynamoDB - bookings, services, staff, availability, customers, sessions
AIAnthropic Claude (Haiku 4.5) - grounded concierge + MCP-inspired tool-using admin agent
Authbcrypt password hashing, session-scoped guest & admin access
InfraAWS CDK (TypeScript), least-privilege IAM, CloudWatch logs & metrics
My role - Architect and engineer: serverless architecture (API Gateway, Lambda, S3, CloudFront), DynamoDB data modeling, the FastAPI backend, the grounded concierge and the agentic admin assistant on Anthropic's Claude, the frontend, and the AWS CDK deployment.