← Home
Low Cost ClinicBanashankari, Bengaluru · website and admin
01The deck · October 2026

One tap to the clinic

The new website and admin for Low Cost Clinic, Dr. Jyoti Puthran’s general-physician practice in Banashankari. Patients read about care and fees, book, ask and give feedback in four languages, with no login and no online payment. The clinic team runs every booking, message and page from one admin. Patient details are encrypted, and every look at them is logged.

Astro · Cloudflare Workers · D1 · R2 19 build phases · 10–13 Oct 2026 Claude Code · Claude Design · Deep Research
Low Cost Clinic confirmed by the clinic Book
03The brief

A clinic website that does the clinic’s work

Low Cost Clinic is a general-physician and internal-medicine practice in Banashankari, Bengaluru, run by Dr. Jyoti Puthran. It serves local patients with diabetes, blood pressure, thyroid, cholesterol, fever and infections, and people looking for de-addiction or mental-health care.

Cost

Rs 0 a month

Free plans only. The domain is the one recurring cost.

Content

Everything is editable

Fees, hours, contacts, doctor details, page text, translations and photos live in the database and change in the admin.

Booking

Requested, then confirmed

Patients ask for a time online and the clinic confirms it. No login, no OTP, no online payment.

Messages

WhatsApp in one tap

Messages are written in the admin and sent from the clinic’s own WhatsApp. Emails go out by themselves.

The clinic’s line: “Quality care that doesn’t cost a fortune.”

10:0010:1510:30 10:4511:0011:15 a 30-minute visit takes two Paav = पाव one quarter of an hour
Paav (पाव, “a quarter”) walks through this deck. It is one 15-minute block, the unit every booking in the clinic’s calendar is made of.
04At a glance

What was built

A public website and a staff admin on one database, built to the medical ethics rules (IMC 2002) and India’s data protection law (DPDP Act 2023 and Rules 2025).

4
Languages
English, हिंदी, ಕನ್ನಡ and मराठी
21
Public pages
plus every article and each patient’s private booking page
31
Admin screens
for 4 roles: owner, reception, editor, translator
49
Message templates
bookings, home visits, follow-up, feedback, notices, staff
23
Feature switches
any feature or language off at once
9
Automatic jobs
expiry, reminders, digests, retention, backups
Rs 0
A month to run
Cloudflare and Resend free plans
370+
Automated tests
every rule that protects patient data, stops double booking or enforces a role

Where it stands (14 Oct 2026): all 19 phases are built and checked; the preview is live at preview.lowcostclinics.in. Production waits on a short launch checklist (slide 62).

05Part 1

For patients

What anyone sees on the public website. It is written for older and less tech-savvy patients as much as anyone: every page leads to Call, WhatsApp or Book in one tap, and nothing asks for a login.

Services Fees Book
06Public website

Twenty-one pages, one clear menu

Every page is built from the database, so a fee or a phone number changed in the admin changes on every page, in every language, at once.

Care · 8 service pages

  • General Physician
  • Internal Medicine
  • Diabetes
  • Hypertension
  • Fever & Infection
  • Mental Health Consultation
  • De-addiction
  • ADHD Coaching

The clinic

  • Home
  • Dr. Jyoti Puthran
  • Why Low Cost Clinic
  • Fees & Services
  • Contact & Location

Do something

  • Book an Appointment
  • Request a Home Visit
  • Articles
  • Patient Resources

The fine print

  • Privacy policy and data notice
  • Medical disclaimer
  • Terms of use
  • Page not found

Private, never in a menu

  • Each patient’s booking page
  • The feedback form
  • Thank-you screens
The home page on the preview site: a strip with the phone number and hours, the clinic logo and menu (Services, Dr. Jyoti Puthran, Fees, Articles, Why Low Cost Clinic, Contact), Call and Book Appointment buttons, and the headline General Physician and Internal Medicine Doctor in Banashankari, Bangalore, with Book, Call and WhatsApp buttons and 'First consultation ₹700, all fees shown upfront'
Home on the preview site: Book, Call and WhatsApp before anything else, and the first fee in the first screen.
The whole Diabetes page from top to bottom: summary with the doctor's qualifications and Book, Call and WhatsApp buttons; When to see a doctor checklist; complications screened and linked conditions checked; How diabetes care works here in five steps; How the clinic helps; the fees box with first visit ₹1,000 and follow-up ₹700; questions patients ask; written by Dr. Jyoti Puthran, medically reviewed on 13 Oct 2026; Visit the clinic card with address, hours and an Open in Google Maps button; the medical disclaimer with emergency numbers; and the footer
The Diabetes page, full length. Scroll inside the frame.
07Public website

Every service page, the same nine parts

A patient who has read one service page knows where everything is on the next.

  1. A plain summary with the doctor’s name and qualifications, and Book, Call and WhatsApp buttons
  2. “When to see a doctor”, as a checklist
  3. How the clinic helps: consultation, tests only when needed, follow-up, teleconsultation, home visit
  4. The fees box, read from the database
  5. Questions and answers that open on a tap, with no script needed
  6. Who wrote the page and who medically reviewed it, and when
  7. A location card with hours and the map
  8. A short medical disclaimer
  9. The emergency numbers 108 and 112

Mental health and de-addiction pages use the same layout. The WhatsApp message they prepare says only “Consultation with Dr. Jyoti Puthran”.

08Public website

Fees first, the clinic one tap away

Doctors are expected to announce their fees (IMC 2002), so every fee is on the Fees page and in each service page’s fees box before anyone books. Fees are paid at the clinic; there is no online payment.

  • The phone number is shown as text and as a tap-to-call button.
  • WhatsApp opens a chat with a ready message in the page’s language.
  • The map is a picture with Tap to load map. Google Maps loads only when asked, so nothing from Google runs on a plain visit.
  • On phones a bar at the bottom keeps Call, WhatsApp and Book in reach, and the header stays at the top.
  • The footer carries the address, hours, the doctor’s registration number and council, every service, the legal pages and the emergency line.
The Fees and Services page: 'Every fee is shown here before your visit. Fees are paid at the clinic; there is no online payment', then a Clinic consultations card with First general consultation ₹700, 3 days' free follow-up for sharing advised reports
The Contact and Location page: the address in Banashankari with Get directions, the phone and WhatsApp number, and a striped map placeholder with a Tap to load map button
09Online booking

Booking in five steps, about two minutes

One question per step with a progress bar, built to work on a basic Android phone.

12345 visit typedatetimeyour detailsreview & send ₹700 then the clinic confirms, by WhatsApp or a call
  • Only free times are offered, grouped into morning and evening. Closed and leave days are greyed out with the reason.
  • If someone else takes the time while the patient types, they pick another and their details stay.
  • Double taps and retries never make two bookings.
  • The clinic confirms every request. One left unconfirmed expires by itself and frees the time.
  • “For emergencies, call 108 or go to the nearest hospital. Do not book online.”
  • Mental health, de-addiction and teleconsultation visits are bookable online only while their switch is on.
