Creates docs/ with three audience-specific guides: - docs/user-guide.md: step-by-step form-filling instructions, field descriptions, FX rate explanation, receipt handling, troubleshooting - docs/admin-guide.md: deployment instructions and exhaustive config.yml key/value reference with types, defaults, and constraints - docs/developer-guide.md: architecture overview, full state model, all CFG key mappings, PDF engine internals, column positions, four-pass build process, common modification checklists, known limitations Rewrites CLAUDE.md as a dense agent reference covering the same ground in a compact format: code section line ranges, full config key table with JS access patterns, validation rules, PDF coordinate system, design decisions, and modification checklists. https://claude.ai/code/session_01Dad69NPna53u4hucCYnVNs
8 KiB
Administrator Guide — Reimbursement Form
This guide is for the person responsible for deploying and configuring the reimbursement form for their organisation.
Architecture
The application is a static web app — a single HTML file that loads a YAML configuration file at runtime. There is no server-side logic, no database, and no build step.
app/
├── index.html # Complete application
├── config.yml # All organisation-specific settings
└── assets/
└── logo.png # Optional organisation logo (PNG or JPG)
The browser downloads the two CDN libraries at startup:
pdf-lib1.17.1 — PDF generationjs-yaml4.1.0 — YAML config parsing
Both are loaded from unpkg.com. Users need an internet connection to open the form for the first time; subsequent use within the same browser session does not re-fetch them.
Deployment
- Copy the
app/directory to any static web server (Nginx, Caddy, Apache, S3 + CloudFront, GitHub Pages, etc.). - Ensure the server serves
.ymlfiles with a valid MIME type. Caddy does this automatically. For Nginx, add:types { text/yaml yml; } - Access the form at the URL where
index.htmlis served. No path configuration is needed inside the file.
The form works with any URL path. If you deploy at https://intranet.example.org/finance/reimbursement/, no changes to the source are required.
Configuration reference — config.yml
All customisation is done in config.yml. The file is loaded fresh every time the page is opened, so changes take effect immediately without redeploying.
Organisation identity
organization: "Center for Asylum Protection"
logo: yes
logo-maxwidth: 4
| Key | Type | Required | Description |
|---|---|---|---|
organization |
string | Yes | Displayed in the form header and on the PDF. Used as a fallback if the logo is disabled or the image file is missing. |
logo |
yes / no |
Yes | Whether to show a logo image. If yes, the app attempts to load assets/logo.png; if that fails, it tries assets/logo.jpg; if that also fails, it falls back to displaying the organization text. |
logo-maxwidth |
number (cm) | No | Maximum width of the logo in centimetres, applied in both the browser UI and the PDF. Default behaviour is unconstrained. Typical value: 4. |
Logo requirements:
- Format: PNG (preferred) or JPG
- File must be placed at
assets/logo.png(orassets/logo.jpg) - The image is scaled to fit within
logo-maxwidthcm width and 56 px height (UI) or 50 pt height (PDF), whichever is the binding constraint
PDF page setup
page-size: A4
| Key | Type | Required | Description |
|---|---|---|---|
page-size |
A4 / letter |
Yes | Paper size for PDF output. A4 = 595.28 × 841.89 pt. letter = 612 × 792 pt. |
Typography
font-body: Helvetica
font-heading: Helvetica
font-monospace: Courier
font-size: 10
| Key | Type | Required | Description |
|---|---|---|---|
font-body |
string | Yes | Font used for body text in the PDF. Must be one of the standard PDF fonts: Helvetica, Times, or Courier. Custom TTF fonts are not yet supported. |
font-heading |
string | Yes | Font used for headings and labels in the PDF. Same options as font-body. |
font-monospace |
string | Yes | Font used for monospaced content. Recommended: Courier. |
font-size |
number (pt) | Yes | Base font size in points for PDF body text. Headings and labels are scaled relative to this. Typical range: 9–12. |
Note on fonts: The current implementation always uses
Helvetica/HelveticaBold/Courierregardless of whatfont-body,font-heading, andfont-monospaceare set to. Custom font selection is planned but not yet implemented.
Branding
accent-colour: "#1a3a5c"
| Key | Type | Required | Description |
|---|---|---|---|
accent-colour |
hex colour string | Yes | Primary brand colour. Applied as the --accent CSS variable in the browser UI (buttons, borders, headings) and as the heading/divider colour in the PDF. Must be a six-digit hex string including the # prefix. |
Form text
intro: ""
footer: "Confidential"
| Key | Type | Required | Description |
|---|---|---|---|
intro |
string | No | Optional introductory text shown on the first page of the PDF, above the staff/period/currency fields. Leave empty ("") to omit. Long text wraps automatically. |
footer |
string | No | Text printed at the bottom of every PDF page. Typical values: "Confidential", "Internal use only", or your organisation's name. |
Currency settings
currency-base: USD
currencies:
- code: USD
name: United States dollar
- code: THB
name: Thai baht
- code: EUR
name: Euro
- code: NOK
name: Norwegian krone
| Key | Type | Required | Description |
|---|---|---|---|
currency-base |
ISO 4217 code | Yes | The default base (reimbursement) currency. Must be present in the currencies list. All amounts on the PDF summary are converted to this currency. |
currencies |
list of {code, name} |
Yes | All currencies available in the per-line currency dropdown. code must be an ISO 4217 three-letter code. name is shown in the dropdown for user reference only. |
FX rate convention: rates are expressed as units of the line currency per 1 unit of the base currency (e.g. 34.25 THB per 1 USD). Conversion is base_amount = line_amount / fx_rate.
Adding a currency: append a new {code, name} entry to currencies. No other changes are needed.
Removing a currency: remove its entry. Any existing PDF claims already generated are unaffected.
Accounts
accounts:
- "1000 - General Operations"
- "2000 - Travel & Transport"
- "3000 - Office Supplies"
- "4000 - Professional Services"
| Key | Type | Required | Description |
|---|---|---|---|
accounts |
list of strings | Yes | Dropdown options for the "Account" field on each expense line. Each string is shown verbatim. Typically formatted as "CODE - Description". At least one entry is required. |
Selecting an account is mandatory for each line. The account code selected appears verbatim on the generated PDF.
Programs
programs:
- "General Operations"
- "Legal Aid Program"
- "Protection Program"
- Other
| Key | Type | Required | Description |
|---|---|---|---|
programs |
list of strings | Yes | Dropdown options for the "Program" field on each expense line. At least one entry is required. |
Special value Other: if the literal string Other is included in the list, selecting it in the form reveals an additional free-text field where the user must type the program name. The PDF will show Other: [typed value]. All other values are shown exactly as written.
Changing configuration
- Edit
app/config.ymlin any text editor. - Save the file and refresh the browser. Changes are live immediately.
- Existing downloaded PDFs are not affected.
Adding a logo
- Prepare a PNG or JPG image of your logo. Transparent background (PNG) works best.
- Place the file at
app/assets/logo.png(create theassets/folder if it does not exist). - Set
logo: yesinconfig.yml. - Set
logo-maxwidthto the desired maximum width in centimetres.
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Form shows "Failed to load: Cannot load config.yml" | Server not serving the YAML file, or file missing | Check the file path and server MIME type configuration |
| Logo does not appear | File missing or wrong path | Place file at assets/logo.png relative to index.html |
| Accent colour not applied | Malformed hex value | Use the format "#rrggbb" (six digits, with quotes, with #) |
| Currency not in dropdown | Missing from currencies list |
Add the {code, name} entry to currencies |
currency-base not selectable |
Code not in currencies list |
Add it to currencies before using it as currency-base |
| PDF fonts look wrong | Custom font specified | Only Helvetica, Times, Courier are currently supported |