smooth-app
A collaborative, free and open database of ingredients, nutrition facts and information on food products from around the world
Upload a medical bill and check it for duplicate charges, unbundled procedures and prices far above Medicare. Free, with a letter you can take to the billing office.
HealthTypeScript · PLpgSQLGitHub @xK3ROOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Unbundle audits medical bills. You upload a photo or PDF of a bill, it reads the line items, runs fixed, tested checks against public Medicare data, and tells you what is worth asking about in plain English or Spanish. You leave with a report and a letter you can take to the billing office.
Demo: <DEMO LINK PLACEHOLDER> (the sample bill needs no sign-in)
Medical bills are hard to read and harder to check. Duplicate lines, services billed separately that should be billed together, and prices far above what Medicare pays all look the same to someone holding a bill with no way to verify it. Most people pay, or give up, because they cannot tell what is worth disputing and do not know what to say.
The AI only reads the bill into structured data. It never decides what is wrong. Every finding comes from deterministic code in src/lib/rules, and the wording of each finding comes from fixed templates (English and Spanish). The AI has one other job: when you tap "What is this?" on a line, it defines that single billing code in general terms. Only the code is sent for that, never your name, dates or amounts.
flowchart LR
A[Photo or PDF of bill] --> B[Resized in the browser]
B --> C[AI reads the bill<br/>into line items]
C --> D{Zod validation}
D -- invalid --> X[Rejected or flagged,<br/>never guessed]
D -- valid --> E[You review and correct<br/>the bill's line items]
E --> F[Deterministic rules<br/>+ public CMS data]
F --> G[Findings]
G --> I[Report and dispute letter from<br/>fixed templates, English or Spanish]
E -. tap What is this? .-> J[AI defines one<br/>billing code]
Why this split matters: model output is validated against a schema, you can review and correct the bill's line items before the report is produced, and the rules are plain functions with unit tests. Amounts read from an optional EOB are used by two rules but are not shown for editing, so those two findings rest on an unreviewed reading. The same bill and the same data always produce the same findings, with no randomness, no clock and no network access.
Ten checks: nine rules that look at the bill, plus an optional Good Faith Estimate comparison for people without insurance. Seven of the nine rules run on every bill. Two (denied, then billed; and balance billing) run only when an EOB is uploaded. The financial assistance estimate is a separate optional step, not a check of the bill.
| Check | What it looks for |
|---|---|
| Duplicate charges | The same service billed more than once on the same day |
| Math errors | Units times price that does not match the amount charged |
| Wrong dates | Charges dated outside the dates of service |
| Unbundling | Services Medicare's NCCI edits say should not be billed together |
| Quantity limits | More units than Medicare's medically unlikely edits (MUE) allow |
| Price outliers | Prices more than 5x the Medicare rate for the same service |
| Vague charges | Lump-sum or unlabeled charges |
| Denied, then billed (needs an EOB) | Lines the insurer denied that were still billed in full |
| Balance billing (needs an EOB) | Bill asks you to pay more than the EOB says you owe for the same service |
| Good Faith Estimate (optional) | Compares an uninsured patient's estimate with the final bill |
| Financial assistance estimate (optional) | Compares household income with HHS poverty guidelines to estimate whether free or discounted care at a California hospital may apply |
Findings are things worth asking about, not certain mistakes.
Each rule was run against the fixture bills and compared with the findings expected for them (npm run accuracy, source src/lib/accuracy/accuracy.json, full method in docs/accuracy.md).
| Rule | TP | FP | FN | Precision | Recall |
|---|---|---|---|---|---|
| duplicate_charge | 1 | 0 | 0 | 100% | 100% |
| math_error | 1 | 0 | 0 | 100% | 100% |
| date_mismatch | 1 | 0 | 0 | 100% | 100% |
| ncci_unbundling | 2 | 0 | 0 | 100% | 100% |
| mue_exceeded | 1 | 0 | 0 | 100% | 100% |
| price_outlier | 1 | 0 | 0 | 100% | 100% |
| vague_charge | 1 | 0 | 0 | 100% | 100% |
| denied_billed_in_full | 1 | 0 | 0 | 100% | 100% |
| balance_billing | 1 | 0 | 0 | 100% | 100% |
| overall | 10 | 0 | 0 | 100% | 100% |
Read this honestly. These numbers come from 16 synthetic fixture bills that I wrote alongside the rules, 6 of them (4 traps and 2 clean bills) designed to catch false alarms. They show the rules behave as designed. They are not a measure of real-world accuracy: every rule has only one or two true cases, and real bills are messier. A finding must match on rule, line item IDs and amount at stake to count as correct. The reading step (AI extraction) is not part of this table.
All reference data is public and loaded into Postgres as read-only tables.
| Data | Source | Release |
|---|---|---|
| NCCI procedure-to-procedure edits (practitioner) | CMS | 2026 Q4 |
| NCCI medically unlikely edits (MUE) | CMS | 2026 Q4 |
| Medicare Physician Fee Schedule relative values and GPCI | CMS | RVU26A |
| Poverty guidelines | HHS | 2026 |
This summary matches the in-app /privacy page.
NEXT_LOCALE, "en" or "es", one year) only if you choose a language; session cookies from Supabase when you sign in; and your Light or Dark choice in localStorage under unbundle-theme. There are no analytics, advertising or tracking cookies.Next.js (App Router) and TypeScript, Tailwind and shadcn/ui, Supabase (Google auth, Postgres with row-level security, storage), the Anthropic SDK (extraction and explanations only), Zod at every external boundary, next-intl (English and Spanish), @react-pdf/renderer for the report and letter, Vitest for tests.
Requirements: Node 20+, a Supabase project, an Anthropic API key (optional in mock mode).
npm install
# create .env.local; see docs/DEPLOY.md for the full list of variables
npm run dev
EXTRACTION_MODE unset the app uses a mock extractor, so the sample bill and the whole flow work without an Anthropic key. Set EXTRACTION_MODE=anthropic with ANTHROPIC_API_KEY for real extraction.supabase/migrations/0001 to 0005 in order (0006, typed-in bills, is a draft until docs/manual-entry-test.md has been run), then import reference data with node scripts/import-reference.mjs and node scripts/import-poverty.mjs --confirm (needs the service role key locally). In production the service role key is set in exactly one place, for account deletion (src/lib/account/admin.ts); see docs/DEPLOY.md.Useful commands:
| Command | What it does |
|---|---|
npm run dev / npm run build | Run or build the app |
npm test | Unit and component tests (Vitest) |
npm run lint and npx tsc --noEmit | Lint and type check |
npm run accuracy | Regenerate the accuracy table (needs .env.local) |
npm run check:contrast | Colour contrast guard |
npm run test:e2e | Browser smoke test of the signed-out demo flow (see docs/e2e.md) |