The booking page on a phone: 'Booking requests are confirmed by the clinic. Fees are paid at the clinic', a pink emergency notice to call 108, Step 1 of 5 with a progress bar, and visit-type cards: General consultation, first visit, 30 minutes, ₹700; Diabetes, BP, lipid or obesity, first visit; and the bottom bar with Call, WhatsApp and Book
Step 1 of 5 on a phone
…/booking/k7Q9xR2vTm no name, no number Your booking •••3 5 tries, then 1 hour
10Private booking page

A private page for every booking

Right after booking, and from every message, the patient reaches a page of their own. There is no account and no password.

  • It opens after the last 4 digits of the mobile number used. Five wrong tries lock it for an hour.
  • It shows the reference (such as LCC-4K7Q), status, visit type, date, time, fee, address and map, a masked mobile number, what to bring and the booking’s history.
  • Add to calendar, fix a name or an email, change the contact preference or language, reschedule, cancel, turn reminders off, print or save as PDF.
  • After the clinic’s cutoff the buttons give way to “Please call the clinic to make changes”.
  • The link stops working 30 days after the visit. The page is titled only “Your booking”, and is never indexed or cached.
11Public website

Home visits and questions

Request a home visit

For patients who cannot travel: name, mobile, locality (from the clinic’s served areas), PIN code, preferred date, a time window (morning, afternoon or evening), visit type, an optional short note and the consent box.

The fee shows before sending: the area’s fee, or “confirmed on the call”. An unlisted area reads “We may not be able to visit this area. Please call us.” The patient gets a private page, as for a booking.

Never online

The full street address is never collected on the website. Staff take it on the confirmation call.

Enquiry form, on the Contact page

Name, mobile, topic, message, how to reply, whether a message may be left, and consent, with the line “Please do not share medical details here.”

Every public form has invisible spam protection (Cloudflare Turnstile), a hidden trap field and a limit of 5 sends an hour per visitor.

Request a Home Visit on a phone: 'For patients who cannot travel to the clinic. Send a request and the clinic will call you to confirm the address, time and fee', a fee card with Home visit fee ₹2,000 within 1 km of the clinic, and notes that the full street address is not collected online, that visits are confirmed only after the call, and to call 108 or 112 in an emergency
The home-visit form on a phone
12After the visit · on every page

Feedback stays inside; notices go on top

Feedback after a visit

Once a visit is marked completed the patient gets a feedback link: on WhatsApp from the clinic, or by email the next morning. A 1–5 star rating; four Yes / Somewhat / No questions (felt heard; diagnosis and treatment explained; waiting time acceptable; fees clear beforehand); an optional comment; an option to stay anonymous and a “You may contact me” tick. One response per visit; the link works for 14 days.

Feedback is never published. Testimonials count as self-promotion under IMC 2002, so the site has none.

Holiday and leave banner

A slim notice above every page (Holiday, Doctor on leave, Changed hours or General notice) in the visitor’s language, between its start and end times. The visitor can close it, and it never covers the Call or WhatsApp buttons.

for the clinic only
13Public website

Reading, downloads and search

Articles

A list with search, category, sort and pages, showing reading time and the “Medically reviewed on” date. Each article has headings, lists, highlighted boxes, images, references, an author box, a related service and a Book button.

Patient resources

Free PDFs (diet guides, log sheets, exercise sheets) by category, the visitor’s language first. No login, email or form before downloading. Downloads are counted per day and language, with nothing about the visitor stored.

Search engines

Unique titles and descriptions, one address per page, a sitemap, and structured data that names the clinic, the doctor and each qualification. English is the indexed version; private pages, downloads and filtered lists are kept out.

  • MedicalClinic
  • Physician
  • MedicalWebPage
  • Article
  • FAQPage
  • BreadcrumbList
downloads today English हिंदी ಕನ್ನಡ no names, no addresses PDF
14Part 2

For the clinic team

The admin is where reception confirms bookings and sends messages, the editor keeps the pages right, translators work in their languages, and the owner approves what needs approving. It works on a computer, a tablet or a phone, in light or dark.

requested confirmed
15Admin · sign-in

One sign-in, four roles

Staff sign in through Cloudflare Access with a one-time code sent to an allowed email address, or with Google. The site stores no passwords.

  • Owner: everything, including feedback comments and message text.
  • Reception: bookings, home visits, enquiries and messages.
  • Editor: website content; no patient data.
  • Translator: assigned languages only; no patient data.

One table in the code lists every screen and the roles that may open it. The menu, the tabs, the route checks and even the user guide read that same table, so nobody is shown a screen they cannot open.

Who opens which screens (✓ yes, — no)
ScreensOwnerReceptionEditorTranslator
Dashboard, user guide✓✓✓✓
Appointments (Day, Week)✓✓——
Home-visit requests, enquiries✓✓——
Feedback, service areas✓———
Message generator, log, daily messages✓✓——
Pages, interface text, articles, resources, templates✓—✓✓
Media library, menus, clinic details, fees✓—✓—
Hours & closures, banners✓✓✓—
Booking rules✓✓——
Publish and its history✓—✓—
Feature switches, users, audit log✓———

Reception sees the message log without message text. Editors’ fee changes wait for the owner. Translators can’t publish or mark a page reviewed.

16Admin · overview

The day, at the top of the dashboard

  • Today cards: today’s visits, requests waiting for confirmation (and how long the oldest has waited), home visits, new enquiries, reminders not sent, the active banner.
  • Charts with date ranges and filters: bookings per day, visit types, confirmation, completion, cancellation and no-show rates, time to confirm, online versus reception, languages, feedback, home visits, enquiries and downloads. Each has a table view.
  • System card (owner): last publish, last backup and today’s free-plan usage, so a limit is seen before it is reached.
  • Totals CSV (owner): counts only, never a patient row.
The admin dashboard with made-up data: Today, Last 7 days, Last 30 days and This month buttons; date, visit type, area and language filters; cards for 4 appointments today, 3 waiting for confirmation with the oldest waiting 16 hours 36 minutes, 0 home visits today, 2 new enquiries, 0 reminders not sent; an amber active-banner strip; and the first charts, Appointments per day and By visit type
Made-up sample week. Every admin screenshot in this deck comes from the guide’s generator, never from real patients.
17Admin · appointments

Reception runs the day from one list

Day and Week views, with a badge for requests waiting for confirmation. Each row carries only the buttons that make sense for its status.

  • Confirm
  • Decline, with a reason
  • Reschedule
  • Cancel
  • Arrived
  • Mark completed
  • No-show
  • New booking for phone and desk bookings: confirmed at once, up to 60 days ahead.
  • Block time: a range, a session or a whole day. It disappears from online booking at once.
  • Mobile numbers are masked in lists. Searches by name or last 4 digits are posted, so they never appear in the address bar.
