Case studies / Tigg POS · Dec 2025 – Sep 2026
The screen is not the end
Three short cases from Tigg POS, each a state that leaves the browser tab: returning to the order after Pay Now, telling a barcode scan from typing, and the dynamic-QR customer display on NiziPOS, a separate device by Yarsa Tech.
Role
Timeline
Team
Platform
Not mine
Measured outcome
the key decision
Design the hand-off, not just the screen: the return path, the scanner and the customer display each get explicit states.
how deep do you want to go?
The screen is not the end
A POS screen is where a cashier works, but most of what matters happens after the cashier looks away. The customer pays at a device on the counter. The scanner keeps typing into the page. The cashier needs to land back where the next order is waiting.
This case collects three small pieces of Tigg POS, the till used by Nepali shops and restaurants. Each one is a state that leaves the browser tab:
| The hand-off | What goes wrong if the state is wrong | |
|---|---|---|
| A | From payment back to the queue | The cashier is dropped on the home screen and has to find their place again, after every bill. |
| B | From a barcode scanner into the page | A scan adds the previous item again, or two scans run together into one code. |
| C | From the till to a customer-facing display | The customer sees a stale QR, or nothing, and asks "did it go through?" |
In all three I tried to follow one rule: design the state, not just the screen. A state has to hold up after the person has stopped looking at it.
A · Returning to the order after Pay Now
In a busy restaurant, the floor lead collects payment from the order list or the kitchen ticket (KOT) queue. Until December 2025, payment always ended on the location's home screen. Whoever started from the queue had to find it again, bill after bill.
The fix sounds trivial: go back. It took me four tries in one week, and two of them were reverted.
| Try | Idea | Why it failed or held |
|---|---|---|
| 1 | A yes/no flag: "came from the order list" | It named one origin only. The KOT queue and retail orders were next, and a yes/no can't name three places. |
| 2 | Use the browser's Back | In a POS, "back" is unpredictable: print dialogs, reloads and links opened directly all change what it means. |
| 3 | Back, but only when the origin is the order list | Still history underneath, so the same problem returned behind a condition. |
| 4 | Name the destination | The screen that opens payment says where it came from. Payment returns there. |
The return fires at every way out of payment: an invoice or credit note saved without printing, or the bill or credit-note print dialog closed. Retail orders can be reached in several ways, so they go back in history but fall back to the retail order list if there is nothing to go back to. A payment started from the order page itself still ends on the home screen, as before.
B · Telling a barcode scan from typing
Most shop scanners behave like a keyboard: they type the code very fast and press Enter. To the order page's search box, a scan and a person typing look the same, unless the design teaches it the difference.
In May 2026 I designed the barcode-mode order page for web and the mobile app. In August 2026 I rewrote how the page tells a scan from typing, because of three failures:
- The scanner's Enter arrived before the search had caught up, so the page acted on the previous result and added the previous product again.
- Two quick scans landed in one box and ran together into one long code.
- When a field was focused, both the field and the page-wide scan listener handled the same keystrokes.
Pace, not a streak
My first rule, on 4 August, looked for a streak of fast keystrokes. Two days later I replaced it with an average. A string counts as a scan if it has at least four characters and arrives at 60 ms per character or faster, on average, from the first character. One slow gap, such as a hiccup on the USB cable, breaks a streak but hardly moves an average.
After the lookup there are three outcomes. No match shows a "No barcode" message. One match is added, or opens the amount keypad when the shop bills by amount. More than one match opens a chooser instead of silently taking the first, which turns a hidden error into a visible choice.
Every scanner we tested with works with this rule.
C · The dynamic-QR customer display on NiziPOS
In many Nepali shops a digital payment starts with a printed QR on a stand: the customer scans it and types the amount. A dynamic QR carries the amount for one bill, so there is nothing to type. The question is where the customer sees it.
NiziPOS, made by Yarsa Tech, is a separate small device that faces the customer and shows the dynamic QR. Tigg POS drives it from the cashier's browser over USB.
Who did what
I designed the overall dynamic-QR payment flow for the app and web. The senior frontend engineer built the QR payment itself: the Fonepay and NepalPay integration, the countdown and the live payment status. For the display, I designed its screens (June 2026) and built the browser side that connects to the device and tells it what to show (July to September 2026).
Five screens for the customer
The customer should see the same moment the cashier sees:
Designing the connection, not just the screens
A USB display is not a second browser window. The page has to find the device, get the browser's permission once, stay connected across reloads and replugs, and never let a missing display block a payment. I designed it as two linked state machines: one for the connection, one for what the display shows. The display only changes while the connection is up; otherwise its updates are skipped and the payment carries on.
From a permanent button to a fallback
The "connect" control had three homes in ten days in July 2026: first a button in the header, then an icon inside the QR modal, and finally only a fallback. The browser needs a click only for the first permission. After that the page reconnects by itself when it loads or when the device is plugged in. What is left for the cashier is one icon, in the one place the display matters, shown only when it is not connected. In retrospect, each move took away a reason for the cashier to think about the device.
Results and what I learned
Status. All three pieces are in tagged releases of Tigg POS: the Pay Now return path in the first POS release of February 2026, the scan detection in August 2026, and the NiziPOS display in September 2026. Every scanner we tested works with the new detection.
Measured outcome: none. I don't have numbers for extra navigation after payment, double-added scans or QR payments completed on the display. If I measured one thing for each piece:
| Piece | What I would measure |
|---|---|
| A · Return path | Extra navigations per payment when paying five orders from the KOT queue (target: none). |
| B · Scanning | How often scans and typing are misclassified, with two or three scanner models and a typist baseline; double-adds per 100 scans. |
| C · Display | Recovery without a page reload after unplugging, reloading, opening a second tab and cancelling the permission prompt. |
Lessons
- 01
Return paths are a design artifact
Two reverts in four days taught me that navigation has to be stated, not inferred from browser history.
- 02
Hardware is a participant
The scanner and the USB port have their own timing and failure modes. The fixes came from modelling their behaviour (pace, permission, a stale connection), not from adding buttons.
- 03
Remove the control when the system can act
The connect button went from permanent, to contextual, to fallback only. The best control for the cashier was the one they almost never see.
Edge cases and states
A · Return path
| Situation | What happens |
|---|---|
| Payment opened from the order list or KOT list | Returns to that list at every exit from payment. |
| Payment opened from retail order cards | Goes back; if there is no history (a link opened directly), falls back to retail orders. |
| Payment opened from the order page | Ends on the location home screen, as before. |
| The page is reloaded mid-payment | The origin is part of the address, so the return still works. |
B · Scanning
| Situation | What happens |
|---|---|
| Scan, one match | Added to the bill; the box clears. |
| Scan, one match, shop bills by amount | Opens the amount keypad (for example "Rs 500 of tomatoes"). |
| Scan, several matches | A chooser opens; nothing is added silently. |
| Scan, no match | The box clears and "No barcode" appears. |
| Typed search, no match | The text stays so the person can keep typing. |
| Two scans in quick succession | The first clears before the second lands, so they can't run together. |
| A field is focused | That field owns its keystrokes; the page-wide listener ignores them. |
C · NiziPOS connection and display
| # | Transition | Why it's designed this way |
|---|---|---|
| 1 | Open a device permitted before, on page load or when it's plugged in; or open from a click on "Connect POS display" | The browser needs a click only for the first permission; after that, reconnecting is silent. |
| 2 | Opening fails because an earlier session still holds the device: close it and retry | Otherwise a working display looks dead until someone reloads. |
| 3–4 | Opened → Connected; a failed update or an unplug → Disconnected | The state follows the device, not what the screen last assumed. |
| 5–6 | Permission prompt cancelled or failed → no automatic prompt until the device is next unplugged | A cashier who dismissed it shouldn't see it on every payment. |
| a–d | QR chosen and generated → QR screen; checking → "Processing..."; result → "Payment Successful" or "Payment Failed" | The customer sees the same moment the cashier sees, with the amount on the QR. |
| e | Leaving payment or finishing → Idle, sent only when the page really is idle | An idle screen sent at the wrong moment can wipe a result the customer is still reading. This was tightened after QA in late July 2026. |
In browsers that can't reach USB devices, the display is simply skipped and payment works as normal.
Trade-offs, credit and sources
Trade-offs I accepted
- Checking instead of listening. The payment screen checks whether the display is connected every 1.5 seconds rather than waiting for the device to announce it. It is simple and hard to break, at the cost of up to a second and a half of lag in the icon.
- Browser support. Talking to a USB device from the page works only in Chromium-based browsers on a secure connection. Elsewhere the display is skipped, so payment never depends on it.
- The display shows only the payment moment. Some POS products mirror the whole cart on a second screen. This one shows the amount, the QR and the result, which is what the customer needs to pay.
Credit
- The kitchen queue, the barcode feature and the original scan listener existed before me; I redesigned and extended them.
- The QR payment modal, its provider integration, countdown and live status were built by the senior frontend engineer from my flow design.
- NiziPOS is a product of Yarsa Tech. I designed its screens for Tigg and built the connection from the POS.
- The senior frontend engineer reviewed and merged most of this work; QA tested it before release.
Sources
Written from the product, my design tickets and my own work history. There were no interviews or usability tests for these pieces, and no usage data. Reasons marked "in retrospect" were not written down at the time. The typing traces in the scanner figure are illustrative, not measurements.