3.2 KiB
CTM Document Builder
Electron + React desktop app for CTM document workflows: instruction PDFs and vaccination records, backed by a cloud PocketBase instance for instruction storage.
Setup
1. Install dependencies
npm install
2. Configure PocketBase (internal build)
Edit electron/main/pocketbase-config.js with your instance URL and superuser credentials. Values are bundled into the desktop app — no .env file is required.
3. Cloud PocketBase collection
Your PocketBase instance should have an instructions collection with:
vaccine— Textinstruction— Text
The app authenticates as a _superusers account (PocketBase v0.23+).
4. Run the app
npm run dev
Restart Electron after changes to electron/main/ (e.g. PDF import).
Features
Three tabs:
- Instructions — Compose instruction documents from library entries; reorder and edit on the canvas; export a portrait PDF with logo and header.
- Instruction Manager — Create, edit, and delete instruction entries in PocketBase.
- Vaccination Record — Patient header, up to 15 vaccination rows, and notes; export a landscape PDF; Import from PDF to reload a previously exported record.
PDF export
PDFs are generated with Chromium printToPDF in a hidden Electron BrowserWindow. The app logo is loaded from assets/logo.png (bundled as extraResources in packaged builds).
Vaccination record import (metadata-only)
Import reads embedded machine-readable metadata from PDFs exported by this app. There is no visual/layout fallback.
- Only PDFs with valid
CTM_VRmetadata can be imported. - Last update is always set to today on import (not read from the PDF).
- Import replaces the current builder data (with a confirm dialog if data already exists).
- Third-party PDFs, scanned documents, or files with stripped or tampered metadata will show an error.
Metadata format (developers)
Vaccination record PDFs embed a hidden text payload for round-trip import.
Wire format:
CTM_VR:<version>:<base64url(JSON)>
Current version: 1
v1 JSON fields:
| Field | Type | Notes |
|---|---|---|
patientName |
string | |
dateOfBirth |
string | ISO YYYY-MM-DD |
notes |
string | |
rows |
array | Max 15 rows |
rows[].diseaseKey |
string | Key from DISEASE_OPTIONS |
rows[].date |
string | ISO YYYY-MM-DD |
rows[].productBrand |
string | |
rows[].lotNumber |
string | |
rows[].provider |
string |
lastUpdate is intentionally omitted from metadata; the UI sets it on import.
Implementation: src/lib/vaccinationRecordMetadata.js
Adding a new version: register a parser in VERSION_PARSERS, bump VR_METADATA_LATEST_VERSION for export, and keep older parsers so previously exported PDFs still import.
Scripts
npm run dev— Start Vite dev server + Electronnpm run build— Build and package with electron-buildernpm run preview— Vite preview (renderer only; no PDF export)
Packaging
assets/ (logo and icon) are included as extraResources for packaged builds. No local PocketBase binary is bundled.