Appointments, Day view for Wednesday 14 October 2026 with made-up patients: a '3 waiting for confirmation' badge, Block time and New booking buttons, filters, a note that name and digit searches are posted so they never appear in the address bar, and rows: 10:00 completed, 10:30 arrived with Mark completed, 11:30 confirmed (visit type shown only as Consultation) with Arrived, No-show, Reschedule and Cancel, and 5:00 pm requested with Confirm, Reschedule and Decline
18Admin · statuses

A booking’s life, in seven words

The same status colours appear everywhere in the admin: Requested Confirmed Completed Declined Cancelled No-show Expired. A move that isn’t allowed from the current status is refused, and arrival, completion and no-show belong to the visit day.

RequestedConfirmedCompleted confirm on the day reschedule (status kept) DeclinedExpiredCancelledNo-show with a reasonnobody confirmedpatient or clinicdidn’t come feedback link
19Admin · a booking

Every booking carries its messages and its history

  • A message panel on each booking: confirmation, new time, decline, cancellation, feedback request. The approved template is filled in the patient’s language, ready to edit.
  • Send on WhatsApp copies the text first, then opens the clinic’s WhatsApp with it, so it can be pasted if WhatsApp opens empty. Copy and Send by email sit beside it.
  • Wording stays neutral: no visit type and no health details in any message.
  • A timeline of everything that happened: key dates across the top, then each status change, edit, message, page access and note, with filters and print.
The key-dates strip of a booking: Requested Tuesday 13 October 6:00 pm, Confirmed Wednesday 14 October 10:35 am, Rescheduled none, Reminder sent none, Visit Thursday 15 October 10:00 am, Completed none, Feedback none; filter chips for Status, Changes, Messages, Access, Notes and Feedback; and the first timeline entries, booking requested by the patient online, then confirmed by staff 16 hours 36 minutes later
The top of a booking’s timeline
Booking LCC-RZWR just confirmed, with made-up patient Lakshmi Test: visit type, date and time Thursday 15 October 2026 10:00 to 10:30 am, a masked mobile number with a Call link, contact by WhatsApp, language Hindi; Reschedule, Cancel, Message patient and Other messages buttons; and the Confirmation message panel with Confirmation and New time tabs, language tabs with Hindi marked as the patient's, the filled message with the clinic address, map link and booking link, a note on neutral wording, and Send on WhatsApp and Copy buttons
Just confirmed: the message is ready to send
20Admin · home visits

Home visits share the clinic’s calendar

  • A requests list and a page for each request: schedule, move, cancel and complete.
  • A scheduled visit blocks the same time in the clinic calendar, so online booking can’t offer it.
  • Ready messages: visit scheduled, please share the full address, the doctor is on the way, cancellation, feedback request.
  • Service areas (owner): names in each language, PIN codes, a fee per area, order and on or off.

The street address is taken on the confirmation call and is not stored online.

The Home visits list with made-up data: a '1 new request' badge, filters for status, area, time, language and preferred date, and two rows: LCC-HK4X in Kathreguppe, PIN 560085, ₹2,000, preferred Friday 16 October afternoon, Requested; and LCC-HVEZ in Padmanabhanagar, fee on the call, scheduled Thursday 15 October 2 to 3 pm; a note that full street addresses are taken on the confirmation call and a scheduled visit blocks the same time in the clinic calendar
21Admin · inboxes

Two inboxes that stay closed until opened

The Enquiries inbox with made-up names: All, New, Contacted, Closed and Spam tabs, filters, and three rows each showing 'Topic hidden', and a side panel saying topic and message are shown only after opening, and each opening is logged
Enquiries · owner and reception

Topic and message stay hidden until an enquiry is opened, and each opening is logged. Call, reply with a template, mark contacted, close or mark as spam. When a patient withdraws consent, the enquiry is deleted that night.

The Feedback inbox, owner only, with made-up data: cards for average rating 4.5, 2 responses, 0 low ratings to follow up, 100 percent response rate; an opened four-star feedback with the notice 'You opened this feedback. The view was recorded in the audit log', its comment, visit type, date, a note that the patient allowed contact, answer chips Heard yes, Explained yes, Waiting somewhat, Fees clear yes, and Mark reviewed, Needs follow-up, Open the visit to call back and Call-back message buttons
Feedback · owner only

Ratings and answers, the comment after opening, Reviewed or Needs follow-up, and a call-back only when the patient allowed it. Comments are deleted after 12 months.

The Message generator: 1 use case Confirmed; 2 language, English marked as the recipient's, with Hindi, Kannada and Marathi; 3 recipient, a booking reference with a made-up name; 4 channel WhatsApp, Email or Plain text; a note that only approved templates are filled, with no diagnoses, results, medicine names or clinical advice; 5 preview and edit with the filled confirmation text; Send on WhatsApp, Copy and Print
22Admin · messages

Any message, from an approved template

Choose a use case, a language (the recipient’s by default), a recipient and a channel. The approved template is filled with the booking’s details; anything missing is listed. Edit, then Send on WhatsApp, Copy, Send email or Print.

Templates · 49 use cases

Bookings, teleconsultation, home visits, follow-up, feedback, enquiries, clinic notices, fees, information and staff. Each has a text per language, variables, drafts and approval. Approved versions are kept, so the log can always show what was sent. Clinical topics need the owner’s approval.

No AI writes these messages. Staff fill approved wording, and nothing leaves without a person pressing Send.

23Admin · messages

Every message logged; tomorrow’s reminders in one tap each

The Message log with made-up data: cards for total messages, emails delivered, WhatsApp opened and copied, automatic versus manual, reminders due, top use case, by language, edited before sending, and failures; then filters for channel, status, use case, language, trigger, sender and date, and an Export CSV (metadata) button
Message log

Every WhatsApp opened or copied and every email, with stats, filters, delivery status from the email provider, “Send again” for a failed email, and a metadata-only CSV. Message text is the owner’s only.

Daily messages and reminders: Reminders for tomorrow, Thursday 15 October 2026, with four made-up bookings and a home visit, each marked WhatsApp not sent with Send on WhatsApp and Copy buttons; below, Ready for staff today with Tomorrow's schedule (emails at 8:00 pm) and Today's summary (emails at 9:00 pm), each a block of text with references only
Daily messages & reminders

Tomorrow’s WhatsApp reminders in one tap each; email reminders go by themselves at 6 pm. The staff schedule (8 pm) and summary (9 pm) carry references and counts, never names. A Tomorrow list prints for the desk.

24Admin · website content

