Build an invoice whose figures add up. Amounts on integers in the currency own ISO 4217 minor unit, fractional quantities, the discount taken before tax, and a PDF that gets written whatever alphabet the client name is in.
Initializing in your browser…
Generate fake data that is the thing it is labelled: card numbers with a real Luhn check digit, IBANs that pass ISO 7064 MOD 97-10, UUID v4 and v7 per RFC 9562, reserved e-mail and IP ranges, a seed so the same data comes back, and JSON, NDJSON, CSV or SQL output
Generate passwords from the Web Crypto generator by rejection sampling, with the entropy stated exactly from the alphabet, the cost of every rule computed, and crack times against four named attacker models
Stack CSS box shadows with any colour notation, and never write a declaration the browser will drop: a layer that will not parse is left out and flagged rather than taking every other layer down with it
Build an invoice whose figures add up. Every amount is computed on integers counting the currency own minor unit, so the printed lines add to the printed subtotal and the printed subtotal, discount and tax add to the printed total. The page checks that on every keystroke and says so. Nothing is uploaded: the PDF is written in your browser.
**The first is that the column adds up.** Whoever pays an invoice adds the line amounts and checks them against the subtotal, then adds the subtotal and the tax and checks them against the total. A tool that keeps an unrounded figure and rounds each printed number independently produces a column that does not add up: the version of this tool that shipped before September 2026 printed three lines of $0.38 under a subtotal of $1.13, and on a measured corpus of twelve ordinary invoices, ten of eighteen printed lines did not equal their own printed quantity times their own printed unit price. Everything here is computed on integers counting the minor unit, and **the subtotal is the sum of the rounded line amounts** rather than the rounding of an unrounded sum, which is the only arrangement in which a column agrees with its own footer. The page re-reads its own printed strings, adds them again, and shows you the result of that check.
**The second is the number of decimal places, which belongs to the currency and is not always two.** ISO 4217 calls it the minor unit. The Japanese yen and the Korean won have none, the Bahraini and Tunisian dinar have three. The figure comes from CLDR through the browser own `Intl`, so a yen invoice reads ¥100 and not ¥100.00.
**The third is when the discount comes off.** A price discount granted to the customer at the time of supply is excluded from the taxable amount by article 79 of the EU VAT Directive, and US sales tax works the same way, so tax is charged on the discounted figure by default and the page names the amount it was charged on. Charging tax on the full subtotal instead overcharges by the tax on the discount: 2.00 on a 100 invoice with 20 percent tax and a 10 discount. The other order is offered, because a settlement discount or a third-party-funded one can genuinely fall outside the taxable supply, but it has to be chosen by name.
**The fourth is what a PDF can actually write.** A PDF drawn with one of the standard 14 fonts carries the WinAnsi encoding, which is 218 characters: printable ASCII, Latin-1, and 27 more. The Indian rupee sign is not among them, and neither is any Greek, Cyrillic or CJK letter, and pdf-lib throws rather than dropping a character. Measured across twelve ordinary invoices, five produced no file at all: a rupee invoice, and clients named in Polish, Greek, Chinese and Turkish, each ending in a bare "Failed to generate PDF". Now the page tells you what cannot be drawn BEFORE you click, substitutes the nearest Latin form where there is one, falls back from an unwritable currency symbol to its ISO 4217 code, which is always ASCII, and writes the file.
Quantities may be fractional to three decimal places, which is what an hourly invoice needs: 2.5 hours at 100 an hour bills 250, where reading the quantity with `parseInt` billed 200. A unit price may be finer than the currency, up to six places, because a per-unit rate genuinely is quoted below the minor unit, and the price is printed at the precision it was given while only the line amount is rounded. Show working prints the product before rounding, how far rounding moved each line, and what the tax was charged on.
Every figure the page produces is checked in the project tests against a second implementation of the arithmetic written in Python decimal from the same definitions: 146 invoices across four currencies and both tax orders in the module tests, and sixteen more driven through the browser, with no disagreements. What the PDF says is read back out of the file by two independent readers, poppler pdftotext and pypdf.
Three lines of 3 units at $0.125 each. Each line is exactly $0.375 and prints as $0.38, and the subtotal is the sum of those three rounded amounts, $1.14. Rounding the unrounded $1.125 instead gives $1.13, which is a column of three $0.38 lines under a footer that disagrees with them.
A $100 subtotal, 20 percent tax, a $10 discount. Tax on the discounted $90 is $18 for a total of $108. Tax on the full $100 is $20 for a total of $110. The page says which of the two it charged and on what amount.
A fractional quantity is the whole point: 2.5 hours at your rate bills 2.5 hours.
A yen invoice with two decimal places is wrong on its face. The decimal places come from the currency, not from a constant.
The figures add up by construction, and Show working prints where each rounding went, so a query has an answer.
Because an invoice is settled in whole minor units, and 0.375 is not one. That rounding cannot be avoided. What can be avoided is the subtotal disagreeing with the lines, and here the subtotal is the sum of the rounded amounts, so it agrees. Show working prints how far each line moved.
Before, in almost every case. A price discount granted at the time of supply is excluded from the taxable amount by article 79 of the EU VAT Directive, and US sales tax treats a cash or trade discount the same way. That is the default. Pick the other only for a discount that genuinely falls outside the taxable supply, such as one funded by a third party.
Because a PDF drawn with one of the standard 14 fonts carries the WinAnsi encoding, and the rupee sign was added to Unicode in 2010, long after that encoding was fixed. Rather than fail, the PDF writes the ISO 4217 code, which is ASCII and always writable. The screen keeps the symbol.
A standard PDF font can draw 218 characters and no CJK, Greek or Cyrillic letter is among them. The page lists exactly which characters it cannot draw before you download, so nothing is a surprise. A name in a Latin script with accents or strokes is handled: it keeps its accents where WinAnsi has them and loses only the marks it does not.
No. Everything stays in the page and the PDF is written in your browser. Nothing is saved between visits, so download each invoice before you close the tab.
There is no dedicated field, so put it in your address block or in the notes. If your jurisdiction requires one, check the invoice before sending it.
This runs as client-side JavaScript. Keys, tokens, payloads, and other inputs never leave your device.