Bananas POS is a small desktop tray app that accepts ZPL over HTTP and raw TCP, then routes jobs to a configurable output target.
The app is built with Go and Fyne. At runtime it starts one process, enforces single-instance semantics, exposes local listeners, and keeps a minimal settings UI in the system tray.
- HTTP input defaults to
:9180 - TCP input defaults to
:9100 POST /zplsubmits print payloads over HTTP and rejects empty payloadsGET /_/healthreports target health, configured station, TCP port, and selected queue for the system print queue target, and returns a non-200 response when the active target is unhealthy- Browser access to the HTTP server is CORS-enabled
Incoming payloads are split into labels and forwarded as job.PrintJob units to the active target.
The tray settings window persists the selected station, target mode, printer, transform, and listener ports between launches. Output mode, printer, transform, and station changes apply immediately. HTTP/TCP listener changes are saved but require an app restart to take effect.
On macOS and Windows, the settings window can also register the app to start automatically at user login. macOS uses a LaunchAgent in ~/Library/LaunchAgents, while Windows writes a current-user startup entry under HKCU\Software\Microsoft\Windows\CurrentVersion\Run.
system-print-queue: submits raw label payloads to the host platform print queue and checks that the selected printer is availablehttp-proxy: forwards jobs to another HTTP endpoint, proxies HTTP traffic through to that upstream, and reports unhealthy if the upstream returns a non-2xx health responseemulator: renders label previews in a local window via Labelary
None: forwards incoming payloads unchangedEpson ESC/POS (debug): available forsystem-print-queue; renders ZPL through Labelary and converts the preview into ESC/POS raster output
Environment variables:
HTTP_ENABLEDdefaulttrueHTTP_LISTEN_ADDRdefault:9180TCP_ENABLEDdefaulttrueTCP_LISTEN_ADDRdefault:9100TARGET_MODEdefaultsystem-print-queuePRINTER_NAMEdefault empty; when no printer is configured, the app resolves the system default printer at startupPROXY_HTTP_URLdefaulthttp://localhost:9100EMULATOR_DPMMdefault8
Run locally:
go run ./cmd/bananas-posBuild:
make buildPackage:
make package-linux
make package-macos
make package-windowsNotes:
- macOS packaging produces a
.appbundle and ad hoc re-signs it duringmake package-macos - the Windows package target expects the workflow toolchain setup from
.github/workflows/release.yml