Every word on the site is edited here

  • Pages & translations: each page’s title, heading, search text, summary, sections and questions, with character counters, a draft preview, a medical review and “Sensitive” marks.
  • Interface text: buttons, menus, form texts, fee names, qualifications and categories in each language.
  • Articles: a block editor (headings, paragraphs, lists, callouts, images), references, a cover image, a related page and review.
  • Translators see their own languages, with the English beside each field. A page without a reviewed translation stays English on the site, with a short note.
The page editor for Diabetes in English: language tabs with English ticked and Hindi, Kannada and Marathi empty, Preview the draft, and fields with character counters: page title 8 of 120, main heading 42 of 160, search title 49 of 60, search description 141 of 160, plain-language summary, sharing title and description, and WhatsApp message
The same page for a translator, in Hindi: a notice that translators edit their assigned languages and cannot publish or mark a page reviewed, English read-only for reference, 'No translation yet: the website shows English with a short note', and empty fields each with the English text below
25Admin · publish

One button sends every ready change

Edits are saved as drafts. Publish sends every change that is ready to the website, which is rebuilt in 1–3 minutes while staff keep working.

  • A change that needs the owner (a fee edited by an editor, clinic settings) or a medical review (a page or an article) waits, and says why.
  • Publish history shows each build and who asked for it.
  • The public pages are plain files, so they stay up even if the database is down.
The Publish screen with made-up data: 'Publish 1 change to the website?' listing a fee change marked Needs owner, a Hypertension page and an article marked Not reviewed, and an image text change marked Draft; a Publish now button with 'The website is usually rebuilt in 1 to 3 minutes. You can keep working'; and a table of earlier publishes
draft medically reviewed owner approves Publish live in 1–3 minutes
26Admin · clinic settings

The clinic’s facts, in six tabs

  1. Clinic details: name, address, map link, phone, WhatsApp, email, social links, headline and tagline; the doctor’s registration number, council and photograph (owner).
  2. Fees: an editor’s change waits for the owner’s approval.
  3. Hours & closures: the weekly hours and closed days.
  4. Booking rules: how far ahead, minimum notice, when unconfirmed requests expire, the change and cancel cutoff, how many online reschedules, visit lengths and the weekly booking schedule.
  5. Banners: previewed in all four languages, with the option to close online booking for those dates.
  6. Menus: header and footer order; the legal links, the emergency line and Book stay locked in.

Online booking answers “unavailable” until the booking rules are filled in. Nothing is guessed.

The Booking rules tab: booking limits of 14 days ahead, 12 hours minimum notice, unconfirmed requests expiring after 24 hours, a 12-hour change and cancel cutoff and 2 online reschedules; and visit types with fees and durations in 15-minute blocks, such as General consultation ₹700, 2 blocks; Follow-up ₹700, 1 block; Video follow-up and Teleconsultation off by their switch; and a De-addiction session marked Sensitive: neutral wording, off for online booking
Feature switches, owner only: 23 switches, among them online booking, home-visit page and form, general enquiry form, banner on all pages, articles, resources, feedback requests, emails to patients, Send on WhatsApp in the admin, staff schedule and summary messages, day-before reminders and the message generator, all on, each with its code name
27Admin · system

Twenty-three switches, each one instant

The owner can stop any feature, or show a language, at once: online booking, home visits, the enquiry form, banners, articles, resources, feedback, patient emails, WhatsApp buttons, staff digests, reminders, the generator, Hindi, Kannada, Marathi, analytics, teleconsultation and the sensitive visit types.

  • Dependent switches turn off together: teleconsultation booking needs online booking.
  • A switched-off endpoint answers “unavailable” with the clinic’s phone number. Existing bookings keep working.
  • Users & roles and the audit log live beside the switches. At least one active owner is always kept.
28Admin · resources & media

Photos and PDFs shrink before they upload

  • Photos are resized to 2,000 px and turned into WebP in the browser, which also drops the location data a phone camera writes into a picture. Alt text in each language.
  • PDFs are compressed in the browser by Ghostscript (as WebAssembly, loaded only when a PDF is chosen), with their author and title data removed. A PDF per language, order and show or hide.
  • The server trusts nothing it is sent: it checks the file really is WebP or a PDF, its size and dimensions, refuses PDFs with scripts, and spots duplicates.
Media library, Upload a photo: Before 103 KB PNG at 2400 by 1600; After 12 KB WebP at 2000 by 1333 at 80 percent quality, a quality slider, and the note EXIF and GPS location removed, targets 400 KB for photos and 150 KB for article images
103 KB 12 KB WebP location removed
29Admin · help

The staff guide lives inside the admin

  • Help → User guide in the menu, and a Help button on every screen that opens the right section.
  • Step-by-step for every action, starting with reception’s daily routine and the patient privacy rules for everyone.
  • Each role sees the parts for its own screens.
  • Screenshots of every screen, made from made-up patients by a script that drives the real admin; they are remade whenever a screen changes.
The User guide inside the admin: an introduction saying the guide is for the owner, reception, content editors and translators, that each person sees the parts for the screens their role can open, and that the screenshots show made-up sample patients; then cards for Features, Before you start (signing in, your role, patient privacy rules, finding your way, lists and searching), Reception's daily routine, Appointments, Home visits and Enquiries
30Behind the screens

What runs by itself, through one day (IST)

every 15 minutes: expire unconfirmed requests, send what is due 00030609 1215182124 banner rebuild same-day reminder (optional) patient reminders retention clean-upreport totalsSunday: encrypted backup feedback emails 8 pm: schedule to staff 9 pm:summary any time: staff alerts, a link only

Hatched hours are night. The free plan has five scheduled triggers per account and the site and its preview already use four, so there are just two: every 15 minutes and nightly. The 15-minute job checks the India time itself and runs each daily task once; a record of each run stops duplicates.

31Part 3

Patient data stays private

A clinic holds some of the most sensitive data there is. The rule here is to collect little, lock what is kept, log every look, and delete it on time. Everything in this part is checked by automated tests or by the security review.

patient records secret store
32Privacy · collection

Ask only for what the visit needs

Each form has a fixed list of fields and refuses anything else it is sent, so a field cannot be added by accident, or by someone tampering with the page.

Booking

Name, mobile, an optional email, preferred language, whether WhatsApp is OK, consent.

Home visit

Name, mobile, locality, PIN code, preferred date and time window, visit type, an optional short note, consent.

Enquiry

Name, mobile, topic, message, how to reply, whether a message may be left, consent.

Feedback

A rating, four short answers, an optional comment, stay anonymous or not, may the clinic call back.

Never asked, anywhere
  • Date of birth
  • Street address (taken on the phone for home visits)
  • ID numbers
  • Medical history or reports
  • File uploads of any kind
  • Passwords or accounts

Consent: the box is never ticked in advance. The version of the privacy notice, its language and the time are saved with each request.

