Product Hunt launch weekSave 30% on every licence7d 11h 49m 00s left

Next.js 15 · React 19 · Supabase · TypeScript

A clinic management system where the safety rules are tested.

Appointments, consultations, prescribing, laboratory, pharmacy, billing and a patient portal. 6 roles, 53 screens, 61 tables. The parts that can hurt somebody are pure modules with 343 tests around them, and the permissions are proven against real Postgres rather than asserted in a README.

Open the live demoSee pricingNo sign-up. Switch between all 6 roles inside the demo.
The consultation workspace: an allergy banner, a SOAP note in draft, the problem list with ICD-10 codes, and what was issued during the visit.
343
Unit tests

Scheduling, dosing, money, triage

200
RLS assertions

Run against real Postgres

15
Money parity checks

Screen totals match the database

134
Row level policies

Across 61 tables

Most clinic templates are screens. This one is mostly the reasoning underneath them.

11 pure, dependency-free modules hold the decisions that matter. They have no database, no framework and no network, so they can be read in one sitting and tested directly. Every one of them is the answer to something that goes wrong in real clinics.

Drug allergy checking

Catches amoxicillin prescribed to a penicillin-allergic patient, which a name comparison misses entirely. It warns and demands a written reason; it never blocks, because software that refuses gets worked around.

Result flagging

Picks the reference range by sex and age before comparing, so 13 g/dL of haemoglobin is normal for a woman and low for a man. Critical beats abnormal. No range on file means no flag rather than a guess.

Invoice arithmetic

Ported from the generated columns and triggers, then proven against the real migrations in Postgres. It found a schema bug where an insurance-settled invoice stayed unpaid forever.

Batch dispensing

Picks first-expiry-first-out, not first-in-first-out, and flags a batch that expires partway through a 30-day course. Nothing else in a clinic system knows both those facts at once.

Scheduling

Slot generation in the clinic's own timezone, tested through daylight saving in both directions, because an appointment that moves an hour twice a year is a patient who missed it.

Statistics

Medians with a 90th percentile rather than means, and any rate built on fewer than ten observations refuses to print a percentage instead of publishing noise a manager will act on.

Pharmacy

The warning names the reason, not just the risk.

  • A class match, not a name match, amoxicillin and penicillin share no letters, so a string comparison misses it entirely.
  • It asks rather than refuses, the pharmacist can go ahead with a written reason, which is stored on the dispense.
  • The batch is picked by expiry, not by arrival, and the server picks again at the counter rather than trusting the page.
  • Stock is never written directly, every change is a ledger row, so a batch and its history cannot disagree.
Dispensing amoxicillin to a penicillin-allergic patient. A red panel explains that amoxicillin is a penicillin and asks for a written reason, and the batch below it was picked by expiry date.

Analytics

Every percentage arrives with its denominator.

  • No bare percentages, 90% always appears as 90% (735 of 818), because the first is an opinion and the second is a fact.
  • Under ten observations it will not give a figure, it says there are too few to judge, and means it.
  • Medians with a 90th percentile, a mean waiting time hides the afternoon that went wrong.
  • Empty days stay in the series, dropping them turns a quiet week into a flattering line.
The analytics screen over 30 days. Attendance reads 90 percent with 735 of 818 expected shown beside it, and the money chart keeps its empty days.

Front desk

A day that survives daylight saving.

  • Arithmetic in the clinic's timezone, never the viewer's, tested through the clock going forward and back.
  • Walk-ins and appointments in one queue, because that is how a waiting room actually works.
  • Waiting time is measured, not estimated, from the moment of arrival, and it is on the screen for the person who can act on it.
  • Cancellations are excluded from no-shows, a patient who rang ahead is not the same as one who did not turn up.
The reception queue: who has arrived, who is waiting, how long they have been waiting and who they are waiting for.

The assistant

Half of the AI features deliberately use no AI.

A patient asking what a haemoglobin of 9.1 means wants what the test measures, where their number sits, and what happens next. All three are already in the record. A language model adds nothing and risks the one thing that matters most: producing a number the record does not contain, fluently. So the result explainer is a curated glossary and a template, and a test asserts that no figure can appear in an explanation that was not in the result row.

Symptom triage is an explicit rule table a clinician can read and correct. It answers how soon somebody should be seen, which is routing rather than diagnosis, and a test walks every rule to prove none of them names a condition. Red flags cannot be talked down: chest pain reported as one out of ten is still an emergency.

