WellForm MD
A physician-led weight loss and wellness clinic in Ankeny, Iowa, serving patients in the clinic and by telehealth across a set of licensed states.

What they came with
A treatment catalogue here has to answer two questions at once: what the treatment is, and whether you can have it where you live. The same medication programme is priced one way in the Ankeny clinic and another way over telehealth, and the brand names patients actually search for are not the names the clinic organises its care around. Underneath that sits long-form clinical education that a patient reads before booking rather than after, which means it has to be versioned and re-reviewed as evidence moves. A page tree alone will not hold any of it.
What the build had to do
Two taxonomies over one catalogue
Every treatment record carries a clinical focus category and a care-centre hub, with a field for additional hubs on top. That lets one canonical document surface under weight loss and under the medical spa at once, so placement can vary without the page's own URL moving or the content being duplicated.
Books modelled as ordered chapters
The library treats a book and its chapters as separate records joined by a relationship and an order field, each chapter holding its own reading time and an optional closing call to action that can be switched off. Books also carry distinct slots for a cover form, a mid-book form and a brief request, plus a version and a disclaimer, so the conversion moment and the review state are part of the content model rather than bolted onto a template.
Pricing that carries delivery mode
The price list groups programmes by care centre and sets the in-clinic and virtual variants of the same programme next to each other, with dose bands inside each. That comparison is the point: a patient choosing between visiting Ankeny and being seen remotely is choosing a price as well as a place, and hiding one behind the other would move the decision off the page.
Service area as a first-class page
A state map splits the country into currently served, in process and not currently served, with a picker beside it and a chip list for people who would rather read the names. It puts eligibility ahead of persuasion, so a visitor establishes whether care reaches them before reading about the treatment itself.
Patient media under its own rules
The media library classifies each asset by class, separating patient imagery from general marketing imagery, and holds focal points, a service-page role and a spread of generated sizes. Keeping consented patient material in its own class is what stops it drifting into ordinary marketing use later.
Technical detail
Nested pages, materialised path
Pages hold a parent reference alongside a denormalised full path, so a catch-all route resolves an address like /medical-spa-ankeny-iowa/ with a single indexed lookup instead of walking ancestors on every request. The cost is that renaming a slug has to rewrite the stored paths of everything beneath it, which is why a redirects collection sits directly alongside the page tree.
Publication gated by a review contract
Service documents carry a review record covering how the content is classified medically, whether it is governed, which reviewer key signed it, what evidence keys it rests on, when it is next due and whether it has decayed. A second page contract sits beside the live one holding a contract version, QA state, review state and release readiness with an explicit list of blocking reasons and its own enabled flag, so a new page shape can be prepared per treatment and switched on document by document. Publishing is a state machine rather than a toggle, which is the right shape for clinical copy.
Strict CSP paid for in dynamic rendering
Every response carries a fresh script nonce with strict-dynamic and a tightly enumerated source list, which rules out handing one cached HTML document to every visitor. Pages render per request behind Vercel and media is served through a first-party API route backed by Supabase Storage in pre-generated sizes. The trade is deliberate: script-injection protection on a site that takes patient enquiries, bought with origin work rather than edge cache hits.
The stack
Application
Content
Data and media
Front end and measurement
- Sector
- Medical weight loss, wellness
- Audience
- Ankeny and telehealth patients
- Shape
- Catalogue, library and booking
- Platform
- Next.js and Payload on Vercel



Something like this to build?
Tell us what runs today and where it hurts. An engineer reads it and replies.