33Privacy · storage

Encrypted, field by field

  • Names, phone numbers, emails, notes, comments and message text are encrypted (AES-GCM) before they are saved. The key lives only in Cloudflare’s secret store, never in the code or the database.
  • Each value is sealed together with its place (table, column and row). Copied anywhere else it will not open, and the admin shows “[cannot be decrypted]” rather than the wrong person’s name.
  • The database itself refuses plain text in those columns: a forgotten encryption fails loudly instead of storing a readable name.
  • IP addresses and email addresses used for matching are kept only as salted hashes: enough to count, not to read.
  • Weekly backups are encrypted before they are written.
Asha appointments.name row 7f3c sealed with its place [cannot be decrypted] enquiries.name row 91ab moved, it won’t open
34Privacy · access

Who sees what

Patient data is for the owner and reception only. Editors and translators never see a patient, and the most sensitive text (feedback comments and message text) is the owner’s alone.

  • Lists mask mobile numbers. Mental health and de-addiction visits read “Consultation” in every list.
  • Enquiry topics and feedback comments stay hidden until a record is opened.
  • Opening a patient record is written to the audit log before the data is shown.
  • No bulk export of patient data exists: the only downloads are counts and message metadata.
WhatOwnerReceptionEditorTranslator
Bookings and home visits✓✓——
Enquiries, after opening✓✓——
Feedback ratings and comments✓———
Message log: who, when, which template✓✓——
Message log: the text itself✓———
Audit log✓———
Website content✓—✓own languages
Dashboard counts✓✓content onlycontent only
35Audit trail

Every change and every look, written down

  • Every sign-in, change, opening of a patient record, export and publish writes an audit row: who, when, what, which record, and what changed.
  • The audit row is saved in the same database batch as the change, so a change is never saved without its record.
  • The log is append-only, kept for a year, and only the owner can read it.
  • Each booking and home visit also keeps its own timeline of events, with old and new values encrypted.
The Audit log, owner only, with made-up staff: filters for record, action, who and when, and rows such as editor@example.test updating a media item with its stored size, dimensions and alt text, and reception@example.test viewing the home-visit requests and appointments lists, with the ids of the records listed
saved together, or not at all the change the audit row who, when, what
Your booking lowcostclinics.in/booking/k7Q9xR2vTm lang theme all it keeps
36Privacy · the edges

Nothing in the address bar, the logs or the browser

  • Web addresses carry a random code at most: never a name, a phone number or a condition. Admin searches are posted, so they never land in the address bar or history.
  • Page titles stay generic. The booking page is “Your booking”.
  • The browser keeps two things: the language and light or dark. The booking form holds details in memory only.
  • Server logs hold no request bodies, no decrypted fields and no tokens. Request logging on Cloudflare is switched off, and errors never repeat what was typed.
  • Analytics are cookieless and never run on booking pages; no outside script can read a form.
  • The public site is built from published content only. A test proves the build cannot read a patient table.
37Extra care

Sensitive visits, neutral words

Mental health and de-addiction care need more than encryption: a calendar reminder on a shared phone, or a message on a lock screen, can say too much.

  • “Consultation with Dr. Jyoti Puthran” is the only wording in messages, calendar files, web addresses, done screens and analytics.
  • The WhatsApp message these pages prepare is neutral too.
  • Admin lists say “Consultation”; the visit type shows only inside the record.
  • Patients are asked whether a message may be left and whether WhatsApp is OK, and the answer is honoured: no WhatsApp button without it.

Checked in the browser in Hindi and Marathi during the security review: the done screen, booking page and calendar file all read “Consultation with Dr. Jyoti Puthran”.

Thu, 15 Oct · 10:30 am Consultation with Dr. Jyoti Puthran
38Security

A lock on every door

Public forms
  • Cloudflare Turnstile, the invisible spam check
  • A hidden trap field that only bots fill
  • 5 sends an hour per visitor, counted by a salted hash of the address, never the address
  • A 16 KB size cap and a fixed list of fields
  • An idempotency key, so retries never double-book
The private booking page
  • A long random code in the link; only its hash is stored
  • The last 4 digits of the mobile, 5 tries, then locked for an hour
  • A 30-minute session in a cookie scripts cannot read, sent only to this site
  • Never cached, never indexed, no referrer sent onwards
The admin
  • Cloudflare Access in front; the Worker checks the Access token again (signature, audience, issuer, expiry)
  • The email must belong to an active staff user
  • A role check on every route
  • Forms accepted only from the admin itself
  • A strict content policy, no framing, never cached or indexed

HTTPS only, with HSTS. Secrets live only in Cloudflare’s secret store; the encryption key is shared by the two Workers and nothing else.

12 months visit: Oct 2025 nightly
39Privacy · over time

Kept for a year, backed up weekly, ready for the worst

Retention, every night

Patient records, feedback comments and message text are deleted 12 months after the visit or enquiry; old sessions, rate limits and audit entries go too. When a patient withdraws consent, their enquiry is deleted that night.

Backups, every Sunday

The whole database is encrypted into private storage and kept 12 weeks. A weekly job copies the newest encrypted file outside Cloudflare. Restoring is written down and was tested.

Breaches and requests

A written runbook: tell affected people without delay and report to the Data Protection Board within 72 hours. Data requests are answered within 90 days, aiming for 7.

40Compliance

Built to the medical ethics rules and the data law

The site follows the IMC 2002 ethics regulations (the NMC 2023 conduct rules are on hold) and the DPDP Act 2023 with the DPDP Rules 2025, whose notice, security and breach duties start on 13 May 2027. It is built to them from day one.

Medical ethics (IMC 2002)What the site does
Registration numberOn the doctor page and the footer, with the council
Announce feesThe full fee table, and a fees box on each service page
No self-promotionFactual tone; “best”, “top”, awards and badges are banned, and tests scan every page for them
No testimonialsFeedback stays internal
No cure claims“Manage” or “control”, never “cure”
Photograph, statisticsThe doctor’s photo only with the doctor’s agreement, behind a switch; a diabetes statistic hidden until verified
Data protection (DPDP)Status
Minimal forms, unticked consent, notice version storedMet
Encryption; every staff view loggedMet
Deleted after 12 monthsMet
Contact for data questions; breach runbook; 90-day requestsMet
Privacy notice in all four languagesEnglish done others before their language goes on
Data-processing terms with Cloudflare and the email providerOwner before launch

From the requirements: “This is research, not legal advice; confirm with the Karnataka Medical Council or a healthcare lawyer.”

41Security review · 13 Oct 2026

Every test passed. The review still found five things.

The last build phase read every code path against the privacy rules, ran the release check against a local copy, and tested all four languages in a browser. Five findings, all fixed the same day:

