@ericrisco/rsc 3.3.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +2 -2
  2. package/manifest.json +43 -22
  3. package/package.json +1 -1
  4. package/scripts/lib/default-skill-floor.js +5 -1
  5. package/scripts/lib/domains.js +2 -2
  6. package/scripts/lib/retired-skills.js +4 -0
  7. package/skills/design/SKILL.md +4 -3
  8. package/skills/design/evals/cases.yaml +2 -2
  9. package/skills/react/SKILL.md +2 -1
  10. package/skills/ux/SKILL.md +149 -0
  11. package/skills/ux/THIRD_PARTY.md +32 -0
  12. package/skills/ux/evals/cases.yaml +40 -0
  13. package/skills/ux/references/flows.md +124 -0
  14. package/skills/ux/upstream/UPSTREAM.json +59 -0
  15. package/skills/ux/upstream/ux-designer/GUIDE.md +180 -0
  16. package/skills/ux/upstream/ux-designer/LICENSE +21 -0
  17. package/skills/ux/upstream/ux-designer/references/01-core-principles.md +251 -0
  18. package/skills/ux/upstream/ux-designer/references/02-laws-of-ux.md +330 -0
  19. package/skills/ux/upstream/ux-designer/references/03-accessibility.md +411 -0
  20. package/skills/ux/upstream/ux-designer/references/04-visual-design.md +433 -0
  21. package/skills/ux/upstream/ux-designer/references/05-information-architecture.md +432 -0
  22. package/skills/ux/upstream/ux-designer/references/06-interaction-design.md +495 -0
  23. package/skills/ux/upstream/ux-designer/references/07-forms-and-inputs.md +491 -0
  24. package/skills/ux/upstream/ux-designer/references/08-mobile-ux.md +539 -0
  25. package/skills/ux/upstream/ux-designer/references/09-ux-writing.md +493 -0
  26. package/skills/ux/upstream/ux-designer/references/10-user-research.md +533 -0
  27. package/skills/ux/upstream/ux-designer/references/11-design-systems.md +618 -0
  28. package/skills/ux/upstream/ux-designer/references/12a-presence-awareness.md +395 -0
  29. package/skills/ux/upstream/ux-designer/references/12b-conflict-resolution-sync.md +420 -0
  30. package/skills/ux/upstream/ux-designer/references/13a-canvas-navigation.md +388 -0
  31. package/skills/ux/upstream/ux-designer/references/13b-canvas-objects-performance.md +559 -0
  32. package/skills/ux/upstream/ux-designer/references/14-ai-ux-patterns.md +511 -0
  33. package/skills/ux/upstream/ux-designer/references/15-ethical-design.md +419 -0
  34. package/skills/ux/upstream/ux-designer/references/16-onboarding.md +430 -0
  35. package/skills/ux/upstream/ux-designer/references/17-notifications.md +461 -0
  36. package/skills/ux/upstream/ux-designer/references/18-data-visualization.md +453 -0
  37. package/skills/ux/upstream/ux-designer/references/19-search-ux.md +479 -0
  38. package/skills/ux/upstream/ux-designer/references/20-emotional-design.md +382 -0
  39. package/skills/ux/upstream/ux-designer/references/21-data-tables.md +629 -0
  40. package/skills/ux/upstream/ux-designer/references/22-performance-ux.md +626 -0
  41. package/skills/ux/upstream/ux-designer/references/23-internationalization.md +347 -0
  42. package/skills/ux/upstream/ux-designer/references/24-voice-and-multimodal.md +308 -0
  43. package/skills/ux/upstream/ux-designer/references/25a-barcode-camera-scanning.md +342 -0
  44. package/skills/ux/upstream/ux-designer/references/25b-barcode-scanner-workflows.md +412 -0
  45. package/skills/ux/upstream/ux-designer/references/25c-barcode-display.md +277 -0
  46. package/skills/ux/upstream/ux-usability-foundations/GUIDE.md +285 -0
  47. package/skills/ux/upstream/ux-usability-foundations/LICENSE +21 -0
  48. package/skills/ux/upstream/ux-usability-foundations/references/anti-patterns.md +267 -0
  49. package/skills/ux/upstream/ux-usability-foundations/references/checklists.md +130 -0
  50. package/skills/ux/upstream/ux-usability-foundations/references/decision-prompts.md +340 -0
  51. package/skills/ux/upstream/ux-usability-foundations/references/principle-cards.md +449 -0
  52. package/targets/clone-bootstrap.mjs +1 -1
  53. package/skills/ui-engineering/SKILL.md +0 -113
  54. package/skills/ui-engineering/evals/cases.yaml +0 -38
