A Claude agent converts blank clinical forms (text, PDF or image) into FHIR R4 Questionnaires coded in LOINC, and corrects itself until the HL7 validator accepts them.
HealthTypeScript · VueGitHub @nanguiOnlineOwner 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
Any clinical form → a valid FHIR R4 Questionnaire, coded in LOINC. A Claude agent proposes, the HAPI FHIR validator decides.
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Any clinical form → a valid FHIR Questionnaire.
Paste a blank clinical form, or upload a PDF or a screenshot. An AI agent built on the Claude API turns it into a FHIR R4 Questionnaire (SDC), with questions coded in LOINC. It keeps correcting itself until the Questionnaire passes validation.
The model proposes, the validator decides.
Live demo: form2fhir.vercel.app · Demo only: blank forms, no real patient data. Not a medical device.
Browser ── POST /api/convert (text | PDF | image) ──► Nuxt server route
▲ │ size, type and rate-limit checks
│ Server-Sent Events: each step, then the result ▼
└───────────────────────────────────────────── agent loop (≤ 4 Claude calls)
┌───────────────────────┴──────────────────────┐
search_loinc submit_questionnaire
NLM Clinical Tables API server checks ─► HAPI FHIR $validate
errors go back to Claude to fix
search_loinc with every question worth coding. The server queries the NLM Clinical Tables LOINC API and remembers every code it returned. For a known instrument (PHQ-9, AUDIT-C…) it also fetches the panel's official questions, with their answers and scores.submit_questionnaire with a complete FHIR R4 Questionnaire. The server checks what HAPI can't (every LOINC code must come from step 1; every scored LOINC answer carries its exact score as an ordinalValue; choice items need answer options; no HTML rendering extensions), warns when an item under a panel uses a code that is not one of the panel's questions, then calls HAPI FHIR $validate.Every step streams to the UI, which renders the result with NLM's LHC-Forms, plus the JSON, the codes table and the validator report.
server/lib/agent.ts, so every step can be traced and tested with a scripted fake client.EventSource only supports GET, so the browser reads the text/event-stream body of a fetch POST. No server-side state, which suits serverless.max_tokens and searches.cp .env.example .env # set ANTHROPIC_API_KEY
pnpm install
pnpm dev
| Command | What it does |
|---|---|
pnpm test | Unit tests (offline) |
pnpm test:live | Smoke tests against the LOINC search and HAPI FHIR APIs |
pnpm typecheck / pnpm lint / pnpm build | Quality gates |
node eval/run.ts --url http://localhost:3000 | Runs every fixture through the real API (costs API credits) |
Five blank forms (eval/fixtures.json lists each one's source and license), run end to end through /api/convert with Claude Sonnet 5.5:
| Form | Lang | Valid | Claude calls | LOINC coverage | Code accuracy | Time | Est. cost |
|---|---|---|---|---|---|---|---|
| Vital Signs Intake | en | ✅ | 2 | 9/13 (69%) | 8/10 (1 wrong) | 14.8 s | $0.044 |
| PHQ-9 | en | ✅ | 2 | 10/10 (100%) | 10/10 | 26.5 s | $0.083 |
| Pre-Visit Health Questionnaire (PDF) | en | ✅ | 2 | 4/11 (36%) | 2/4 | 14.0 s | $0.033 |
| Questionnaire relatif à l'état de santé du sportif mineur (Journal officiel, PDF) | fr | ✅ | 2 | 1/26 (4%) | 0/1 | 21.8 s | $0.063 |
| Bilan annuel de suivi (diabète de type 2, PDF, 3 pages) | fr | ✅ | 3 | 16/56 (29%) | 15/20 | 75.7 s | $0.159 |
5/5 valid · median 21.8 s · total ≈ $0.38 · code accuracy 35/45 (78%), 1 wrong (2026-10-27, eval/results/).
How to read it:
$validate operation reported no errors and the server's own checks passed (every LOINC code was returned by a search in the same run).expectedCodes in eval/fixtures.json, each code checked against the LOINC API): correct, wrong (another code) or missing (uncoded). Valid FHIR is not enough: a Questionnaire can pass $validate with the wrong code. Re-scoring the previous run (2026-10-16) gives 37/45 with 2 wrong, among them the PHQ-9 difficulty question coded with the generic 44256-6 instead of the panel's own 69722-7. Since panel searches return the panel's official questions, the PHQ-9 is 10/10 with no wrong code; the agent leaves a few more items uncoded instead. NLM's AUDIT-C definition replaces item 1 (68518-0) with another question, so the agent now also searches each question of an embedded instrument on its own: AUDIT-C item 1 is coded since 2026-10-27. The one wrong code is the respiratory rate coded as "Respiratory rate --resting" (9303-9) instead of 9279-1; the form does not say whether the patient is at rest. Pre-Visit went from 3/4 to 2/4 in this run (pain left uncoded). One run per form, so expect some variance between runs.eval/results/.Code: MIT. The forms used as examples and eval fixtures keep their own licenses, listed in eval/fixtures.json (PHQ-9: Pfizer, free to reproduce; the French sports questionnaire: an official text published in the Journal officiel; the other forms were written for this project and are CC0).