#What was wrongWhat it would have doneThe fix
F1The admin’s site address pointed at the admin itselfEvery booking link in staff messages would have sent patients to the staff sign-in pageCorrected, and a test now compares the two Workers’ settings
F2Cloudflare could keep a log of every requestBooking codes, visitor addresses and the staff sign-in token would sit in logsRequest logs switched off in both Workers; covered by the config test
F3The admin logged raw error messagesSome errors quote what was typed, such as a nameQuoted parts are dropped; a test checks a name never reaches the log
F4Staff alerts were set to send from a Gmail addressEvery staff alert and daily summary would have failed to sendSent from the clinic’s own domain
F5The privacy notice said “write to [TBD]”No published contact for data questionsThe confirmed clinic email is in the notice

F1 and F4 passed every test because tests set their own settings. The lesson went into the log: check the deploy configuration itself, not just the code.

42Part 4

Everyone can use it

Many of the clinic’s patients are older, read best in their own language and use a basic Android phone on a patchy connection. The site was built for them first: large text, big buttons, four languages, and pages that load fast.

English हिंदी ಕನ್ನಡ मराठी
43Accessibility

Large, clear and calm

Built to WCAG 2.2 AA, then checked page by page.

Designed in

  • 18 px body text; contrast of 4.5:1 or more, checked for every status colour in both themes
  • Tap targets of at least 44 px; a thick amber focus ring
  • Every field labelled; icons always with words
  • Plain language; one question per booking step; the number keypad for phone numbers
  • Menus and questions open without JavaScript
  • Light and dark, following the phone or the visitor’s choice

Checked

  • Lighthouse accessibility 100 on the English pages and on 12 admin screens
  • W3C validator: 0 errors on the 21 pages, the booking page and 30 admin screens
  • Every page at 360 px in all four languages: no sideways scrolling
  • A booking made start to finish on a phone in Marathi, a change and a cancel in Hindi
The home page on a phone in light mode: logo, Call and menu buttons, the headline, Book Appointment, Call and WhatsApp buttons, the phone number, and the bottom bar with Call, WhatsApp and Book
Light
The same home page in dark mode: pale text on deep green-black, the primary button in a lighter green
Dark
44Languages

Four languages, one address per page

Englishthe indexed version
हिंदीHindi
ಕನ್ನಡKannada
मराठीMarathi
  • Switched in the header or footer; remembered on the device and kept in shared links (?lang=hi).
  • A language appears in the switcher only when the owner turns it on, once its translations are reviewed.
  • A page without a reviewed translation stays in English, with a short note in the chosen language.
  • Indian-language fonts are served by the site itself and loaded only when that language is chosen. A translated page waits for its text and font before it shows, so nothing jumps.
  • Booking pages, forms, messages, dates and calendar files come out in the patient’s language too.
How it was tested without translators

Every English text was copied into each language with a marker in front, switched on, and built. A browser then opened 20 pages in all four languages at 360 px and flagged any visible text without its marker.

  • हिं·Book an Appointment
  • ಕನ·Book an Appointment
  • मरा·Book an Appointment

Any text that stayed plain English was a string the switcher had missed. The marked copies were deleted afterwards.

45Speed

Fast on a mid-range phone, over 4G

The targets: the main content in under 2.5 seconds, a reply to a tap in under 200 ms, and a layout that doesn’t jump (shift under 0.1).

  • Content pages are plain HTML with no framework, only small scripts for languages, booking and forms. The hero image is 100 KB or less.
  • Lighthouse on its phone profile (slow 4G, a 4× slower processor): English pages score 97–100 for performance.
  • The quality pass found three slow spots and fixed them: the booking page’s footer jumped as the steps appeared; translated pages jumped as text and fonts arrived; and the home page preloaded italic fonts it never used.

Layout shift, before and after the fixes

Lighthouse phone profile; lower is better

00.250.50.751.0 target 0.1 Booking page Translated pages Booking page before: 0.475 Booking page after: 0 0.475 Translated pages before: 0.6 to 0.9 Translated pages after: 0 0.6–0.9 0 after both fixes

Home page, time to main content

Seconds, Lighthouse phone profile; lower is better

0 s1234 s target 2.5 s Home page Before: 3.4 s After: 2.0 to 2.4 s 3.4 2.0–2.4
Show the numbers as a table
MeasureBeforeAfterTarget
Layout shift, booking page0.4750under 0.1
Layout shift, translated pages0.6–0.90under 0.1
Home page, main content3.4 s2.0–2.4 sunder 2.5 s
46Part 5

Under the hood

For developers: how a static Astro site, two Cloudflare Workers, one SQLite database and two storage buckets do all of the above for Rs 0 a month, and how the rules that protect patients are enforced in code and tested.

Workers D1 R2
47Architecture

Two Workers, one database

  • Public pages are static HTML built by Astro from published content. A database outage cannot take them down.
  • The site Worker serves those files and handles only the moving parts: booking and form endpoints, private booking pages, downloads, list views, the email webhook and the scheduled jobs.
  • The admin Worker runs on its own address behind Cloudflare Access and shares the database and file bucket with the site.
  • Publishing marks drafts as published in one database batch, then calls a deploy hook; Workers Builds rebuilds and deploys the pages in 1–3 minutes.

npm workspaces, Node 24, TypeScript throughout: site/, admin/ and shared/ (crypto, booking, messages, backups, the content readers).

visitors clinic staff lowcostclinics.in Cloudflare Access (email code, Google) Site Worker Static pages, built by AstroBooking, forms, private pages, downloadsJobs every 15 minutes and nightlyTurnstile on every form Admin Worker Hono, pages drawn on the serverAccess token checked againA role check on every routeAn audit row with every change Workers Builds publish new pages R2 encrypted backups R2 photos and PDFs D1 SQLite Outside services Resend: patient emailsCloudflare Email: staff alertsGitHub: a weekly copy of the backup
48Stack

Rs 0 a month, without pausing

The brief allowed free plans only, for commercial use, on a service that never sleeps between visits. That ruled out most of the usual choices.

LayerChoiceFree limit (Oct 2026)
SiteAstro, static outputopen source
HostingWorkers + static assetsstatic free; 100k Worker requests a day
PublishingWorkers Builds, deploy hook3,000 build minutes a month
DatabaseD1 (SQLite)5M rows read, 100k written a day
FilesR210 GB, free egress
Admin sign-inCloudflare Access50 users
SpamTurnstile + trap field + limitsfree
Patient emailResend3,000 a month, 100 a day
ConsideredWhy not
Next.js on Vercel Hobby + SupabaseHobby is non-commercial; Supabase Free pauses after 7 quiet days
Netlify Free + SupabaseA monthly credit cap; the site pauses when credits run out
Payload CMS on CloudflareThe best paid upgrade (about $5 a month)
Directus, StrapiNeed an always-on server with no reliable free host
Git-based CMSValues would live in git, not a database

