Komplettes Rework der AI-Studio-Vorlage zu einem produktiven Werkzeug fuer
deutsche AcroForm-Formulare (Reha-Antraege, Arzt-Befundberichte):
- Backend: Express spawnt headless Claude CLI ('claude -p --output-format json'
via stdin-Pipe). Prompt enthaelt die Feldnamen als Ziel-Schema plus die
Arbeitsregeln (Stichwortstil, feste Zeichen-Kaestchen ohne Leerzeichen,
Vordrucke respektieren, keine geratenen Werte, nur medizinisch).
- PDF-Handling: pdfjs-dist statt pdf-lib — pdf-lib scheitert an verschluesselten
Object-Streams in DRV-Formularen. annotationStorage + saveDocument, kein
Flatten. Worker-Patch zur Laufzeit forciert Auto-Size und schwarze Schrift.
- Multi-Source-Upload: beliebig viele PDFs/Bilder + optional Freitext.
- Design: Kanagawa Design System (Preset aus ../kanagawa-design-system),
Tailwind lokal gebaut statt CDN, Dark/Light-Toggle, Progress-Indicator.
- Deployment: Multi-Stage-Dockerfile, docker-compose in matrix_default-Netz,
Claude-Credentials vom Host per Volume. PLAN.md + AGENTS.md (Alex-Schema).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.5 KiB
5.5 KiB
Rentenversicherer: AcroForm Auto-Fill
Purpose
- Browser-UI nimmt ein Original-PDF (mit AcroForm-Feldern) und ein Quelldokument (Scan, Brief, Ausweis, o.ä.) entgegen.
- Ein lokales Node-Backend ruft die Claude Code CLI (
claude -p) als Subprozess auf, übergibt beide Dateien und die Liste der AcroForm- Feldnamen. Claude liefert strukturiertes JSON mit{feldname -> wert}. - User reviewt/korrigiert die Werte im Browser, lädt das ausgefüllte PDF runter.
- Das heruntergeladene PDF bleibt AcroForm (keine Flattening-Operation). Im PDF-Reader nachträglich manuell editierbar — als hätte ein Mensch es ausgefüllt.
Scope
- Frontend: React/Vite, Upload + Review-Panel + Live-Preview + Download.
- Backend: Minimaler Node-Server, eine Route
POST /api/process. Spawntclaude -p --output-format jsonmit Temp-Files und einem Prompt, der die Ziel-Feldnamen enthält. - PDF-Handling:
pdfjs-distclient-side — Widgets sammeln, Werte viaannotationStorage.setValue(id, { value })setzen,doc.saveDocument()schreibt ein PDF ohne Flatten. (pdf-lib wurde getestet, scheitert aber an komprimierten Object-Streams in DRV-Formularen.) - Lokaler Single-User-Betrieb (localhost).
Out of scope
- Gemini, Anthropic SDK, Claude Agent SDK — nur die CLI als Subprozess.
- Visual-Overlay-Modus mit Koordinaten für gescannte Flat-PDFs.
- Form-Overlay-View (Drag & Drop) im Review-Panel.
- Authentifizierung, Multi-User, Persistenz, Datenbank.
- PDF-Flattening, Signaturen, Formular-Editor, Seiten-Modifikation.
- Cloud-Deployment.
Architektur
Browser (Vite :5173)
│ multipart upload: form.pdf + source.pdf + fieldNames[]
▼
Node Server (:3001, Express)
│ 1. schreibt beide PDFs in Temp-Verzeichnis
│ 2. spawnt:
│ claude -p --output-format json \
│ --permission-mode bypassPermissions \
│ "<Prompt mit Feldliste + Pfaden>"
│ 3. parst stdout → extrahiert JSON aus result-Feld
│ 4. löscht Temp-Verzeichnis
▼
Browser bekommt { fields: [...], summary: "..." }
│ User reviewt/korrigiert
│ pdfjs-dist: annotationStorage.setValue + saveDocument
│ (kein flatten; AcroForm bleibt erhalten)
▼
Download
Repo-Layout
Rentenversicherer/
├── App.tsx # Upload → Process → Review Flow
├── components/
│ ├── FileUpload.tsx
│ └── ReviewPanel.tsx # nur List-View, Overlay-View entfernt
├── services/
│ ├── api.ts # Frontend-Client für /api/process
│ └── pdfService.ts # getPdfFields + createFilledPdf via pdfjs-dist
├── server/
│ ├── index.ts # Express: static + /api/process
│ └── claudeRunner.ts # spawn('claude', ['-p', ...]); JSON-Extraktion
├── types.ts
├── vite.config.ts # dev-proxy /api → :3001
├── package.json # dev-script: vite + server parallel
├── tsconfig.json # shared tsconfig für Client + Server
├── .gitignore
├── PLAN.md
├── AGENTS.md
└── README.md
Workflow (User-Sicht)
- Original-PDF hochladen. Client scannt AcroForm-Feldnamen
mit
getPdfFields()und zeigt die Anzahl als Hinweis. - Quelldokument hochladen (PDF oder Bild).
- "Analyze & Fill" klicken.
- Browser sendet beide Dateien + Feldliste an
POST /api/process. - Server schreibt Dateien ins Temp-Verzeichnis, baut Prompt, spawnt Claude CLI, parst JSON, antwortet.
- Review-Panel zeigt
{label, value, validation}-Paare — User korrigiert, markiert als verified. - "Download" →
createFilledPdfsetzt die Werte via pdfjsannotationStorageund schreibt mitdoc.saveDocument(). Kein Flatten. - User öffnet das runtergeladene PDF → Felder sind gefüllt und bleiben klick- und editierbar in Acrobat/Reader.
Umsetzungsschritte
package.json: Server-Deps (express,multer,tsx,concurrently, typings) ergänzen, Scripts aktualisieren.server/claudeRunner.ts:spawnmit Windows-kompatiblem Aufruf, stdout buffern,--output-format jsonResult-Wrapper entpacken, inneres JSON parsen.server/index.ts: Express-App,multerfür Upload, Temp-Dir pro Request,finally-Cleanup.vite.config.ts:server.proxy['/api']nachhttp://localhost:3001.services/api.tsals Frontend-Client;services/geminiService.tslöschen.services/pdfService.ts: aufpdfjs-distumgestellt.getPdfFieldsiteriert über Pages + Widget-Annotations,createFilledPdfnutztannotationStorage+saveDocument.components/ReviewPanel.tsx: Form-Overlay-View entfernen, nur List-View behalten, Koordinaten-Logik raus.App.tsx: Fehlermeldung, falls Ziel-PDF keine AcroForm-Felder hat (UI blockiert Upload dann).- Smoke-Test mit
G2210-11_Aerztlicher_Befundbericht_Anforderung_WAG.pdf:npm run dev, ausfüllen, runterladen, in Acrobat öffnen, Feld editieren können.
Notes
- Claude CLI wird über dein bestehendes Login authentifiziert. Kein API-Key im Code oder in Env-Dateien.
claude -pbraucht--permission-mode bypassPermissions, damit das Read-Tool ohne User-Prompt auf die Temp-Files zugreifen darf.- Temp-Verzeichnisse liegen unter
os.tmpdir()und werden nach jedem Request gelöscht. Kein persistenter Upload-Ordner. - Windows-Pfad-Konvention: Server nutzt
path.join, arbeitet also plattformneutral. Der Claude-CLI-Aufruf läuft viashell: trueunter PowerShell (vgl. globale CLAUDE.md).