invoice/docs/admin-guide.md
Claude d0c5249bcb
Add user, admin, dev documentation and CLAUDE.md
docs/user-guide.md  — end-user guide covering the full invoice workflow
docs/admin-guide.md — config.yml reference for setting up the app
docs/dev-guide.md   — codebase guide: architecture, state, functions,
                      localStorage, i18n, FX convention, PDF generation
CLAUDE.md           — project briefing for Claude Code sessions
2026-05-24 18:25:19 +00:00

13 KiB
Raw Permalink Blame History

Administrator Guide

All runtime configuration for this invoicing application lives in a single file: app/config.yml. No HTML or JavaScript needs to be modified to adapt the app to a new organisation. Edit the YAML, save, and reload the browser tab — that is the entire deployment cycle.

This guide covers every section of the file in the order it appears, plus a complete walkthrough for adding a new language.


Deployment and Serving

The application fetches config.yml at startup using an HTTP request. It will not work when opened directly as a local file (file:// URLs block cross-origin fetches even within the same directory). It must be served by a web server.

The simplest option from the repository root is:

npx serve app

This serves everything inside the app/ directory on http://localhost:3000 (or the next available port). Any other static file server pointed at the app/ directory works equally well — nginx, Apache, Caddy, Python's http.server, or a cloud storage bucket with static hosting.

No build step, database, or server-side runtime is required.


Default Language

default-code: en
default-name: English
default-direction: ltr

These three keys determine the language the app starts in before the user changes anything.

  • default-code must exactly match the code of one of the entries in the languages list below.
  • default-name is a human-readable label used only as a hint in this section; it is not read programmatically.
  • default-direction must be ltr (left-to-right) or rtl (right-to-left). Set this to rtl if the default language is Arabic, Hebrew, Persian, or any other right-to-left script. The app applies CSS direction and layout mirroring based on this value.

Available Languages

languages:
  - code: en
    name: English
    direction: ltr
  - code: de
    name: Deutsch
    direction: ltr

This list controls which languages appear in the language selector. If the list contains exactly one entry, no selector is shown and the UI is fixed to that language.

Each entry has three required fields:

  • code — a short identifier, typically an IETF language tag such as en, de, fr, or ar. This value is used as the lookup key throughout the rest of the config (in labels, description, and translations maps). Every language code used elsewhere in the file must appear here.
  • name — the display name shown in the language selector dropdown, written in that language (e.g. Deutsch rather than German).
  • directionltr or rtl. Setting this to rtl causes the entire UI to mirror for right-to-left reading, including the invoice PDF layout.

YAML treats bare no as the boolean false, so Norwegian (no) must always be quoted: "no". This applies to the language code entry itself and to every map key that uses it elsewhere in the file.


Payment Info Visibility

hide-payment-info: false

When set to true, the entire Payment card is removed from the invoice form and the payment block (account holder, account number, BIC, bank address, payment reference) is omitted from the generated PDF. Set this if your organisation invoices through a platform that handles payment separately, or if displaying bank details on invoices is not appropriate for your context.

Set to false (the default) to show the payment section normally.


Date and Paper Format

date-format: "d MMMM YYYY"
paper-format: a4

date-format

Controls how dates are rendered on the invoice. The value is a format string using the following tokens:

Token Output
d Day of the month without leading zero (1, 2, … 31)
dd Day of the month with leading zero (01, 02, … 31)
M Month number without leading zero (1, 2, … 12)
MM Month number with leading zero (01, 02, … 12)
MMM Abbreviated month name (Jan, Feb, …)
MMMM Full month name (January, February, …)
YY Two-digit year (25, 26, …)
YYYY Four-digit year (2025, 2026, …)

Any separator characters (spaces, hyphens, slashes, dots) between tokens are preserved literally. Examples:

  • "d MMMM YYYY"24 May 2026
  • "dd/MM/YYYY"24/05/2026
  • "YYYY-MM-dd"2026-05-24

paper-format

Controls the page dimensions of the generated PDF. Accepted values:

  • a4 — 210 × 297 mm (standard outside North America)
  • letter — 8.5 × 11 inches (standard in North America)

Tax Types

tax-types:
  - key: vat
    labels:
      en: VAT
      de: MwSt.
      fr: TVA

This section defines the tax labels available in the tax-line dropdown when the user builds an invoice. It does not set any rates — rates are always entered by the user at invoice time, which allows different invoices to use different rates for the same tax type.

Each entry has:

  • key — an internal identifier (not shown to users) used to reference this tax type. It must be unique within the list.
  • labels — a map of language code to display string. When the user adds a tax line, the label shown is the one matching the active language.

Add as many tax types as your jurisdiction requires. Remove any that are irrelevant to your operation. Every active language code should have a corresponding entry in each labels map; if a code is missing, the app will fall back to the raw key.


Units of Measure

uom:
  - code: HR
    labels:
      en: Hour
      de: Stunde
      fr: Heure

Defines the unit-of-measure options available in the invoice line dropdown. Each entry has:

  • code — an uppercase internal identifier (e.g. HR, DY, EA). This code is what gets stored and is what must be referenced in the products section.
  • labels — a map of language code to the human-readable label displayed in the UI and on the invoice.

Add units appropriate to your business (e.g. KG for kilograms, KM for kilometres, PG for pages). Remove any that are not used. At least one unit must be present.


Predefined Recipients

charge-to:
  - display: Acme Corporation
    name: Acme Corporation Ltd.
    address1: 123 Business Avenue
    address2: Suite 400
    address3: New York, NY 10001
    address4: ""
    country: US
    phone: "+1-212-555-0100"
    email: accounts@acmecorp.example
    vat-id: "US-EIN-12-3456789"
    reg-no: ""
    currency: USD
    project-codes:
      - AC-100
      - AC-110

The charge-to list populates the recipient dropdown on the invoice form. When the user selects a recipient, all fields are filled in automatically. This section is optional — if omitted or empty, the user fills in recipient details manually every time.

Fields

  • display — the short label shown in the dropdown. Does not appear on the invoice itself; it is only for the user's convenience when choosing from the list.
  • name — the legal name printed on the invoice under the "Charge to" heading.
  • address1 through address4 — four free-form address lines. Use as many or as few as the address requires; set unused lines to an empty string ("").
  • country — the recipient's country as an ISO 3166-1 alpha-2 code (two uppercase letters, e.g. US, GB, DE, NO). This is printed on the invoice.
  • phone — contact phone number. Printed on the invoice. May be left empty.
  • email — contact email address. Printed on the invoice. May be left empty.
  • vat-id — the recipient's VAT or tax registration number. Printed in the recipient block if present.
  • reg-no — the recipient's company registration number. Printed in the recipient block if present. Set to "" if not applicable.
  • currency — an ISO 4217 three-letter currency code (e.g. USD, EUR, GBP). When this recipient is selected from the dropdown, the invoice currency is automatically set to this value. The code must appear in the currencies list for the currency selector to work correctly.
  • project-codes — an optional list of project code strings specific to this recipient. When this recipient is selected, only these codes appear in the project code dropdown. If this key is absent from a recipient entry, the dropdown falls back to the global project-codes list.

Adding a new recipient

Add a new list item with all the fields above. Omitting optional fields (vat-id, reg-no, project-codes, empty address lines) is fine as long as the key is present with an empty value where the app expects a string.


Global Project Codes

project-codes:
  - Project 100
  - Project 110
  - Project 230

This is the fallback list of project codes shown in the project code dropdown when no recipient is selected, or when the selected recipient has no project-codes key of its own. Each item is a plain string.

Set this to the codes that span multiple clients or apply to general work. Leave the list empty (project-codes: []) if project codes are not used in your organisation, which causes the dropdown to show no options.


Predefined Products and Services

products:
  - code: CONSULTING
    description:
      en: Consulting Services
      de: Beratungsleistungen
    uom: HR
    price: 100.00

The products list populates the description dropdown on each invoice line. When a product is selected, the description, unit of measure, and unit price are filled in automatically. The user can override any of these values after selection.

Each entry has:

  • code — an internal identifier, not shown to users. Must be unique within the list. Conventionally uppercase.
  • description — a map of language code to the human-readable description string printed on the invoice line. Provide a translation for every active language.
  • uom — the unit of measure code for this product. Must exactly match a code value from the uom list.
  • price — the default unit price as a decimal number. The user can edit this at invoice time.

Products can represent services (billed by the hour or day) or fixed-price deliverables (billed as each). Remove products that are not relevant to your work and add your own.


Currencies

currencies:
  - USD
  - EUR
  - GBP
  - NOK

This list defines the options available in the invoice currency selector. Each entry is an ISO 4217 three-letter currency code. The list is used for two purposes:

  1. Populating the invoice currency dropdown when the user changes the invoicing currency from the default.
  2. Validating that the currency field on a recipient entry points to a known code.

Include every currency your organisation might invoice in. The order of the list is the order entries appear in the dropdown. There is no limit on the number of entries.


UI Label Translations

translations:
  invoice:
    en: INVOICE
    de: RECHNUNG
    fr: FACTURE
    "no": FAKTURA
  generate-invoice:
    en: Generate Invoice
    de: Rechnung erstellen

The translations section contains every user-facing string in the application UI. Each top-level key under translations corresponds to a specific label, button, column header, or section title. The value is a map of language code to translated string.

These strings appear in both the interactive form and the generated PDF. When the active language changes, every label on the page re-renders using the matching translation.

You should not need to change keys or add new keys unless you are modifying the application itself. The keys that must be present are fixed by the application code.

Adding a translation for a new language

For each key in the translations section, add a new entry for your language code:

  invoice:
    en: INVOICE
    de: RECHNUNG
    ar: فاتورة

Every key in the translations section must have an entry for every language code listed under languages. If a translation is missing for a given language, the app displays the raw key as a fallback.


Adding a New Language End to End

To add a new language — for example, Arabic (ar) — make the following changes to config.yml in order:

  1. Add to the languages list. Append a new entry. For a right-to-left language, set direction: rtl:

    languages:
      - code: ar
        name: العربية
        direction: rtl
    
  2. Optionally set it as the default. If Arabic should be the startup language, update the default block:

    default-code: ar
    default-name: Arabic
    default-direction: rtl
    
  3. Add labels to every tax-type entry. For each item under tax-types, add an ar: entry under labels.

  4. Add labels to every uom entry. For each item under uom, add an ar: entry under labels.

  5. Add descriptions to every product entry. For each item under products, add an ar: entry under description.

  6. Add a translation for every key under translations. Work through every key in the translations map and add an ar: entry with the appropriate translated string.

Once all entries are present, save the file and reload the browser. The new language will appear in the language selector. For RTL languages, the layout will mirror automatically.


After Editing

Save config.yml and reload the browser tab. The application fetches the config fresh on every page load; there is no cache to clear and no server process to restart. Changes take effect immediately.