@@ -0,0 +1,412 @@
1
+ # Scanner-Driven Workflows
2
+
3
+ Warehouse, logistics, retail POS, field service, and healthcare apps where the **scan is
4
+ the primary input**. The devices are rugged handhelds, ring scanners, keyboard-wedge USB or
5
+ Bluetooth scanners, and fixed-mount or presentation scanners. The worker's eyes are on the
6
+ shelf, the parcel, or the patient, and their hands are busy, often gloved. Throughput is
7
+ high: GS1 targets 40–70 items per minute at POS. An unclear failure turns into a
8
+ workaround, and in healthcare workarounds hurt people.
9
+
10
+ This file also holds the **symbology and GS1 primer** that the other barcode files link to.
11
+
12
+ > Consumer camera scanning: [25a-barcode-camera-scanning.md](25a-barcode-camera-scanning.md).
13
+ > Showing codes for others to scan: [25c-barcode-display.md](25c-barcode-display.md).
14
+ > Offline and sync UI in general: [12b-conflict-resolution-sync.md](12b-conflict-resolution-sync.md).
15
+
16
+ ---
17
+
18
+ ## Contents
19
+
20
+ - Devices & What They Mean for UX
21
+ - Scan-First Design
22
+ - Input Capture: Wedge vs. Intent/SDK
23
+ - Scan Routing
24
+ - Eyes-Free Feedback
25
+ - Error Recovery
26
+ - Verification Patterns & Healthcare (BCMA)
27
+ - Batch, Counters & Undo
28
+ - Manual Entry Fallback & Audit
29
+ - Screen Design for the Floor
30
+ - Offline, Retries & Idempotency
31
+ - Training & Multilingual Crews
32
+ - Symbology & GS1 Primer
33
+ - Quick Checklist
34
+ - Common Mistakes
35
+ - Sources
36
+
37
+ ---
38
+
39
+ ## Devices & What They Mean for UX
40
+
41
+ | Device | How scans arrive | UX consequence |
42
+ |---|---|---|
43
+ | Rugged Android handheld (Zebra, Honeywell) | Vendor service: Zebra DataWedge, Honeywell Scan Wedge / Intent API / SDK | Prefer intent/SDK delivery; hardware trigger works on every screen |
44
+ | Ring / wearable scanner (Zebra RS5100, ProGlove) | Bluetooth to a host device | Eyes aren't on the host screen. Route feedback to the wearable (haptic, LED) |
45
+ | USB/BT keyboard-wedge scanner | Keystrokes, like a keyboard | Needs a focused field; the browser can't tell it from typing; keyboard-layout issues |
46
+ | Fixed-mount / POS presentation | Continuous or presentation mode | Dedupe the same code staying in view; dual-marked items |
47
+ | Phone camera inside an ops app | Camera SDK | Fallback only. Turn it off when the device has a scanner (D365 "Scan with camera") |
48
+
49
+ **NFC/RFID** complement barcodes rather than replacing them. HF/NFC suits a deliberate tap
50
+ (badges, patient or asset tags). UHF RFID reads many tags without line of sight. DataWedge
51
+ reports `source=rfid` through the same intent, so one handler can accept both.
52
+
53
+ ## Scan-First Design
54
+
55
+ - **The scan is the navigation.** Each step asks for one thing, the scan answers it, and
56
+ the app moves on. Tapping is the exception.
57
+ - **Name the expected scan** in a large step prompt: "Scan location", "Scan item",
58
+ "Scan pallet LP". Not a generic "Scan or enter here". Microsoft replaced that
59
+ placeholder in the D365 warehouse app.
60
+ - **One scan, many fields.** A GS1 code carries GTIN, batch, expiry, and quantity together.
61
+ Parse it and fill every field it covers, and show the screen only when the worker needs
62
+ to act (D365 multi-field GS1 policy with auto-submit).
63
+ - Show the **current task context** (order, location, remaining qty) at a size readable
64
+ at arm's length. The worker glances at it; they don't read it.
65
+
66
+ ## Input Capture: Wedge vs. Intent/SDK
67
+
68
+ | | Keyboard wedge (keystroke output) | Intent / SDK |
69
+ |---|---|---|
70
+ | Setup | None; works in any text field | App integration per vendor |
71
+ | Needs focus in a field | **Yes** | No; works over dialogs and on any screen |
72
+ | Symbology known | Only via a configured AIM prefix | Yes (`label_type`, `aimId`) |
73
+ | Control chars (GS 0x1D) | Often lost, especially in web apps | Raw bytes available (`decode_data`) |
74
+ | Keyboard-layout bugs | Yes | No |
75
+
76
+ **Prefer intent/SDK** on dedicated devices. Use a wedge when you must: web apps, desktop
77
+ POS, BYO scanners.
78
+
79
+ **Wedge rules:**
80
+ - **Suppress the soft keyboard** on scan fields with `inputmode="none"`. Don't use
81
+ `readonly`, because a readonly field ignores the scanner's keystrokes too.
82
+ - **Configure a suffix** (Enter or Tab) to end the scan. Microsoft recommends letting the
83
+ *device* send Enter instead of auto-submitting in the app, because vendors differ: the
84
+ same app auto-submits on Zebra but waits for confirmation on Honeywell.
85
+ - **Configure a prefix** (AIM symbology ID or a custom one). It identifies scans far more
86
+ reliably than timing, and it tells GS1 data apart from plain data.
87
+ - **Keyboard layout:** the scanner maps characters using its *own* keyboard-country
88
+ setting (US by default). On a German host, Y and Z swap and punctuation breaks. If
89
+ a scan fails format validation, say "Scanner keyboard layout may not match" instead
90
+ of "Item not found".
91
+ - Scanner keystrokes can trigger browser shortcuts. Capture and consume them during a scan burst.
92
+ - **Honeywell** opens URL barcodes in the browser by default (`DATA_PROCESSOR_LAUNCH_BROWSER`
93
+ = true), so no read event reaches your app. Turn it off for GS1 Digital Link or URL codes.
94
+ - **Zebra** keystroke output doesn't deliver control characters as key events to web
95
+ apps by default. GS1 separators vanish (see the primer).
96
+
97
+ **Telling a wedge scan from typing** (use only when you can't use a prefix or intent).
98
+ The thresholds are defaults from the widely used onScan.js library, not a standard.
99
+ Calibrate them per device. Timing breaks with configured inter-character delays (DataWedge allows
100
+ up to 1000 ms), slow Bluetooth HID, and remote-desktop sessions.
101
+
102
+ ```js
103
+ // Timing heuristic: humans type ~100-200 ms/char, scanners burst in a few ms/char.
104
+ const MAX_GAP = 30, MIN_LEN = 6; // onScan.js defaults; calibrate per device
105
+ let buf = '', last = 0;
106
+ addEventListener('keydown', e => {
107
+ if (e.timeStamp - last > MAX_GAP * 3) buf = ''; // long gap -> new burst
108
+ last = e.timeStamp;
109
+ if (e.key === 'Enter' || e.key === 'Tab') {
110
+ if (buf.length >= MIN_LEN) { e.preventDefault(); onScan(buf); }
111
+ buf = ''; return;
112
+ }
113
+ if (e.key.length === 1) buf += e.key; // printable only; GS (0x1D) may not arrive
114
+ }, true); // capture phase: independent of focus
115
+ ```
116
+
117
+ This doesn't stop the characters from also landing in a focused input. Route the scan
118
+ explicitly, or clear the field on detection.
119
+
120
+ ## Scan Routing
121
+
122
+ - **Route by content, not only by focus.** Check the symbology or prefix, parse the payload,
123
+ then decide: SSCC → pallet, GTIN → item, location-label pattern → location. The focused
124
+ field is a hint, not the only rule.
125
+ - **Global listener.** A scan must work while an error, confirmation, or options dialog is
126
+ open. D365 added a dedicated global listener after dialogs were swallowing scans.
127
+ - **Transient UI never steals focus.** A success toast on iOS once left the D365 scanner
128
+ stuck in a non-ready state.
129
+ - **Unexpected type at this step** (e.g. a location scanned when the step wants an item):
130
+ say what was scanned and what's expected ("That's location A-12-03. Scan the item.").
131
+ If the intent is clear, offer the jump.
132
+ - **Unknown GS1 AIs:** skip the element rather than rejecting the whole scan (Microsoft's
133
+ recommended setting). Log it.
134
+ - Keep the scan button for scanning only. OCR, RFID, and other capture methods get their own
135
+ controls (SAP Fiori).
136
+
137
+ ## Eyes-Free Feedback
138
+
139
+ Every scan produces **sound + haptic + visual** feedback, distinct for each outcome, and
140
+ readable without looking closely at the screen.
141
+
142
+ | Outcome | Sound | Haptic | Visual |
143
+ |---|---|---|---|
144
+ | Accepted | Short, high beep | Short single pulse | Full-screen green flash ~1 s + ✓ + value |
145
+ | Warning (accepted, check something) | Distinct mid tone | Two short pulses | Amber banner + text |
146
+ | Rejected / mismatch | Low, long, or repeated tones | Long or double pulse | Red full-screen state + ✕ + reason; stays until acknowledged or rescanned |
147
+
148
+ - The conventions come from Zebra's classic beeper codes (short high = good decode; long
149
+ low = error), D365/ProGlove wearable haptics (single crisp pulse = OK; double pulse =
150
+ "stop and check the screen"), and the DataWedge decode screen notification (green overlay,
151
+ 1000 ms default, adjustable 500–1500 ms).
152
+ - **Never colour alone** (WCAG 1.4.1). Pair colour with an icon, text, and a sound and
153
+ haptic pattern that differ per outcome.
154
+ - **Too fast:** if the system can't keep up, say so with a distinct alert and "rescan"
155
+ (D365 added exactly this).
156
+ - Give **per-user volume and vibration settings** (D365: vibration 0–5, sound 0–10, separate
157
+ success/failure/warning sounds). Floors are loud, and hospital wards are quiet at night.
158
+ - **Meaningless beeps get muted.** In Koppel's BCMA study, staff disabling audio alarms was a
159
+ workaround, and confusing alert beeps and noise were listed as causes. Keep the sound
160
+ vocabulary small and distinct.
161
+ - Wearables: send the result to the ring or glove (LED + haptic). The host screen may be in a
162
+ pocket or on a cart.
163
+
164
+ ## Error Recovery
165
+
166
+ | Situation | Handling |
167
+ |---|---|
168
+ | Wrong item for this pick | Block. Show expected vs scanned (name + image), error feedback, require a rescan. No "accept anyway" without a reasoned, audited override |
169
+ | Duplicate scan | Same code in view: same-symbol timeout. Same code via two channels (wedge + intent both on): dedupe (D365 duplicate-scan protection). Intentional repeat: count it and show the new total |
170
+ | Unknown code | Show the raw value and symbology, and offer manual lookup or "report label". Never add unknown barcodes to the master data on the spot (see ISMP below) |
171
+ | Over-scan (qty exceeded) | Stop at the limit, show "10 of 10 — this one is extra", and offer to put it back or report it |
172
+ | Invalid format / check digit | "Couldn't read that correctly — rescan", not "Not found". Possibly a short read or layout issue |
173
+ | Server error | Show the server's **specific** message. D365 had to fix a generic failure message that hid it |
174
+
175
+ - **No modal traps.** Error states clear with the next valid scan or a trigger press, not only
176
+ by tapping a small OK button with gloves on.
177
+ - **Crowded labels:** enable picklist mode (decode only what's under the crosshair) or ask
178
+ the user to cover the other codes.
179
+ - **Dual-marked retail items** (1D + 2D within 50 mm): count them once.
180
+
181
+ ## Verification Patterns & Healthcare (BCMA)
182
+
183
+ **Warehouse:** location → item → quantity confirmation, where each scan verifies the
184
+ previous instruction. A confirmation scan (D365 "ProductConfirmation") is cheaper than
185
+ a mis-pick.
186
+
187
+ **Barcode medication administration** is the best-studied scanning workflow:
188
+ - **Poon et al., NEJM 2010** (14,041 administrations): with BCMA + eMAR, non-timing
189
+ administration errors fell 41.4%, potential ADEs from them fell 50.8%, timing errors fell
190
+ 27.3%, and transcription errors were eliminated. Errors were reduced, not eliminated.
191
+ - **Koppel et al., JAMIA 2008:** 15 workaround types and 31 causes. Patient wristbands were
192
+ taped to carts, doorjambs, or belt rings; a single package was scanned for several doses;
193
+ documentation happened before administration; audio alarms were disabled. Causes included
194
+ unreadable or crinkled labels, chewed wristbands, non-barcoded meds, dying batteries, poor
195
+ Wi-Fi, and emergencies.
196
+ - **van der Veen et al., JAMIA 2018:** workarounds in 66% of administrations, with 3.06×
197
+ the odds of error. The most common were not scanning at all, and no wristband.
198
+ - **ISMP:** hard-stop product scanning; overrides only for real emergencies; track compliance
199
+ and override rates; fix the barriers behind workarounds. In an ISMP case, adding
200
+ unscannable barcodes on the fly let a strength mismatch (15 mg vs 5 mg) get overridden.
201
+
202
+ **Design takeaways:**
203
+ - Make **compliance easier than the workaround**: bedside wristband reprint, a flow that
204
+ works offline, and readable feedback in dim rooms.
205
+ - Scan the patient *and* the medication. A manual-key path must still run the same
206
+ verification.
207
+ - Overrides are visible, need a selected reason, and are audited.
208
+ - US drug barcodes are changing: the FDA's 2026 final rule moves to a 12-digit NDC and allows
209
+ 2D barcodes (effective 2033, with a transition to 2036). Parsers must accept both NDC
210
+ lengths and 2D symbols.
211
+
212
+ ## Batch, Counters & Undo
213
+
214
+ - **Continuous scanning:** show a running count and the **last scanned value** prominently.
215
+ Allow **one-tap undo of the last scan** in a non-modal way. (There's no published standard;
216
+ this is the common pattern.)
217
+ - **Batch round trips.** Sending a server request per scan doesn't scale at many scans per
218
+ second (Microsoft's multi-scan pages). Collect scans locally and submit them in one call
219
+ with per-item results.
220
+ - **Multi-barcode capture** (Zebra NG SimulScan) reads several codes per trigger. Show
221
+ which codes were read and which were missed on a visual of the label.
222
+ - **Quantity from the scan** can override the default ("PO for 10, scanned 5"), but only
223
+ when configured, and the difference is shown.
224
+
225
+ ## Manual Entry Fallback & Audit
226
+
227
+ - **Every scan step has a manual path.** Labels get crinkled, smudged, torn, missing, or
228
+ printed on a curved surface (ISMP asked manufacturers to stop printing across round
229
+ surfaces).
230
+ - **Validate typed and scanned values the same way:** check digit, field ranges (month
231
+ 01–12), length limits, numeric-only fields.
232
+ - Use a numeric keypad for numeric IDs (`inputmode="numeric"`), and support external numpads.
233
+ - **Record the input method** (scan vs manual vs override) with a reason. Track the manual
234
+ and override rate per user, site, and product. A rising rate points to a bad label or a
235
+ broken flow, not a bad worker.
236
+
237
+ ## Screen Design for the Floor
238
+
239
+ - **Scalable UI.** D365 gives text scale 70–400% and button scale 50–200%, plus a
240
+ high-contrast theme. Offer comparable ranges.
241
+ - **Handedness.** Let the user put the primary button bottom-right or bottom-left (D365
242
+ "best button position").
243
+ - **Gloves.** Glove sensitivity is a *device* touch-panel mode (Zebra: glove, wet, finger).
244
+ The app's part is larger targets. The bare-hand baseline is ~9 mm (48dp; Parhi et al.
245
+ found 9.2–9.6 mm for one-handed thumb use). The "15–20 mm for gloves" figures are vendor
246
+ blog heuristics, so test with the real gloves.
247
+ - **Sunlight and freezers.** Reflections collapse contrast. Use a high-contrast theme,
248
+ heavy weights, no light-grey text, and never colour-only state.
249
+ - **Hardware trigger** scans from every screen, and a trigger press must never activate an
250
+ on-screen button by accident (D365 fixed a trigger submitting a summary step).
251
+ - **Product photo** on pick steps allows visual confirmation alongside the scan.
252
+ - **Shared devices:** make the signed-in worker obvious (name plus a per-user colour theme, as in D365).
253
+ - Small truck-mount and vehicle screens (~640 px) need their own layout.
254
+
255
+ ## Offline, Retries & Idempotency
256
+
257
+ - **Every scan transaction gets a client ID, and the server dedupes it.** D365 once resent
258
+ a submitted page after a timeout without telling the worker, which could complete warehouse
259
+ work twice.
260
+ - **Tell the worker about retries**, and never silently resubmit.
261
+ - **Keep in-progress state** when the network drops. Don't bounce the worker to sign-in and
262
+ lose the task (another D365 fix).
263
+ - Wi-Fi dead zones cause workarounds (Koppel), so offline or degraded mode is a requirement.
264
+ Queue scans locally with a visible pending count, sync with per-item results, and show
265
+ conflicts (e.g. stock already moved) as a reviewable list. See
266
+ [12b](12b-conflict-resolution-sync.md).
267
+
268
+ ## Training & Multilingual Crews
269
+
270
+ There's little research here; these are heuristics:
271
+ - Scan-driven steps need less reading. Short verbs plus icons, and sound and haptics that
272
+ carry meaning without language.
273
+ - **Language per user, not per device.** Shared devices change hands every shift.
274
+ - Step instructions that can be switched off once learned (D365 "Don't show again").
275
+ - Test RTL layouts for the crews you actually have.
276
+ - Inadequate training is a documented cause of workarounds (Koppel). Build a practice or
277
+ sandbox mode.
278
+
279
+ ---
280
+
281
+ ## Symbology & GS1 Primer
282
+
283
+ ### Symbologies
284
+
285
+ | Symbology | AIM ID | Typical use |
286
+ |---|---|---|
287
+ | EAN-13 / UPC-A / UPC-E | `]E0` | Retail item at POS |
288
+ | EAN-8 | `]E4` | Small retail items |
289
+ | ITF-14 | `]I1` (scanner checked the check digit) / `]I0` | Outer cartons |
290
+ | GS1-128 | `]C1` | Logistics labels: SSCC, batch, expiry |
291
+ | Code 128 (non-GS1) | `]C0` | Internal IDs |
292
+ | Code 39 | `]A0` | Legacy internal |
293
+ | GS1 DataBar | `]e0` | Fresh food, coupons |
294
+ | GS1 DataMatrix | `]d2` | Healthcare UDI, pharma |
295
+ | Data Matrix with GS1 Digital Link | `]d1` | Retail 2D |
296
+ | QR with GS1 Digital Link / GS1 QR | `]Q1` / `]Q3` | Retail 2D, consumer links |
297
+ | PDF417 | — | IDs, tickets, boarding passes |
298
+
299
+ - AIM identifiers are **generated by the decoder**, not stored in the symbol, and they're
300
+ case-sensitive. Have the scanner prefix them so the app can tell `]C1` (GS1) from `]C0`
301
+ (plain) without guessing.
302
+ - **Enable only the symbologies the screen needs.** Zebra recommends disabling every
303
+ decoder the app doesn't need, to improve scanning performance. Honeywell likewise warns
304
+ that enabling everything degrades decoding. Use per-screen profiles (DataWedge profiles
305
+ bind to the app or activity).
306
+ - **Short reads:** ITF and Code 39 without a fixed length or check digit can decode a
307
+ fragment as a valid shorter number. If you must enable them, restrict lengths.
308
+ - 1D laser scanners can't read 2D codes or (reliably) screens. See [25c](25c-barcode-display.md).
309
+
310
+ ### GS1 element strings
311
+
312
+ - Element strings look like `(01)09521101530001(17)210119(10)AB-123`. The parentheses
313
+ exist **only in the human-readable text**, never in the data.
314
+ - **FNC1 in the first position** marks a GS1 symbol. Variable-length fields are ended by a
315
+ separator, which **decodes as `<GS>` (ASCII 29, 0x1D)**. GS1 warns that receiving systems
316
+ often mangle it, and keyboard wedges often drop it. Configure the scanner to substitute a
317
+ printable character (e.g. `~`), or use intent or raw-byte delivery.
318
+ - **Predefined-length AIs** are recognised by their first two digits only: 00, 01, 02, 11–17,
319
+ 20, 31–36, 41. Every other AI needs a separator unless it comes last, **even if its own
320
+ definition says "fixed length"**.
321
+ - Common AIs:
322
+
323
+ | AI | Meaning | Format |
324
+ |---|---|---|
325
+ | 00 | SSCC (logistic unit) | 18 digits |
326
+ | 01 | GTIN | 14 digits |
327
+ | 10 | Batch/lot | up to 20 alphanumeric |
328
+ | 17 | Expiry date | YYMMDD |
329
+ | 21 | Serial number | up to 20 alphanumeric |
330
+ | 30 | Variable count | up to 8 digits |
331
+ | 310n | Net weight, kg (n = decimals) | 6 digits |
332
+
333
+ - **Dates:** YYMMDD, with the century resolved within −49 to +50 years of today. **DD = 00
334
+ means the last day of the month** (`160200` = 2016-02-29). Show the resolved date, never
335
+ the raw "00".
336
+
337
+ ### Check digits
338
+
339
+ - GS1 mod-10 algorithm for GTIN, GLN, and SSCC: weight the digits ×3, ×1 alternately,
340
+ **starting with ×3 at the rightmost data digit**, sum them, and subtract the sum from the
341
+ next multiple of 10. It catches all single-digit errors and most adjacent transpositions.
342
+ - **The scanner usually does not check it.** EAN/UPC readers verify the check digit, and
343
+ ITF-14 does only when the AIM ID is `]I1`. For GS1-128, DataBar, DataMatrix, QR, and
344
+ DotCode, the symbol's own error detection guarantees the *decode* but not the GTIN.
345
+ GS1 says the application **shall** verify it. Validate typed entries the same way.
346
+
347
+ ### GS1 Digital Link
348
+
349
+ - A URI form of GS1 data, e.g. `https://id.gs1.org/01/09520123456788/10/ABC123?17=180426`.
350
+ The primary key (01 GTIN, 00 SSCC, 414 GLN) and its qualifiers (10, 21) go in the path,
351
+ and attributes (17 expiry) go in the query. The GTIN is always zero-padded to 14 digits.
352
+ - **Any domain** may host it. Parse by path syntax, not by the `id.gs1.org` domain.
353
+ - The same code serves the shopper's phone (opens a web page) and the POS (reads the GTIN).
354
+ The POS app must **not** open a browser (see the Honeywell default above).
355
+
356
+ ### Sunrise 2027 (2D at retail POS)
357
+
358
+ - GS1's goal: retail POS globally able to read the GTIN from both linear and 2D codes by
359
+ the **end of 2027**. Accepted 2D forms are GS1 DataMatrix, and Data Matrix or QR carrying
360
+ GS1 Digital Link.
361
+ - It's a milestone, not a switch-off. Products keep the linear barcode until 90% of POS
362
+ systems are 2D-capable, so POS must **dedupe dual-marked items**.
363
+ - The opportunity is the extra data at the till: block sales of expired items, flag recalled
364
+ batches.
365
+
366
+ ---
367
+
368
+ ## Quick Checklist
369
+
370
+ - [ ] Each step names the expected scan; one GS1 scan fills every field it covers
371
+ - [ ] Intent/SDK delivery on dedicated devices; wedge fields use `inputmode="none"` and a suffix
372
+ - [ ] Scanner prefix (AIM ID) configured; scans routed by content and type, not only focus
373
+ - [ ] Scans work over dialogs; toasts and transient UI never steal focus
374
+ - [ ] Distinct success/warning/error sound + haptic + full-screen visual; not colour-only
375
+ - [ ] Wrong / duplicate / unknown / over-scan each have a specific message and a rescan path; no modal traps
376
+ - [ ] Only needed symbologies enabled, per screen; ITF/Code 39 length-restricted
377
+ - [ ] App verifies check digits; GS separator survives the input path; DD=00 dates resolved
378
+ - [ ] Manual entry on every step, validated like scans, logged with method and reason
379
+ - [ ] Overrides reasoned, audited, and rate-tracked
380
+ - [ ] Client transaction IDs + server dedupe; no silent resubmits; offline queue with pending count
381
+ - [ ] Text/button scaling, handedness, high contrast, large targets tested with gloves
382
+ - [ ] Per-user language and sound/vibration settings on shared devices
383
+
384
+ ## Common Mistakes
385
+
386
+ - A generic "Scan or enter" prompt on every step
387
+ - Scans lost because focus left the input, or a dialog was open
388
+ - Soft keyboard popping up over the screen on every scan field
389
+ - One beep for everything, or silence. Workers mute feedback that means nothing
390
+ - A red flash as the only sign of an error
391
+ - An error dialog that needs a precise tap to dismiss before the next scan
392
+ - Enabling every symbology "to be safe", which is slower and risks short reads
393
+ - Trusting the scanner to validate the GTIN check digit
394
+ - Hard-coding `id.gs1.org` or stripping GS characters in a GS1 parser
395
+ - Letting staff register unknown barcodes on the spot (the ISMP strength-mismatch case)
396
+ - A manual-entry path that skips the verification the scan would have done
397
+ - Silent retry after a timeout, completing the work twice
398
+ - Treating a high override rate as a training problem instead of a label or flow problem
399
+
400
+ ---
401
+
402
+ ## Sources
403
+
404
+ - [GS1 General Specifications](https://www.gs1.org/standards/barcodes-epcrfid-id-keys/gs1-general-specifications) (§5.1.3 symbology IDs, §7.2.7 check digit verification, §7.8 separators, §7.9 check digit) · [GS1 Digital Link URI syntax](https://ref.gs1.org/standards/digital-link/uri-syntax/) · [GS1 2D in retail](https://ref.gs1.org/guidelines/2d-in-retail/) · [GS1 US Sunrise 2027](https://www.gs1us.org/industries-and-insights/by-topic/sunrise-2027)
405
+ - [Zebra DataWedge — intent output](https://techdocs.zebra.com/datawedge/latest/guide/output/intent/) · [keystroke output](https://techdocs.zebra.com/datawedge/latest/guide/output/keystroke/) · [barcode input & feedback](https://techdocs.zebra.com/datawedge/latest/guide/input/barcode/) · [profiles](https://techdocs.zebra.com/datawedge/latest/guide/profiles/)
406
+ - [Honeywell Mobility SDK](https://sps.honeywell.com/us/en/software/productivity/development-tools/mobility-sdk-android) · [Honeywell — keyboard layout](https://sps-support.honeywell.com/s/article/Scanner-does-not-support-my-keyboard-layout-wrong-characters-are-displayed)
407
+ - [Microsoft D365 Warehouse Management — GS1 barcodes](https://learn.microsoft.com/en-us/dynamics365/supply-chain/warehousing/gs1-barcodes) · [auto-submit behavior](https://learn.microsoft.com/en-us/dynamics365/supply-chain/warehousing/warehouse-app-autosubmit-behavior) · [haptic feedback](https://learn.microsoft.com/en-us/dynamics365/supply-chain/warehousing/warehouse-app-haptic-feedback) · [user settings](https://learn.microsoft.com/en-us/dynamics365/supply-chain/warehousing/warehouse-app-user-settings-themes) · [what's new](https://learn.microsoft.com/en-us/dynamics365/supply-chain/warehousing/warehouse-app-whats-new) · [multi-scan pages](https://www.microsoft.com/en-us/dynamics-365/blog/it-professional/2018/12/20/customizing-the-warehouse-mobile-app-multi-scan-pages/)
408
+ - [MDN — inputmode](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inputmode) · [onScan.js](https://github.com/axenox/onscan.js)
409
+ - [Poon et al., NEJM 2010 — BCMA and eMAR](https://www.nejm.org/doi/full/10.1056/NEJMsa0907115) · [Koppel et al., JAMIA 2008 — BCMA workarounds](https://pmc.ncbi.nlm.nih.gov/articles/PMC2442264) · [van der Veen et al., JAMIA 2018](https://academic.oup.com/jamia/article-abstract/25/4/385/4091349) · [ISMP workaround case (NABP)](https://nabp.pharmacy/news/blog/regulatory_news/ismp-common-workaround-contributes-to-override-of-barcode-alert/) · [ISMP — round surfaces](https://home.ecri.org/blogs/ismp-news/ismp-calls-for-manufacturers-to-stop-printing-medication-barcodes-across-round-surfaces)
410
+ - [FDA 2026 NDC format and barcode rule](https://www.federalregister.gov/documents/2026/03/05/2026-04368/revising-the-national-drug-code-format-and-drug-label-barcode-requirements) · [21 CFR 201.25](https://www.ecfr.gov/current/title-21/chapter-I/subchapter-C/part-201/subpart-A/section-201.25)
411
+ - [Parhi et al. 2006 — target size for one-handed thumb use](https://www.microsoft.com/en-us/research/wp-content/uploads/2006/01/parhi-mobileHCI06.pdf) · [Zebra touch panel modes](https://docs.zebra.com/us/en/mobile-computers/handheld/tc5-series/tc52-product-reference-guide/settings/display-settings/setting-touch-panel-mode.html)
412
+ - [RFID in healthcare scoping review](https://pmc.ncbi.nlm.nih.gov/articles/PMC9398041/)