Freelance, lab chemist · Solo developer · 2026, prototype, not shipped
QC Chart AI
Control charts and Westgard rules for lab QC data. The rule math runs first, and Claude only gets called when something is actually wrong. It never shipped past prototype. The architecture didn't do anything wrong.
- Next.js
- Recharts
- Neon Postgres
- Drizzle
- Claude API
- QC data entry326 real entries seeded
Seeded from the lab's own charts and spreadsheets, so the first demo showed their numbers.
- Westgard rulesa pure function
Takes recoveries and a baseline, and returns violations with a severity and the exact points that triggered them. No database, no network, no AI.
- Postgresbaselines locked
Mean and standard deviation are locked per analyte and QC type, so the goalposts can't move after the fact. Violations and corrective actions are their own records.
- Claudeonly on a violation
Explains the violation and walks through the corrective action. It only sees the analyte, recoveries, dates, mean and standard deviation. No names, no sample IDs.
- Alerts + actionsemail and in-app
Critical, warning and info levels, with every corrective action logged.
- Sheet
- 1 of 1 · QC Chart AI
- Client
- Freelance, lab chemist
- Role · period
- Solo developer · 2026, prototype, not shipped
- Stack
- Next.js · Recharts · Neon Postgres · Drizzle
- Status
- Prototype, not shipped
The product
A web app for lab chemists. Enter QC data and it plots Levey-Jennings control charts, runs Westgard rules on every entry, and sends an alert when something drifts out of control. Basically a smoke detector for lab results.
How it's built
- Data model first. Analytes (copper, zinc, phosphate), QC types (blank spikes, matrix spikes and their duplicates), and baselines with a mean and standard deviation that are locked per analyte and QC type, so the goalposts can't move after the fact. Runs are grouped into sessions with their batch checks. Every violation and every corrective action is its own record, because in a lab "we fixed it" only counts if it's written down.
- Rules as a pure function. The Westgard engine takes recovery values and a baseline and returns violations with a severity and the exact points that triggered them: 1-3S is critical, 2-2S and 4-1S are warnings, and the 7-point and 10-point runs on one side of the mean are early signs. No database, no network, no AI, so it's easy to test and easy to trust.
- Real data from day one. I seeded the prototype with 326 QC entries from the lab's own charts and spreadsheets, so the first demo showed their numbers, not lorem ipsum with error bars.
- Stack: Next.js, TypeScript, shadcn/ui with Recharts, Drizzle on Postgres, NextAuth, the Claude API and Resend.
How the AI is used
The rule math runs first, because statistics doesn't need a language model to know that a number is three standard deviations off. Claude is only called when there is a violation, to explain what happened and walk the chemist through the corrective action. Cheaper, faster, and no AI confidently explaining a problem that doesn't exist.
The model gets as little as possible: the analyte name, the recovery values, the dates, and the baseline's mean and standard deviation. No analyst names, no sample IDs, no lab name. When the client asked about data privacy, the answer fit in one paragraph, and that's because of the design. The ownership model matched it too: the lab would get the code, its own database, its own Anthropic API key and its own hosting, with no access left on our side.
What happened
I scoped it for accredited private testing labs in the Philippines, priced well below the usual lab software. It stopped at the prototype stage and never shipped. The charts were in control. The launch timeline was not. It stays here because the idea still holds up: use the boring, correct math first and save the AI for the part that needs words.