ReceiptLine, a Markdown dialect for thermal receipt printers
Markdown for receipts. Printable digital receipts. Generate receipt printer commands and images.
At a glance
- What is it?
- receiptline/receiptline turns a short text document into ESC/POS commands for a thermal printer or an SVG image for a screen, so the same source can drive a kitchen ticket printer and a customer-facing display. The package also handles barcode and QR generation, and sibling packages cover .NET, browser and editor use.
- Who is it for?
- Adopt ReceiptLine when you need to render receipts to thermal printers and to screens from one source, especially in a point of sale, kiosk or kitchen ticket system where paper width varies between devices. Skip it if you only need a PDF invoice, since this is a roll-paper format rather than a document layout engine.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 84 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One document, two destinations: paper and screen
ReceiptLine is a receipt description language that expresses the output image of small roll paper. The README describes it as Markdown for receipts, with printable digital receipts, generating receipt printer commands and images.
The core idea is that a document is written as text and is then rendered either to printer commands or to an image, without being tied to a particular paper width. The same source can therefore feed a thermal printer in a kitchen and a screen in a customer-facing point of sale system, and the width is a property of the destination rather than of the document.
The entry point is a single transform method:
const receiptline = require('receiptline');
const doc = '{code:2012345678903;option:ean,hri}';
// printer example
const printer = {
cpl: 42,
encoding: 'multilingual',
upsideDown: false,
gamma: 1.8,
command: 'escpos'
};
const command = receiptline.transform(doc, printer);
// display example
const display = {
cpl: 42,
encoding: 'multilingual'
};
const svg = receiptline.transform(doc, display);What changes between the two calls is the destination configuration, not the document. The printer example selects the escpos command set and adds image-processing options, while the display example asks for SVG output and only needs the character width and encoding.
The printer list is specific: Epson TM series, Seiko Instruments RP series, Star MC series, Citizen CT series and Fujitsu FP series. The Epson South Asia model and the StarPRNT variant of the Star MC series can print Thai characters using device fonts.
The maintainers are the Open Foodservice System Consortium and the OpenReceipt Project, and the licence is Apache-2.0.
The configuration object and why cpl and encoding dominate it
The printer configuration is a flat object, and most of its keys are things you would have to hard-code per device.
cpl is characters per line, defaulting to 48, and it is the single most important value because the whole document is laid out against it. encoding selects the character set, with multilingual covering cp437, cp852, cp858, cp866 and cp1252, and separate options for cp932 and shiftjis for Japanese, cp936 and gb18030 for Simplified Chinese, cp949 and ksc5601 for Korean, cp950 and big5 for Traditional Chinese, and tis620 for Thai. cp437 for the United States is the default.
Then there are the image and output options, which only apply when the destination is a printer. The gradient flag selects image processing for text, barcodes and 2D codes, with true meaning photo processing and being the default. Gamma correction runs from 0.1 to 10.0 with a default of 1.8, and thresholding from 0 to 255 with a default of 128. upsideDown flips the output, spacing enables line spacing, cutting enables paper cutting and is on by default, and margin and marginRight set the left and right print margins from 0 to 24 characters.
The command key selects the output dialect, and this is where the printer variety shows. The values svg, text, escpos, epson, sii, citizen, fit, impact and impactb cover SVG, plain text and the ESC/POS variants used by different manufacturers. The generic ESC/POS option is marked experimental. The Star family has its own set: starsbcs, starmbcs, starmbcs2, starlinesbcs, starlinembcs, starlinembcs2, the emustar variants, stargraphic, and three starimpact entries for dot impact printers, of which starimpact is marked experimental.
That long list is the practical reason to use this project rather than writing ESC/POS by hand. The dialect differences between vendors are the hard part, and they are encoded as a configuration value.
Barcodes and QR codes as part of the document
Barcode and QR generation are part of the package rather than something you bolt on, which is what makes the format usable for real retail receipts where the barcode has to be part of the layout rather than an image placed separately.
The barcode method takes a symbol object and returns a form describing the rendered result:
const bar = { data: '1234', type: 'code39', width: 2, quietZone: true };
const barform = receiptline.barcode.generate(bar);
const qr = { data: 'abcdefgh', level: 'm', quietZone: true };
const qrform = receiptline.qrcode.generate(qr);The barcode types cover the ones a retail receipt actually needs. upc handles UPC-A and UPC-E, ean and jan handle EAN-13 and EAN-8, and the check digit can be omitted for both families. code39, itf for Interleaved 2 of 5, codabar and its synonym nw7, code93 and code128 are also available, with code128 as the default.
The geometry parameters are what distinguish a scannable barcode from a decorative one. width is the module width with a range of 2 to 4 and a default of 2, height is the module height with a range of 24 to 240 and a default of 72. The hri flag controls the human readable interpretation line printed under the symbols, which is what a cashier reads when a scanner fails, and quietZone controls the margin of empty space around the symbol, which scanners require in order to lock on. Both default to false, so if you rely on human readable interpretation or on reliable scanning, you have to set them.
The QR generator takes data, a level and a quietZone, and the returned form is the same kind of geometric description.
The wider ecosystem and the tooling around the format
The receiptline package is the Node.js SDK, but the repository README lists a wider set of packages that share the format, and that is what makes it more than a single-purpose library.
ReceiptIO is a Node.js console application for printing, converting and checking printer status. Receipt.js is the browser-side SDK doing the same job for JavaScript, and it comes with a designer tool for editing, previewing and printing, plus a separate free QR code generator. ReceiptSharp is a .NET standard library with the same two capabilities, so a .NET point of sale system can share receipt documents with the JavaScript front end. A Visual Studio Marketplace extension named Receipt Markdown provides editing and preview inside the editor itself.
That last one matters for the workflow argument. If the format is what developers write, then the editing experience around it is where the time is saved, and having a preview inside VS Code means a developer can see the rendered ticket without a printer attached.
The repository also carries printers.json and servers.json at the top level, plus a designer directory, an example directory with subfolders for cloud, command, data, js, nodejs and receipt cases, and a lib directory that is the published entry point. The package.json is minimal: two runtime dependencies, iconv-lite for character encoding conversion and pngjs for PNG handling, and a single test script that runs designer.js. The version is 4.0.4.
The last push was on 2026-07-31 and there are no GitHub releases, so the npm version and the CHANGELOG.md are the version record.
Where ReceiptLine fits, and what it will not do
The honest scope is roll-paper receipts. The format describes an output image of small roll paper, with a fixed character grid measured in characters per line, and that grid is the whole abstraction. It is a good fit for kitchen tickets, retail receipts, parking tickets and kiosk printouts, where the physical medium is a narrow continuous roll.
It is the wrong tool for a paginated invoice, a contract or anything that needs a two-dimensional layout with images and tables. There is no page model, no flowing text and no notion of a document with sections, because a receipt is a column of lines and nothing else. If you need a PDF invoice, you want a document generator, and ReceiptLine will not get you there.
The other limitation is the printer matrix. The supported list names five families, and although the command options cover many Star and ESC/POS dialects, there is no claim of universal coverage. A receipt printer with a proprietary command set outside that list is not supported, and the two entries marked experimental, generic ESC/POS and starimpact, are explicitly a starting point rather than a guarantee.
The realistic alternative for a project that only needs to print a plain receipt is to write the ESC/POS byte sequence directly, which is not hard for a simple text receipt and gives you full control over the printer. The case for ReceiptLine is when the document is more than a few lines, when it includes barcodes, when you need the same document rendered for a screen and a printer, or when you need several printer models supported at once, since the dialect differences are exactly the part that is tedious to get right by hand.
Editorial conclusion
Adopt ReceiptLine when you need to render receipts to thermal printers and to screens from one source, especially in a point of sale, kiosk or kitchen ticket system where paper width varies between devices. Skip it if you only need a PDF invoice, since this is a roll-paper format rather than a document layout engine. Verify first by calling receiptline.transform on a short document with your cpl and encoding settings, then comparing the output against a printed ticket from your own printer model, because character width and encoding defaults differ between models.
Frequently asked questions
What is ReceiptLine and what does it produce?
ReceiptLine is a receipt description language, packaged for Node.js as receiptline, that turns Markdown-like text into either printer commands or SVG images. The transform method takes a document string and an optional destination configuration and returns the printer commands or the SVG.
How do I install ReceiptLine and print a document?
Install it with npm install receiptline, then call receiptline.transform(doc, printer) with a configuration that sets cpl, encoding and command. Setting command to escpos, epson, sii, citizen or one of the star variants selects the printer dialect.
Which receipt printers does ReceiptLine support?
The README lists Epson TM series, Seiko Instruments RP series, Star MC series, Citizen CT series and Fujitsu FP series. The Epson South Asia model and the StarPRNT variant of the Star MC series can print Thai characters with device fonts.
How do I generate a barcode or QR code with ReceiptLine?
Use receiptline.barcode.generate() with data, type, width, height, hri and quietZone, or receiptline.qrcode.generate() with data, level and quietZone. The barcode types include upc, ean, jan, code39, itf, codabar, code93 and code128, with code128 as the default.
Is ReceiptLine available outside Node.js?
Yes. The README lists Receipt.js as a browser JavaScript SDK with a designer tool and QR code generator, ReceiptSharp as a .NET standard library, ReceiptIO as a Node.js console app for printing and printer status, and a Receipt Markdown extension for Visual Studio Code.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/receiptline-receiptline)Was this useful?