Only note drafting uses a model, and it is fenced on both sides. Identifiers are stripped on the way out. On the way back, every number in the draft is checked against the transcript, because an invented dose reads exactly like a real one.

What that buys the buyer

  • Two of the four features cost nothing to run and cannot hallucinate.
  • With no API key set, the product still works. Drafting says so plainly instead of failing.
  • Every run is recorded with its model, its latency and whether a clinician accepted it.
  • Nothing generated becomes part of a record until a person signs it. There is no button that skips that.
The patient assistant explaining a blood count in plain language, with each number copied from the result rather than generated, and a note that it is not a diagnosis.

Six roles. Six different products.

The navigation, the data and the permissions all change with who is signed in. Open the demo and switch role from the bar at the top; it is the fastest way to see how much is here.

The day calendar with a column per clinician.

Reception

Arrivals, walk-ins, the queue, payments and the day's schedule.

The patient register.

Consulting room

SOAP notes with a sign-and-lock flow, ICD-10 diagnoses, prescribing with allergy checks.

The laboratory worklist.

Laboratory

Bench worklist, chain of custody, result entry flagged live, approve then release.

Pharmacy inventory with batches and expiry dates.

Pharmacy

Dispensing by expiry, batches, the stock ledger, purchase orders and suppliers.

The invoice list with balances.

Billing

Invoices, payments, refunds, insurance claims and day-end reconciliation.

The patient portal home.

Patient portal

Appointments, results in plain language, medication, bills and the assistant.

Permissions

Hiding something in the interface is not a permission.

Three independent layers, none of them trusted to be the only one: middleware gates navigation, pages re-check the role next to the data, and row level security decides what the database will return. All 61 tables have RLS enabled and at least one policy.

You can run the proof yourself with npm run db:test. It applies all 13 migrations to Postgres compiled to WASM and impersonates each role in turn. No Docker, no Supabase project, about twenty seconds.

A few of the 200 assertions

  • Reception sees demographics and money, and no clinical note.
  • A patient sees a lab result only once it is approved and separately released.
  • Signing a note makes it immutable; corrections are amendments.
  • Nobody can promote themselves. Only an administrator changes a role.
  • A clinician cannot file a note under a colleague’s name.
  • The stock ledger and the audit log are append-only.
  • A refund cannot exceed what was paid.

Buy it once. It is yours.

The complete source, the migrations, the test suites and the setup guide. No subscription, no hosted dependency on us, nothing phoning home.

Single licence

One clinic, one deployment. Yours to modify and run.

$349$499Save $150
  • The complete source, all 10 phases
  • Use in one commercial project
  • 12 months of updates
  • The full test suite and the migrations
  • Deployment and Supabase setup guide
Ask about the single licence

Unlimited licence

Every project you build, including work you deliver to clients.

Most bought
$699$999Save $300
  • Everything in the single licence
  • Unlimited commercial projects
  • Use in client work you are paid for
  • Lifetime updates
  • Priority email support
Ask about the unlimited licence

Launch pricing runs until Fri, 07 Aug 2026 23:59:59 GMT. After that both licences return to $499 and $999. The timer at the top of this page counts to that instant and the prices change when it reaches it.

Before you buy

What this is not, and what is still yours to do.

Written plainly, because you will find all of it in the first hour and it is cheaper for both of us if you find it now.

Regulatory compliance is yours

If real patient records go into your deployment, HIPAA, GDPR or your local equivalent applies to you, not to this repository. That means a data processing agreement with your host, a retention policy, and a security review. The audit log, the RLS and the encryption in transit are groundwork, not a certification.

It has not been used on real patients

It is a complete, carefully built system with a large test suite. It has not run a clinic. Anything clinical, especially the triage rule table and the drug class list, should be reviewed by a practising clinician before it touches a real person.

Database types need one command

`src/types/database.ts` is a hand-written stand-in covering seven of 61 tables, so services query through a deliberately untyped client. One supabase gen types run against your project makes the whole service layer type-safe.

Some things are scaffolded, not finished

Purchase orders can be received but not raised. Voice-to-text is not built. There is no analytics export, no online patient payments, and medication reminders have their tables but no delivery. The README lists every gap by name.

The demo is the whole product. Go and break it.

Every screen, every role, real fixtures. Nothing is saved and nothing is hidden behind a form.

A clinic management system where the safety rules are tested