8.2 KiB
Administrator Guide — Reimbursement Form
This guide is for the person responsible for deploying and configuring the reimbursement form for their organisation.
Copyright 2026 Kristian Benestad. Licensed under the Apache License, Version 2.0. See LICENSE for more information.
This is a custom build of kbenestad/reimburse for Boat People SOS and People Serving People Foundation.
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 |