All docs

Receiving & box scanning

Box-level scanning is how a small operation gets a real WMS workflow without a real WMS. Every received unit is traceable to a specific box, and your warehouse team picks from one box at a time so the next box's labels stay on it until you need them.

What "box-level" means

When you receive a PO, the app generates one receipt box per pre-set unit count. A 5,000-unit PO with 100 units per box gives you 50 boxes. Each box gets:

  • A unique workspace-scoped barcode (e.g. K9-42)
  • A printed label with the SKU, qty, and PO reference
  • A state: UNOPENEDOPENDEPLETED

Boxes give your warehouse team a physical handle on the inventory: which box is open, which one to pull from next, which ones are still sealed.

Generating boxes

When you click Receive on a PO, the receipt page asks for units per box. The app then creates the right number of boxes per receipt line. You can edit the count if your supplier's pack-out is non-standard.

Boxes are unique per workspace, not globally — your K9-42 and another tenant's K9-42 won't collide.

Printing labels

After receiving, open the receipt detail page and click Print labels. Two sizes:

  • Large (4×6") — portrait, default. Works on a thermal label printer
  • Small (3×2") — landscape, toggleable

Four design variants: classic, editorial, bold, minimal. Tack ?variant=bold (or any other) onto the URL to switch. Real Code-128 barcodes render via bwip-js; they scan reliably on phone cameras and 1D scanners.

A note on print stylesheets: most browsers don't print background colors by default. The labels use borders instead of background fills so they print cleanly without you needing to enable "Background graphics" in the print dialog.

Scanning to deplete

Open Receiving in the sidebar. Two paths to enter a code:

  • Text input — type the box code, hit enter
  • Camera scanner — point your phone at the barcode (uses the device's camera via @zxing/browser)

Scanning a code:

  • If the box is UNOPENED: marks it OPEN and depletes any previously open box for the same SKU (one open box per SKU is the rule)
  • If the box is OPEN: nothing happens — already in use
  • If the box is DEPLETED: shows an error

The "Mark depleted" checkbox lets you flag a box as fully consumed in one shot — useful for gift events, single-customer pulls, or cases where you don't open a fresh box.

Box state and inventory

Box state is operational, not financial. Opening or depleting a box does not move inventory cost. Inventory is reduced via:

  • Sales import (Shopify/Amazon CSV → outbound SALE movements)
  • Write-offs (WRITE_OFF movements with a reason code)
  • Cycle-count adjustments (COUNT_ADJUSTMENT movements)

Box state is just the warehouse team's signal for which physical box to grab from next. The cost ledger and box state are independent ledgers that happen to share the same product.

Phone camera + HTTPS

iOS Safari blocks getUserMedia on plain http:// (except on localhost). For phone-camera testing during dev, route through an ngrok HTTPS tunnel. In production this is a non-issue — the deployed app is on HTTPS by default.