Getting Started

Hardware Setup

NodeDR POS works with standard off-the-shelf retail hardware. No proprietary devices, no drivers to install in most cases.

Barcode scanner

Any USB barcode scanner that acts as a HID keyboardworks plug-and-play. This includes the vast majority of consumer and commercial scanners — when you scan a barcode, the device “types” the code into the focused field and then sends an Enter keystroke. No driver installation, no configuration.

NodeDR POS uses a custom useBarcodeScanner hook in the frontend that distinguishes scanner input from human typing by measuring inter-keystroke timing (scanners type much faster than humans). This means:

  • The scanner works on any page — POS, Inventory, or the product search — without you needing to click a specific input first.
  • Scanning never interferes with text you’re typing manually in a form field.
  • A known barcode adds the product to the cart (or increments quantity if already there).
  • An unknown barcode shows a brief toast notification and does not block the register.

Recommended scanner types

  • 1D USB HID scanners (EAN-13, CODE128, CODE39) — the most common counter scanner. Plug in and go.
  • 2D / QR scanners — work equally well; NodeDR POS stores QR codes in the barcode field the same as 1D codes.
  • Wireless (2.4GHz USB dongle) — the dongle appears as a USB HID device to the OS, so it works identically.
  • Bluetooth scanners — work as long as they are paired to the machine running Docker (they appear as an HID keyboard).

Barcode & QR label generator

Not every product arrives with a printable barcode — loose produce, house brands, or anything repackaged in-store. NodeDR POS has an offline barcode generator built in so you never need an external service.

  • In the Add Product form, click Generate next to the barcode field. The system produces a structurally valid EAN-13 using the 2029 prefix range that GS1 reserves for restricted/internal circulation — these are never real resellable product codes.
  • The code is checked against your existing catalog for uniqueness and retried automatically if there is a collision.
  • From the Inventory page, the barcode icon on any row opens a label modal with a Barcode / QR code toggle. The label is rendered client-side with jsbarcode / qrcode — no network call, fully offline.
  • Print label opens a new tab and calls window.print() — any printer the OS knows about.
  • Download PNG or JPG saves the label as an image for use in Word, Canva, or any label template.

Receipt printing — three modes

After checkout (and from the Sales history), three print buttons are available:

1. Print (browser print dialog)

Opens a formatted receipt in a hidden iframe and immediately calls window.print(). Your OS print dialog appears, showing every printer configured — a USB thermal printer set up via CUPS (Linux/macOS), Windows print spooler, a network printer, or “Save as PDF”. Set up the thermal printer once at the OS level and it shows here automatically.

The backend is not involved in this path at all — it’s a pure browser action.

2. Download PDF

Generates a real PDF server-side using pdfkit (pure JS, no native dependencies, no shell-out) and downloads it. Use this for emailing a receipt, archiving, or printing later from any device. PDF page height is computed per-receipt — a one-item receipt is a short page, not a blank A4.

3. Print via USB (ESC/POS)

Sends raw ESC/POS commands directly to a USB thermal printer from the backend. No print dialog appears — the receipt cuts off the roll immediately after you click.

This mode requires two one-time steps:

Step 1 — Docker USB passthrough

The docker-compose.yml backend service already includes the necessary device passthrough:

# Already in docker-compose.yml — no changes needed unless your setup is unusual
volumes:
  - /dev/bus/usb:/dev/bus/usb
device_cgroup_rules:
  - "c 189:* rmw"   # USB device major 189 only

This is not privileged: true — the backend can only access USB device nodes, nothing else on the host. If you plug in the printer after docker compose up, no restart is needed.

Step 2 — Set paper width in settings

Go to Settings → Receipt → USB printer paper width and select either 80mm (standard) or 58mm (compact). This controls how wide the fixed-column text layout is.

Limitation: generic ESC/POS printers default to single-byte codepage (CP437), not UTF-8. Accented Latin letters are transliterated (café → cafe) and non-ASCII currency symbols fall back to 3-letter codes (€ → EUR). Non-Latin scripts (Devanagari, Arabic, CJK) print as ?. Use the Print or Download PDF buttons when exact Unicode text matters.

Auto-print setting

Enable Settings → Receipt → Print automatically after every sale to skip clicking Print after each checkout. This only applies to the browser print dialog — it does not trigger USB printing (which has no preview step to skip).

Supported printer compatibility

For the browser print and PDF modes, any printer that the OS recognizes works. For the direct USB mode:

  • Any USB thermal printer that advertises the standard USB Printer device class (bDeviceClass 7) works without configuration.
  • Tested with generic 80mm and 58mm ESC/POS thermal receipt printers from common brands.
  • No vendor/product ID to configure — the backend scans for the first connected USB printer class device.
  • Runs on Linux hosts only for the USB path (Docker’s /dev/bus/usb passthrough is a Linux feature). macOS and Windows users should use CUPS / Windows print spooler with the browser print button instead.