The trade-offs: a custom admin to maintain; one vendor for hosting, data, login and email (weekly off-platform backups cover data loss, not downtime); past the daily database limits, booking and the admin stop until 5:30 am IST while static pages stay up, and the dashboard warns first.

content patients sandbox the website allow-list
49The build

The build cannot see a patient

The public site is built from the same database that holds the patients. So the build never reads that database directly.

  1. Before every build, an allow-list of content tables is copied into an empty, migrated database in memory.
  2. Every reader the pages use runs against that sandbox, which has no patient rows to give.
  3. The build writes the pages, the translation files, the sitemap and structured data, and a content security policy with a hash for every script.

Two tests guard it: the sandbox contains no patient table, and a second test puts patient rows in the source database and checks the built site still has none of them.

50Booking engine

Two bookings never share a quarter-hour

10:0010:1510:3010:45 11:0011:1511:30 booking A: two blocks ✓ booking B this time was just booked: pick another
  • The day is cut into 15-minute blocks. A booking locks every block it needs; the lock table has a unique index on doctor and block start, and every timestamp must sit on a quarter-hour.
  • The booking, its locks and its first event are written in one database batch. If any block is taken the whole batch fails and nothing is saved; the patient is asked to pick another time.
  • An idempotency key means a double tap or a retry returns the same booking.
  • Database triggers free the blocks the moment a booking is declined, cancelled or expires. Staff blocks and scheduled home visits take time the same way.

The test fires three overlapping bookings at the same instant against a real local database: exactly one wins.

51Data model

Three kinds of table, and rules in the schema

Fifteen migrations build one SQLite database. Each table belongs to one of three groups, and only the first is ever exported to the build.

Content · published by the build
  • settings
  • interface strings
  • switches
  • menus
  • doctor
  • qualifications
  • pages
  • FAQs
  • fees
  • hours
  • closures
  • media
  • banners
  • articles
  • resources
  • … and their translations
Patients · never exported
  • enquiries
  • appointments
  • appointment events
  • booking access
  • booking sessions
  • home-visit requests
  • feedback requests
  • feedback
  • admin notes
  • reminders
  • message log
Operations
  • admin users
  • audit log
  • publish jobs
  • rate limits
  • digest settings
  • digest runs
  • download counts
  • daily stats

Checks

Encrypted columns accept only the sealed format; timestamps must fall on a quarter-hour; dates must be real dates.

Triggers

Free a booking’s blocks on cancel; always keep one owner; keep approved template versions; switch off dependants; keep locked menu items; enforce the translation review rule.

Drafts as rows

Each translation has a draft row and a published row; publish swaps them in one batch, so the site never sees half an edit.

52Admin Worker

Six checks before any admin screen

Every request to the admin passes the same middleware, in this order. A screen’s own code only runs after all six.

Secure headers

A content policy allowing only the admin itself, no framing, no referrer, never cached, never indexed.

Same-origin forms

A form post must come from the admin, or it is refused.

Access token

Cloudflare Access’s signed token is verified again: signature, audience, issuer, expiry.

Active staff user

The email must match an active staff user. Each sign-in is audited.

Role check

The route checks the role against the one screen table that also draws the menu.

Audit with the change

Any change, view or export writes its audit row in the same batch.

Errors show a generic page, and quoted input is dropped from what is logged.

On a developer’s own machine only, a set email stands in for Access, and only when the request comes from localhost. A deployed Worker never sees localhost.

53Quality

Tests for the rules that matter

370+
Automated tests
Vitest, each test on a fresh in-memory D1 and R2
536
Release checks pass
of 537; the one left fails on purpose until the clinic’s last answers replace [TBD]
0
Validator errors
on 21 pages, the booking page and 30 admin screens
5
CI steps
lint, typecheck, migrate and seed, build, test

A few of the tests

  • Three bookings for the same time at once: exactly one wins.
  • The public build contains no patient table.
  • Each role opens only its own screens (the role matrix).
  • Every admin response is no-store, noindex and unframeable.
  • Twelve wrong digit guesses at once still lock after five.
  • A quoted name never reaches a log line.
  • No “best”, “top” or “cure” in the seed copy or the built pages.
  • The two Workers’ deploy settings agree with each other.

And by hand, before launch

  • The release check against a running copy: headers, robots, canaries, nothing echoed.
  • A browser sweep of 20 pages × 4 languages at 360 px.
  • Lighthouse on the low-end phone profile.
  • A backup restored into an empty database.
  • The security and privacy review (slide 41), to repeat before launch and every quarter.
54Part 6

Built with Claude

Three Claude tools, each with its own job: Deep Research for the rules and the platform, Claude Design for every screen, and Claude Code for the build, one phase per session. A person made every decision along the way.

Deep Research Claude Design >_ Claude Code
55How it was made

Three tools, three jobs, one set of documents

Each tool handed the next something written down. The three requirement documents sat in the middle: every session began by reading them, and they won every disagreement.

Deep Research

The rules before the code: medical ethics, the data law, free-plan limits, which stacks to avoid.

→ findings in the requirements

Three documents

General Requirements (what), Technical Decisions and Design (how), Database Schema (the tables). About 1,200 lines.

→ the source of truth

Claude Design

Every public page and admin screen as clickable prototypes, with tokens, layouts and copy.

→ 42 files in design/

Claude Code

One build phase per session, against the documents and the design: code, migrations, tests and docs.

→ 19 phases, 10–13 Oct

The result

The website, the admin, the staff guide, a runbook, a deployment guide and a security review.

→ preview live 13 Oct
The developer

Decides

Wrote the brief, answered design-and-document conflicts, reviewed each phase and deployed.

The clinic

Answers

Fees, hours, registration, wording and approvals. Until each answer came, the value stayed [TBD].

Claude

Researches, drafts, builds

Within written rules: stay in the phase, test what protects patients, write down what went wrong.

56Claude Deep Research

The rules, settled before the first line of code

Ethics and law

Which medical ethics code applies (IMC 2002, since the NMC 2023 rules are on hold); what the DPDP Act 2023 and Rules 2025 require and from when (13 May 2027); why “cure” is off limits (Drugs and Magic Remedies Act 1954); and what counts as self-promotion: testimonials, “best”, awards, the doctor’s photograph, a success statistic.

Platforms

Free-plan limits checked in October 2026, the chosen stack weighed against five alternatives (slide 48), and its trade-offs written down.

Duties in practice

72 hours to report a breach to the Data Protection Board, 90 days to answer a data request, data-processing terms with every provider.

The research output itself isn’t kept in the repository; this is what the requirement documents record from it, with their own caveat: “This is research, not legal advice.”

IMC 2002 DPDP 2023 · 2025 free plans
57Claude Design

