Everything it does
Printol is two things in one install: a print server your web app drives over loopback, and a small point-of-sale application the shop can use on its own. They share one local database, so neither has to be kept in sync with the other.
One payload, any paper
The single design decision the whole product rests on: your app sends business data, never layout. The bridge owns the layout, so a shop that swaps a 58mm roll for an 80mm one, or starts printing A4 for B2B customers, does not need you to ship anything.
// The same object, the same call. Only the printer differs.
await printol.print({ templateId: 'pos.receipt.retail', printerId: thermal, data: bill });
await printol.print({ templateId: 'a4.invoice.gst', printerId: laser, data: bill });Printing
- Thermal ESC/POS
- 58mm and 80mm rolls, at 32 and 48 columns. Alignment, bold, double height and width, native QR and barcode commands, partial and full cut.
- A4 and A5 documents
- Rendered to PDF inside the bridge and spooled. The PDF is kept, so your app can also offer it as a download without regenerating anything.
- Cash drawer
- The drawer pulse, on either pin, with a tunable duration for solenoids that need a longer kick.
- Copies and duplicates
- Ask for two copies and get two, with the second marked DUPLICATE if the template says so.
- Raw passthrough
- Already have ESC/POS or ZPL from somewhere else? Send it base64 and the bridge will spool it untouched.
Transports
- System spooler
- Whatever the OS already knows about: USB thermal printers, shared printers, the office laser. Raw byte streams go through the spooler in RAW mode so nothing is re-rendered.
- Network (port 9100)
- JetDirect-style raw TCP, for a printer sitting on the shop LAN with its own IP.
- File
- Writes the byte stream to disk instead of a printer. This is how you develop a template on a laptop with no hardware attached.
Templates
- Block trees, not markup
- A template is a JSON list of blocks — text, rule, table, key/value, QR, cut. The same tree drives the thermal renderer, the PDF renderer and the HTML preview.
- One expression syntax
- Values are {{ handlebars-style }} expressions over your payload, with filters for money, dates, uppercase and amount-in-words.
- Column widths that hold
- Table columns are weights, not character counts, so the same table lays out at 32, 48 or 96 columns without editing.
- Override a built-in
- Push a custom template with a built-in`s id and it shadows it. Delete the custom one and the built-in comes back.
The desktop app
- Catalog and stock
- Items with SKU, unit, tax rate, MRP and rate. Stock is a movement ledger with a reason on every row, so a discrepancy can be traced rather than argued about.
- Billing
- Keyboard-first sale screen, split payments, held bills, reprint. Everything it writes is visible through the API immediately.
- Reports and export
- Day book, item-wise and payment-wise totals, and a CSV export of the raw billing data — the shop owns their numbers.
- Runs at login, lives in the tray
- Installed as a startup item. Closing the window leaves the bridge running; quitting is a deliberate act from the tray menu.
Integration
- Port-range discovery
- No configuration screen. The bridge takes the first free port in 47600–47619 and the SDK finds it.
- OpenAPI, served locally
- The running bridge serves its own OpenAPI 3.1 document, so you can generate a client against the exact build in front of you.
- Server-sent events
- Subscribe to job transitions and printer changes instead of polling.
- Idempotency keys
- Send the same key twice and the second call returns the first job. A retry after a flaky response does not print the bill twice.
What it deliberately does not do
- No cloud sync. The shop's data stays on the shop's machine. If you need it in the cloud, your web app already has it — you sent it.
- No remote access. The listener never binds anything but loopback, so there is no way to reach it from another computer, by design.
- No driver bundling. Printers are reached through the OS spooler or raw TCP. If Windows can print to it, so can Printol.
- No confirmation that ink hit paper. A job reports
donewhen the spooler accepted it. Consumer printers do not tell anybody more than that, and pretending otherwise would be a lie in your UI.