Status: In developmentCo-built with partnersPrivate client repo

Kartar Aarogyam Wellness Centre

Website and booking system for a wellness centre

A public website with Virtual OPD (online doctor consultation) booking, medicine inquiries and a secure admin dashboard. Forms are bot-protected and validated on both client and server; the admin panel manages bookings, content and a Mon–Sat schedule, with hourly reminder and cleanup jobs.

Kartar Aarogyam home page: homeopathic consultations with Dr. Amritpal Kaur, with a consultation details card and a Book a consultation button.
Built with
Next.jsReactTypeScriptTailwind CSSshadcn/uiReact Hook Form + ZodCloudflare WorkersCloudflare D1Drizzle ORMWorkers KV / R2Cloudflare TurnstileVitestPlaywright + axe-core
Type
Client & collaborative work
Source
Private client repository

How it decides

Booking request → confirmed slot

Untrusted inputEnforced on the serverPOSTinsertsessionPatientbooks Virtual OPDClinic staffadmin / super adminBooking formRHF + Zod in browserTurnstile tokenfrom the widgetRoute handlerZod · origin · limitsTurnstile verifyfails closedAdmin APIrequireAdminApi()D1 appointmentsunique slot_keyHourly cronreminders · cleanupR2 prescriptionsprivate bucketUntrusted inputEnforced on the serverPOSTinsertsessionPatientClinic staffBooking formTurnstile tokenRoute handlerTurnstile verifyAdmin APID1 appointmentsHourly cronR2 prescriptions
  • person
  • guesses / untrusted
  • decides
  • process
  • storage
  • third party
  • trust boundary

Boundary Where guessing stops and something deterministic decides.

  • A partial unique index on appointments.slot_key makes double-booking impossible at the database level. repo docs
  • Turnstile is verified on the server; without the secret, forms fail closed. repo docs
  • Every admin handler calls requireAdminApi(); prescriptions are only served through an admin-only route from a private bucket. repo docs
The drawing, in words

Kartar Aarogyam Wellness Centre: Booking request → confirmed slot. Left of the redline is “Untrusted input”; right of it is “Enforced on the server”.

  • Patient — books Virtual OPD (Untrusted input)
  • Clinic staff — admin / super admin (Untrusted input)
  • Booking form — RHF + Zod in browser (Untrusted input)
  • Turnstile token — from the widget (Untrusted input)
  • Route handler — Zod · origin · limits (Enforced on the server)
  • Turnstile verify — fails closed (Enforced on the server)
  • Admin API — requireAdminApi() (Enforced on the server)
  • D1 appointments — unique slot_key (Enforced on the server)
  • Hourly cron — reminders · cleanup (Enforced on the server)
  • R2 prescriptions — private bucket (Enforced on the server)

Connections

  • Patient → Booking form
  • Booking form → Route handler (POST)
  • Turnstile token → Turnstile verify
  • Turnstile verify → Route handler
  • Route handler → D1 appointments (insert)
  • Hourly cron → D1 appointments
  • Clinic staff → Admin API (session)
  • Admin API → R2 prescriptions

The problem

  • A clinic needs patients to book online consultations and send medicine inquiries without staff double-handling slots, and without exposing prescriptions or the admin side. repo docs

What was built

  • Public pages, Virtual OPD booking, medicine inquiries with prescription upload, and an admin dashboard for bookings, content, doctors and the weekly schedule. repo docs
  • Runs on Cloudflare Workers through OpenNext, with D1 + Drizzle for data, KV for page cache and a private R2 bucket for prescriptions. repo docs
  • Unit tests in Vitest; end-to-end tests in Playwright check every public page for one H1, SEO tags, no console errors and WCAG 2.2 AA with axe. repo docs

My part

  • Built the redesign of the public site (the “Parchi” visual system). commits
  • Built the three-step appointment booking flow and the Razorpay checkout backend. commits
  • Ran repeated critic-and-QA review rounds on the redesign — 56 items tracked in the first round alone. commits

Limits and open work

  • Not launched yet. stated
  • If R2 is not enabled, patients are asked to send prescriptions over WhatsApp instead of uploading them. repo docs

Decisions worth knowing

  • The database refuses double-booking

    A partial unique index on appointments.slot_key covers every pending or confirmed booking, so a race between two patients ends in one insert failing — not in two confirmations.

    repo docs

  • One schema, two places

    The same Zod schemas validate in React Hook Form and again in the route handlers, so the server never trusts the browser's checks.

    repo docs

  • Fail closed on bot protection

    Every public form needs a Turnstile token. Without the server secret, forms refuse to send instead of silently skipping the check.

    repo docs

A closer look

Default schedule: Monday to Saturday, 9:00 to 19:00, in 30-minute slots; one row per hour
HourMonTueWedThuFriSat
09
10
11held
12
13
14
15
16
17
18
  1. Request A · Tue 11:00INSERT … slot_key✓ booked (pending)
  2. Request B · Tue 11:00, same momentINSERT … slot_key✗ unique index violation → slot taken
Figure — the default week and the slot rulerepo docs Mon–Sat 9:00–19:00 in 30-minute slots is the migration's default schedule (one row per hour shown here); the two requests illustrate the unique index.