Every screen designed before it was built

  • A Claude Design project of 42 files: every public page, the booking flow, the private booking page and every admin screen, as clickable prototypes with sample data. One entry file shows them all.
  • Imported into the repository on 10 Oct through the design connector, then mapped screen by screen to the phase that builds it.
  • A read-only reference: its prototype runtime never ships, and its sample values (phone, domain, hours, registration number, fee bands, names) were never copied. Each became [TBD] until the clinic confirmed it.
  • The colours, fonts and spacing in this deck are the design’s own tokens, as the live site uses them.
Paper#f7f3ea
Ink#1d2621
Primary#1f5c47
Amber#f2d38b
Focus#c9822b

Newsreader for headings and prices, Public Sans for text, Noto Sans for Devanagari and Kannada.

Where the design and the documents disagreed

#The design hadDecided
D1A dark-mode toggle stored in the browser, where only the language was allowedThe owner chose the toggle; the browser keeps only the theme choice beside the language
D2Fonts loaded from GoogleFonts served by the site; Indian-language fonts only when chosen
D3Video follow-up bookable onlineBehind the teleconsultation switch, off at launch
D4An optional email in bookingKept: emails are sent only if one is given
D5A shorter enquiry form than the schemaThe design’s fields only, until the clinic decides

The documents win over the design. Each conflict had a default, so no phase waited for an answer.

read build check write down CLAUDE.md, the docs, status, learnings one phase, in scope lint · types · tests · build status.md · learnings.md next phase 8 of 19
58Claude Code

One phase per session, the same loop every time

The build was cut into 19 phases, each sized for one Claude Code session of about five hours. CLAUDE.md set the rules every session followed:

  • Read first: the three documents, the plan, status.md, learnings.md and the phase’s design files.
  • Stay in scope: anything extra goes into the notes for later.
  • Test the rules that matter: every rule that protects patient data, prevents double booking or enforces a role.
  • Finish clean: lint, typecheck, tests and build pass; the status and a learnings entry are written. An unfinished phase is marked In progress and finished first next time.
  • The non-negotiables: no patient data in URLs, logs, titles, browser storage, analytics or errors; encrypted patient fields; a public build that reads only published content; neutral wording; no “cure”, “best” or testimonials.
59Timeline

Four days, nineteen phases

The owner decided on 10 Oct to build everything locally and deploy once, at the end. Phase numbers are in green; deployment and owner requests in amber.

10 Oct

Foundations
  1. 0Documents, plan, design import
  2. 1Foundation and layout
  3. 2Schema and seed data
  4. 3–4Public pages, SEO, four languages
  5. D1Light and dark toggle

11 Oct

Admin and booking
  1. 5Admin foundation, roles, audit
  2. 6Content and publishing
  3. 7Enquiries, encryption, retention
  4. 8Booking engine
  5. 9Patient booking screens
  6. 10Admin bookings

12 Oct

Hardening and features
  1. 11Backups, release checks
  2. 12Home visits
  3. 13Banners and feedback
  4. 14Articles
  5. 15Resources and PDFs
  6. 16Templates and message log

13 Oct

Finish and review
  1. 17Daily messages, reminders
  2. 18Reports dashboard
  3. 19Quality pass, security review, staff guide
  4. →Clinic answers
  5. →Preview deployed

14 Oct

Owner requests
  1. →Logo, sticky header, social links
  2. →ADHD Coaching page
  3. →User guide inside the admin
  4. →Features and technical docs
32k
Lines of code
TypeScript, Astro, CSS and scripts
15
Migrations
370+
Tests
240
Lines of learnings
one entry per session
60learnings.md

What the learnings log caught

Every session ended with an entry: what went wrong or surprised, the fix, and what the next session should do differently. Every session began by reading all of it. A few of its 180 lessons:

Phase 8

Green tests, broken Worker

Exporting one constant from the Worker’s main file passed every test, then the local Worker refused to start.

Fix: a test checks that file exports only the handler
Phase 9

The booking page refused itself

With no referrer sent, browsers post forms with Origin: null. Only the browser check found it.

Fix: trust the browser’s same-site header instead
Phase 13

Hindi is heavier

Each Indian-language letter is 9 characters once encoded, so a 500-letter Hindi comment broke the 4 KB form limit.

Fix: a 16 KB limit for forms with free text
Phase 15

A check that passed nonsense

A database rule meant to accept only real dates accepted 2026-13-01: a comparison with NULL passes.

Fix: compare with IS, not =
Phase 11

The restore that only a restore could test

A unit test passed; the first real restore failed, because rebuilt tables sat in the wrong order.

Fix: restore in foreign-key order, one statement at a time
Phase 11

Fonts nobody used

The home page preloaded italic fonts it never shows, which cost a second on a phone.

Fix: upright styles only; 3.4 s became 2.0–2.4 s
Phase 19

Logs that remember too much

Cloudflare’s request logs would have kept booking codes and visitor addresses.

Fix: request logs off, and a test reads the config
Phase 19

A rule that caught its own disclaimer

The banned-word check failed on “do my best” and “cannot be guaranteed” in supplied copy.

Fix: reword the copy, keep the rule
Phases 7 to 19

The heredoc, again

Shell heredocs mangled or hung edit scripts in five separate sessions, and each time the log said so.

Fix: write the script to a file first. Eventually.
61Lessons

What made it work

  1. Documents first, and they win. Three requirement documents written before any code; every session read them, and the design yielded to them.
  2. One phase per session. Small enough to finish, test and write down in one sitting; anything extra went into the notes.
  3. Tests for the rules, not for a number. Double booking, patient data and roles were tested hard; the rest by the release check and a browser.
  4. A log the next session reads. Most surprises happened once, because the next session knew about them.
  1. [TBD] instead of a guess. No invented phone, fee or registration number; the release check fails until the clinic answers.
  2. Decisions with defaults. Every open question had a default (decisions D1 to D32), so no phase waited.
  3. Build locally, deploy once. Nineteen phases ran on one machine against a local database; the preview went up once, at the end.
  4. A review after the tests. The security review found five problems the tests could not see, because tests set their own configuration.
62Where it stands · 14 Oct 2026

Built, checked, and nearly open

Done All 19 phases built and checked; the preview is live at preview.lowcostclinics.in with its admin.

Before launch

  • The domain’s DNS, the admin’s Access application with the staff list, Turnstile and the sending domain for email
  • Data-processing terms accepted with Cloudflare and Resend
  • The clinic’s last answers, so no [TBD] is left
  • Reviewed Hindi, Kannada and Marathi texts, then each language switched on
  • The release check against production, an uptime monitor, Search Console

For the clinic team

The staff guide is inside the admin (Help → User guide). The features list, technical details, runbook, deployment guide and security review live with the code.

Low Cost Clinic Open thank you