smooth-app
전 세계 식품의 성분·영양·정보를 자유롭게 협업하고 공개하는 데이터베이스
Better-bill
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Your billing advocate for hospital bills. Snap a photo of the bill. BetterBill reads every line, shows what looks wrong with the proof behind it, checks if you qualify for free or cheaper care, drafts the letter and the call, and acts only after you approve.
Built in 24 hours at LA Hacks 2026. Free to check. Live app · Demo video · Try the sample bill
▶ Watch the trailer on Vimeo (2:56) · download the MP4
All bills in this repo and the demo are synthetic. Hospital prices, policies and laws are real public sources, captured with dates and hashes. BetterBill is informational, not legal or medical advice.
| Source | ||
|---|---|---|
| 6 in 10 | adults with health care debt cut back on food, clothing and basic household items (63%)14 | KFF Health Care Debt Survey, Jun 16, 2022 |
| $220 billion | at least this much medical debt is owed by people in the U.S.20 | Peterson-KFF Health System Tracker, Feb 12, 2024 |
| 45% | "Close to half (45%) of insured adults ages 19 to 64 got a medical bill in the past year they thought insurance should have covered."4 | Commonwealth Fund Health Care Affordability Survey 2023 (n = 5,602), published Aug 1, 2024 |
| Up to 80% | of medical bills contain errors, billing advocates estimate. The AMA put it at 7.1% of paid claims in 2013.5 | CNBC, Mar 27, 2016 (republished by NBC News) |
Checking a bill takes knowledge of codes, unit limits, price files, charity care law and the patience to call. BetterBill does that work and shows its work.
| Step | What happens | Built with |
|---|---|---|
| 1. Snap | Photo (up to 3 pages) or pasted text. The model only transcribes. It never does math. | StepFun step-5-preview, deterministic text parser, Gemini cleanup |
| 2. Confirm | "Did we read your bill right?" then "Did you get all of these?" You fix misreads and mark services you never got. | Web and native confirm flows |
| 3. Proof | A deterministic rules engine checks duplicates, units against CMS limits3[^mue], bill vs EOB, the hospital's own published price, missing itemization and "not received". Every flag carries an evidence tier and a source. | packages/core (pure TypeScript, unit tested) |
| 4. Help paying | Screens 8 checks: the hospital's assistance policy, state charity care law (9 jurisdictions)2, 12, 16, 18, 19, 24[^states], collection limits, 501(r)11, 13, 15, 17[^fed], No Surprises Act11, 13, 15, 17[^fed], Medicare itemized rights11, 13, 15, 17[^fed], insurance applied, income vs 2026 poverty guidelines1[^fpl]. If the policy is not on file, a Browser Use agent finds it live. | packages/core/src/assistance, Browser Use |
| 5. Act | Gemini drafts the letter. The call has a goal and a script. You approve once, and the approval is saved with a hash of the exact text. Then email goes out and the advocate calls billing. | Gemini, Photon, ElevenLabs |
| 6. Follow | Case timeline, evidence packet you can share with family, a lawyer or a doctor, and "What we did for you". |
Evidence tiers, shown with an icon and a label on every amount: Confirmed from your bill, Billing rule, Hospital's published price, Estimate, You told us.
Measured, not promised. Every number comes from a file in this repo, with the date it was run.
| Result | What it means | Source |
|---|---|---|
| 22 of 22 | seeded errors caught on 11 synthetic bills (duplicate 4/4, units 5/5, bill vs EOB 2/2, published price 10/10, missing itemization 1/1) | data/eval/results.json, run 2026-10-18 03:35 UTC |
| 0 | false flags on the 3 clean bills | same |
| 22 / 22 | precision: every flag raised was a planted error | same |
| 0.012 ms | audit time, p50 (20 runs per bill) | same |
| 88.8% | line recall on 35 phone photos of printed synthetic bills (flat, angled, crumpled, dim, dim and angled); 28 of 35 read perfectly | data/eval/extraction.json, Oct 17, 2026 |
| 26.2 s | photo to lines, p50 (p90 58.3 s), live step-5-preview | same |
| $1,916.85 | less than billed on the $12,000 sample bill SB-01: $1,756.85 MRI above Cedars-Sinai's published cash price21, 22[^cedars], $84.00 duplicate blood count, $76.00 extra blood draws | audit.run on SB-01; price from capture.json |
| 1 of 3 | in-scope reporter findings caught on 5 recreated KFF Health News "Bill of the Month" cases6 to 10[^botm] (1 of 13 overall; the rest are outside what a bill checker can see) | , |
Honest limits: the team planted the seeded errors, so 22 of 22 shows the rules work as designed, not real-world accuracy. The Bill of the Month number shows what we miss. There is no ground truth for who qualifies for assistance; the hospital decides, so every assistance result is labelled an estimate.
| What it asks | What we built | Where we go further |
|---|---|---|
| A real problem, a working product, a measured result | End to end bill check on web and phone: photo in, proof, assistance, letter, live call, shareable packet1 | We publish our misses (Bill of the Month 1 of 3) and keep every claim sourced |
"Not verified live" means the code and tests exist but this README does not claim a live run.
| Challenge | What it asks | What we built | Where we go further |
|---|---|---|---|
| StepFun | step-5-preview at runtime; reliability; user understanding and control | Bill photo reader with per-line confidence and a total reconciliation check; patient confirms or fixes every line2 | Measured across 5 photo conditions; saved readings (cache_first) keep the demo working if the model is slow; reconciliation caught 4 of 7 imperfect reads |
| Sentry | Tracing, Logs, AI agent monitoring | Browser to server traces, orpc.* and hero-path spans, structured logs, Session Replay, browser profiling, gen_ai spans for StepFun and Gemini grouped by case3 | No bill text, prompts, images or model output on any span, and a test proves it (aiSpan.test.ts); replay blocks bill content |
| Browser Use | An agent on real public pages, structured output, used in the product | Captured Cedars-Sinai and UCLA price files and assistance policies; in-app live lookup of a missing hospital policy, with a view-only "Watch the agent" link4 | Agent quotes are kept only if they appear word for word in the downloaded PDF (11 kept, 4 dropped for UCLA); the found policy feeds the screener right away |
| Photon | Use Photon to reach people | Approved letters go out through the Photon email API; calls ride a Photon SIP trunk imported into ElevenLabs5 | Stable idempotency keys on retries; sends only to an allowlist, only after approval. Live calls over the Photon line verified; email inbox delivery not verified live |
All web captures are from the latest main (sample bill SB-01, synthetic) at 390 x 844 and 1440 x 900.
| Landing | Check a bill | Confirm lines | Results |
|---|---|---|---|
| Evidence | Approval | Activity | Evidence packet |
|---|---|---|---|
| Packet: help paying | For plans |
|---|---|
| Landing | Results, full insights |
|---|---|
| Check a bill | Confirm lines |
|---|---|
| Evidence | Approval |
|---|---|
| Activity | Evidence packet |
|---|---|
| For plans |
|---|
Captured in Expo web at 390 x 844 from the latest main against a local API.
| Scan | Did we read it right? | Did you get these? | Results |
|---|---|---|---|
| Flag detail | Bills (home) | What we did for you |
|---|---|---|
Free or cheaper care (from #96 and #99):
| Free care card | Questions | Live rule checklist | Result |
|---|---|---|---|
| Share sheet | Policy lookup running | Lookup steps | Policy found |
|---|---|---|---|
/for-plans lander with a claim review console, measured results, and bulk checkout (#37, #70, #90).| Decision | Why |
|---|---|
The model only transcribes; a deterministic rules engine in pure packages/core computes every flag and dollar | Money must be reproducible and testable, never guessed by a model (#12, #53) |
| An evidence tier and a source on every amount | Patients and billing offices can check each claim themselves |
| Ask, don't accuse | CMS allows up to 4 blood counts a day3[^mue], so a repeat line is a question for billing, not a verdict. bun run copy:check flags banned wording |
| An explicit approval event, with a hash of the exact draft, before any email or call | Nothing goes out that the patient did not read; a call is refused if its script no longer matches the approved one (#47, #49, #79) |
| Synthetic bills only; real public prices, policies and laws | No patient data at a hackathon, but real evidence for every comparison |
Saved photo readings with cache_first | Live reads took 10 to 66 s and timed out under load; a labelled saved reading keeps the demo honest and fast (#58, #82) |
| No bill content in Sentry | Traces show timing and outcomes, never bill text, prompts, images or letters, and a test enforces it (#68, #69) |
| Anonymous audit, account to act | Value before sign-up; approving, sending and calling can require an account (BB_REQUIRE_ACCOUNT) (#60) |
| The shared packet is redacted | Found in review: a share link exposed ids and a recipient. Now ids are replaced, recipients masked, unapproved drafts and income left out (#78, #97) |
| Shared database changes only through CI migrations | Nobody runs db:push against Tiger Data; CI applies committed migrations on main |
| Fee only on confirmed savings | We never charge on an estimate (#70) |
| Agent quotes must match the source word for word | A browser agent can misquote; we keep a limit only when a verbatim quote states it (#98) |
| Expo SDK 57, not 58 | The store build of Expo Go only ran SDK 57, so the app opens on any phone without a custom build (#66) |
main: reading, confirm, rules, savings, assistance screener, live policy lookup, letters, approval, packet, Polar sandbox checkout, Sentry wiring, web and native apps.DEMO_CALL_SCRIPT in use-call-flow.ts); no number is dialled. The call audio in the demo video is an ElevenLabs text-to-speech stand-in.payments.ts; demo values)./for-plans. Polar runs in sandbox; there is no revenue yet.apps/web TanStack Start: routes, UI, /api/rpc (oRPC), /api/v1 (OpenAPI adapter), /api/auth
apps/native Expo Router phone app (same API and auth)
packages/core Pure TypeScript: schemas, reader output parsing, rules, savings, assistance screener, letters, call script
packages/api Thin oRPC routers; StepFun, Gemini, Photon, ElevenLabs, Browser Use, Polar clients; Sentry spans
packages/db Drizzle schema, migrations, seed
packages/ui shadcn components plus BetterBill components (Money, TierBadge, EvidenceSheet, ApprovalSheet, ...)
data/ Synthetic bills, Bill of the Month cases, hospital captures, regulations, eval results, wording rules
Rules for contributors: business logic in packages/core, thin routers, money in integer cents, no keys in client code. See AGENTS.md and docs/plans/00-shared-context.md.
Needs Bun 1.3.12+ and Docker. Python 3.11 and uv only for the capture scripts.
bun install
cp .env.example apps/web/.env # set BETTER_AUTH_SECRET (32+ chars); never commit this file
docker compose up -d db # local Postgres (host port 5434 via docker-compose.override.yml; match DATABASE_URL)
bun run db:push # local database only, never a shared one
bun run db:seed
bun run dev # web app on http://localhost:3001
BB_READER_MODE=cache_only never calls a model.EMAIL_ALLOWLIST or CALL_ALLOWLIST lists the recipient. BB_FAKE_PROVIDERS=1 is for tests..env.example and apps/web/.env.schema. Native app: apps/native/README.md.| Command | What it does |
|---|---|
bun run test / bun run test:integration | Unit tests / integration tests against Postgres |
bun run check-types, bun x biome ci . | Types, lint and format |
bun run e2e | Playwright specs on a phone and a desktop viewport |
bun run eval:all, bun run eval:assistance | Rebuild data/eval/results.json and assistance.json (docs/EVAL.md) |
bun run copy:check, bun run data:check | Wording rules; bundled data matches data/ |
Deploy: Vercel (bun run deploy, env sync with bun run env:preview or env:production). CI on every PR runs Biome, types, unit and integration tests and the build, with BB_READER_MODE=cache_only. On main, CI applies migrations to the shared Tiger Data database.
@matmanna · @sdrucquer · @AbhinavDasari-pennstate · @vs-githjk
Built from Better-T-Stack. Product names and logos belong to their owners; their use here means "built with", not partnership.
Entries are numbered. The small numbers in the text link here. Law, price file and benchmark links were checked in October 2026 (access dates are in the files under data/).
This README's measured results; 89 merged PRs. ↩
reader/stepfun.ts, #53, #58; 88.8% line recall, p50 26.2 s on 35 photos. ↩
docs/SENTRY.md, docs/OBSERVABILITY.md, #59, #68, #69. ↩
#15, #41, #98, #99; Cedars-Sinai price file 883,973,507 bytes, SHA-256 in capture.json; UCLA policy run 145 s, $0.033. ↩
services/email.ts, services/call.ts, #67. ↩
| Postgres on Tiger Data, Sentry |
results.json| 12 of 12 | synthetic bills screened for assistance, 8 checks each, 28 of 28 "may help" findings cite their source | data/eval/assistance.json, Oct 18, 2026 |
| ElevenLabs | ElevenLabs is load-bearing | Conversational AI agent places the billing call, then call.status pulls the transcript and a structured outcome (reference number, next step, follow-up date)6 | Disclosure first, at most 3 items, no codes or ids spoken; script is rebuilt and compared to the approved one before dialing; 3 calls per 10 minutes. Live calls verified |
| Gemini | Gemini is load-bearing | Drafts every letter from the flags; cleans up pasted text when the parser misses more than 30% of rows7 | A claim checker rejects any dollar amount Gemini did not get from the bill or the evidence; measured 4.1 to 5.4 s per letter on 4 bills (#84) |
| Tiger Data (MLH) | Make Tiger Data a load-bearing data layer, not a database added for the badge | Tiger Data Postgres keeps relational patient cases, itemized bill lines, evidence-backed flags, hospital prices and policies beside the chronological event stream that powers each case timeline8 | One SQL system serves both the current case state and its history: indexed events make follow-up activity fast to retrieve, while an append-only database trigger preserves the audit trail. Committed migrations reach the shared database only through CI on main |
| Visa — Future of Shopping | Use AI across the shopping journey while improving commerce, trust and responsible decision-making | A hospital procedure is a purchase whose itemized receipt often arrives later as a difficult medical bill. BetterBill turns that post-purchase document into a collaborative review: AI reads it, the patient confirms each line, deterministic rules compare quantities, EOB responsibility and published prices, and the app prepares evidence before the patient pays or asks for a correction | The natural Visa extension is a cardholder benefit inside a banking or card app: after a healthcare purchase, receipt analysis could surface a questionable line or a lower published price and help a Visa customer keep more of their money. This is a track-fit concept, not a claimed Visa integration: BetterBill uses no Visa API or card data today |
| GoDaddy Registry — Best Domain | Pair a memorable domain with a project people can understand and trust | Our betterbill.us domain says what the product does in two words and gives the live experience a clear home beyond a temporary hackathon URL | The .us ending gives the name a nationwide, consumer-service feel that matches the ambition to help patients across the country, while “BetterBill” stays plain, credible and easy to say at a billing desk. |
| Paper | Design fundamentals and craft | One design for web, iOS and Android, designed in Paper; the phone app was built frame by frame from it9 | Shared tokens on web and native: ink balance card, mint savings, cobalt actions, Instrument Serif; tier badges never rely on color alone |
capture.json.services/gemini.ts, letter-drafter.ts, #40, #84. ↩
packages/db, CI job migrate-shared in ci.yml (green on the latest main run). ↩