03Sole Developer
Chola Beach Resort
Resort Website & Enquiry Platform
- Role
- Full-Stack Developer / Frontend Architect - Sole Developer
- Stack
- TypeScriptNext.js 16React 19Tailwind CSS v4ZodVitestPlaywrightVercel
- Links
- cholabeachresort.com
Send an enquiry
We reply on WhatsApp or phone.
Name
Phone
Check-in
Check-out
Check-out must be after check-in.
Guests
Overview
A production-grade marketing and lead-generation website for a 14-cottage beachfront resort — 18+ routes including dynamic cottage pages, celebrations and venues, offers, gallery and enquiry flows.
Problem
The resort needed a fast, accessible marketing site that turns visits into enquiries, with content that non-technical staff can update without code changes.
Solution
A Next.js 16 site with 18+ routes (dynamic cottage pages, celebrations and venues, offers, gallery, enquiry flows) built on a framework-free domain core, a Zod-validated content-as-data layer, a single-source design token system and calendar-driven seasonal themes.
Architecture
- Next.js App Router pages — 18+ routes
- use-cases
- Domain core — domain · ports · use-cases (framework-free)
- ports & adapters
- Content adapter — 65+ typed JSON files (Zod)
- Enquiry → WhatsApp handoff
- IAvailabilityProvider / IPaymentGateway (stubs)
Features
- 18+ routes
- Dynamic cottage pages
- Enquiry flows
- Hexagonal architecture
- Content-as-data
- Zod validation
- Design token system
- Seasonal theming
- WhatsApp enquiry handoff
- Image optimization
- WCAG 2.1 AA
- Schema.org structured data
- Automated testing
- GitHub Actions CI
Engineering work
- Architected the codebase on ports-and-adapters (hexagonal) principles — a framework-free domain core with infrastructure adapters at the edges — and enforced the import boundaries with custom ESLint rules in CI.
- Built a content-as-data layer of 65+ typed JSON files validated at load time with Zod schemas, allowing non-technical content updates without code changes.
- Engineered a single-source design token system: colour, type and spacing generated from one JSON source into CSS variables and Tailwind theme config, with a lint rule that fails the build on any raw hex value outside the token file.
- Implemented seasonal theming — five calendar-driven themes that re-skin the entire site, including hero imagery and featured offers, by remapping semantic tokens on a single root attribute.
- Designed an enquiry pipeline with validation, deduplication and a pre-filled WhatsApp handoff, so the guest always retains a contact path even if notification delivery fails.
- Defined IAvailabilityProvider and IPaymentGateway interface ports backed by stubs, so real booking and Razorpay UPI integration becomes an adapter drop-in with zero page changes.
- Built an automated image optimisation pipeline using Sharp — responsive resizing plus blur placeholders — to meet a strict performance budget (LCP < 2.0s, CLS < 0.05, JS < 120KB gzipped) on mid-range Android over 4G.
- Achieved WCAG 2.1 AA compliance, verified by an automated contrast test across every seasonal theme plus axe-core scans at desktop and 360px viewports.
- Implemented schema.org structured data (Resort, LodgingBusiness with geo, Place, FAQPage) generated from the same content the page renders.
- Wrote 27 test files across unit, contract, component and end-to-end (Playwright) suites, wired into a GitHub Actions CI pipeline gating types, lint, formatting, token sync, tests and build on every push.
Engineering decisions
- 1Hexagonal (ports-and-adapters) structure with import boundaries enforced by custom ESLint rules in CI.
- 2Content validated with Zod when it loads, so bad content fails fast instead of reaching visitors.
- 3All colour, type and spacing values generated from one token file; a lint rule fails the build on raw hex values.
- 4Seasonal themes implemented by remapping semantic tokens on a single root attribute.
- 5Booking and Razorpay UPI kept behind interface ports, so real integrations are adapter drop-ins.
Code
const Cottage = z.object({ slug: z.string(), name: z.string(), maxGuests: z.number().int().positive(), images: z.array(ImageRef).min(1),});// Content is validated at load time — bad data fails fastexport const cottages = z.array(Cottage).parse(rawCottages);Screens
Cottages
Sea-facing Cottage
Up to 2 adults · extra bed on request
Cottage details, amenities and photos are loaded from typed content files, validated at build time.
Send an enquiry
We reply on WhatsApp or phone.
Name
Phone
Check-in
Check-out
Check-out must be after check-in.
Guests
Challenges
- A strict performance budget on mid-range Android over 4G — met with an automated Sharp image pipeline (responsive sizes + blur placeholders).
- Accessibility across five seasonal themes — verified with automated contrast tests and axe-core scans.
- Never losing an enquiry — validation, deduplication and a pre-filled WhatsApp handoff even if notification delivery fails.
Testing & delivery
- Testing
- Vitest, Testing Library and Playwright — 27 test files across unit, contract, component and E2E suites, plus axe-core accessibility scans.
- Delivery
- GitHub Actions gates types, lint, formatting, token sync, tests and build on every push; deployed on Vercel.
Results
- Performance budget: LCP < 2.0s, CLS < 0.05, JS < 120KB gzipped.
- WCAG 2.1 AA, verified by automated contrast tests and axe-core at desktop and 360px.
- 27 test files across unit, contract, component and end-to-end suites.