ZPLKit
Open-source Swift toolkit for Zebra label printing
Four Modules
Import only the parts you need. Each module builds on the core generator:
- ZPLKit — generate ZPL with Swift result builders: text, multi-line text blocks, shapes, serial numbers, and images with dithering
- ZPLKitRenderer — a native renderer that parses ZPL and produces PNG previews, no external dependencies
- ZPLKitPrinter — send labels over TCP, discover printers via Bonjour, and configure or query them with an async/await API
- ZPLKitVerifier — confirm what actually printed using the Vision framework for barcode decoding and text OCR
Quick Start
Describe the label declaratively, then render it to a ZPL string:
import ZPLKit
let label = ZPLLabel(width: 4, height: 6, dpi: .dpi203) {
Text("PARTS BIN A-7", at: .inches(0.25, 0.25))
.font(.default, height: .inches(0.2))
Barcode128("BIN-A7-001", at: .inches(0.25, 0.6))?
.height(.inches(0.5))
.showText(true)
Box(at: .inches(0.2, 0.2), width: .inches(3.5), height: .inches(1.2))
.thickness(2)
}
let zpl = label.render()
Barcodes and Graphics
Built-in support for the symbologies you actually reach for: Code 128, Code 39, QR, DataMatrix, PDF417, Aztec, EAN-13/8, UPC-A/E, Interleaved 2 of 5, and USPS Intelligent Mail. Photos and images render to monochrome bitmaps with Floyd-Steinberg or Atkinson dithering and aspect-fill cropping.
Preview Without a Printer
Render ZPL straight to a PNG so you can show a live preview in your UI:
import ZPLKitRenderer
let renderer = ZPLRenderer()
let pngData = try renderer.renderToPNG(zpl, width: 812, height: 1218)
Print Over the Network
Send to a known printer, or discover one on the local network with Bonjour:
import ZPLKitPrinter
// Send to a known printer
let printer = ZPLPrinter(host: "192.168.1.100")
try await printer.send(label.render())
// Or discover printers on the network
let browser = ZPLPrinterBrowser()
for await discovered in browser.printers {
try await ZPLPrinter.send(zpl, to: discovered)
break
}
You can also query status, info, memory, and full configuration, or set a printer up from scratch with type-safe presets.
Verify the Output
Rendered a label? Confirm it contains what it should, using on-device Vision:
import ZPLKitVerifier
let verifier = ZPLVerifier()
let check = try await verifier.verify(cgImage) {
Barcode(.qr, containing: "SKU-123")
Text("FRAGILE")
}
if !check.passed { print(check.summary) }
Installation
Add ZPLKit to your Package.swift. (The first tagged release is on the way; until then, pin to main.)
dependencies: [
.package(url: "https://github.com/jonathanspiva/zplkit.git", branch: "main")
]
Then add the products your target needs:
.target(name: "YourTarget", dependencies: [
"ZPLKit", // generation
"ZPLKitRenderer", // previews
"ZPLKitPrinter", // network printing
])
Requirements
- Swift 6.3+ (Swift 6 language mode,
Sendablethroughout) - iOS 26+, macOS 26+, tvOS 26+, watchOS 26+
- No third-party dependencies
- MIT licensed
The latest-OS-only floor is intentional: ZPLKit uses the newest Swift concurrency and Vision APIs rather than carrying back-compatibility shims.
Why Open Source
Zebra printers are everywhere, but working with ZPL in Swift has always been painful. We built ZPLKit for The Labeler and released it separately so other developers don't have to reinvent the wheel. It also ships 124 ZPL test fixtures you can reuse to validate any parser or renderer.