The anti-rip-off

1QR — scan to pay with total confidence

Scan once. See the real total. Pay before anything moves.

Paying abroad is mostly guesswork: a QR code, a number you half-trust, and a real cost you only learn from your statement days later — after the dynamic-conversion screen and the ~3% markup have done their quiet work. 1QR inverts that. You scan once and see the real total upfront — baht as the big number, your home currency beside it — with every fee itemised at the mid-market rate and the savings versus a typical card spelled out before you commit. Pay, and you keep a durable receipt that records exactly what you paid and how. The whole product is one promise made literal: see the true cost before your money moves.

Fully interactive — run the whole flow: home → scan → the itemised total → pay → the receipt, then rate a merchant or manage your payment methods. The screen-jumper bar at the top spans the full width and the phone itself stays centered. The camera scan is simulated here; the live build uses the device camera.

The problem: you learn the real cost too late

Abroad, the number you act on is almost never the number you pay. Dynamic currency conversion, a hidden FX markup, and fees buried in settlement do the damage after you've already tapped.

"≈ $11.84, fees applied later" tells you nothing you can use at the stall. You can't see the rate, you can't see the markup, and by the time the real figure lands on your statement the moment to refuse is long gone. Worse, opacity trains the wrong habit: you stop checking, because checking was never possible. The first design decision was to treat that opacity itself as the bug to fix — to move the entire reckoning to before the money moves.

The black box · what most terminals show

You'll be charged ≈ $11.84

No rate shown. No itemised fees. A ~3% conversion markup folded into one number, settled later. No receipt you can keep. A verdict.

The open total · what 1QR shows

Total you pay ฿420.00

≈ $11.50 · rate 36.52

mid-market · no markup 1QR fee ฿0 save ≈ $0.34

Every fee itemised at the mid-market rate before you commit — and a flag if the name or amount looks off.

The thesis: the real number, the open fee, the kept proof

Three properties, non-negotiable. Local currency dominant. Fees never fine print. Proof is a first-class output.

Everything in 1QR descends from one promise: total confidence at the moment of payment. The design is numbers-first and language-light — a traveller who doesn't read Thai can still act on every screen — because trust here isn't a reassuring tone of voice, it's a set of structural guarantees you can check before you tap. Show the true total in the currency that matters. Itemise every fee at the mid-market rate. Hand back a receipt that proves what happened. Get those three right and the rip-off has nowhere to hide.

See the real total

Baht is the big number; your home currency sits beside it. Nothing is priced against a rate you can't see.

Every fee in the open

The 1QR fee and network fee are itemised at the mid-market rate — no DCC, no hidden markup, and the savings versus a typical card spelled out.

Keep the proof

Every payment yields a durable receipt — reachable from Activity in two taps, forever, offline — that records the source it paid from.

Screen 2 · Verify who you're paying, before you pay

Most rip-offs don't begin at the total — they begin one screen earlier, when you trust a sticker without knowing whose account is behind it.

So the anti-rip-off check is moved before the number: the merchant screen matches the name on the code to the registered PromptPay account, lays the trust checks inline, and shows tenure with a dispute count. Why this is the best choice — a confidence problem is cheapest to catch before any money is in play, and a swapped sticker is exactly the failure a total alone can't reveal. The checklist is built to slow you down only when something is off; if every signal is green it reads in a glance, and a flag path sits right there if it isn't. The benefit: you arrive at the total already knowing the stall is real.

Merchant found

Som Tam Nua — Stall 14

Street food · Chatuchak Market, Bangkok

★ 4.8 · 1,204 tourists paid here · ~120m

Identity verified
The name on the code matches the registered PromptPay account.
No hidden FX markup
You'll pay the mid-market rate, with every fee shown in full.
Both currencies shown
The local total and your home estimate, side by side, every time.
Report this merchant
Something look off? Flag it before you pay, not after.
On 1QR since Mar 2024 · 0 disputes
Hours 9:00–22:00 · open now

See all 1,204 traveler reviews

A specimen of the merchant card and its trust checklist — the live version is the first screen after a scan in the prototype above.

Screen 3 · The itemised reckoning you read before you pay

"Total you pay" isn't a summary line at the bottom of a flow. It's the whole product, shown in full before a single baht moves.

The card leads with baht as the big figure, keeps your home-currency estimate as the supporting line, and locks the rate with a visible countdown — honest about the fact that FX moves while you decide. Then it opens the arithmetic: each fee carries its reason right beside it (mid-market · no markup; free under ฿1,000; covered by 1QR), ending in an explicit savings line. Why this is the best choice — folding fees into settlement is exactly how the rip-off works, so the load-bearing move is to itemise them before commit, turning a number you'd have to trust into a decision you're free to refuse. The benefit: nothing about the cost is discovered after the fact.

You pay
฿420.00
THB
≈ $11.50 USD home estimate
Rate locked 00:58

Rate & fees — nothing hidden

Exchange rate · mid-market · no markup 1 USD = 36.52 THB
Merchant amount ฿420.00 · ≈ $11.50
1QR fee · free under ฿1,000 ฿0.00
Network fee · covered by 1QR ฿0.00
Total you pay ฿420.00 · ≈ $11.50
You save ≈ $0.34 vs a typical card's ~3% conversion markup

Before you pay

Paid to Som Tam Nua
Method 1QR balance · USD
Arrives instantly, in THB
You confirmed the stall name matches the code

The rate is locked the moment you land here. If the countdown lapses, 1QR re-quotes at the new mid-market rate before anything moves — never silently.

This is the screen the whole product is built around — open the prototype above, scan, and watch the total itemise itself, reason by reason, before you commit.

Screen 4 · One explicit commitment moment

Between reading the total and moving money there is exactly one deliberate act — a hold, not a tap.

A single tap is too easy to do by accident with a phone in one hand and a bowl of som tam in the other, and an accidental send is the kind of small betrayal that ends trust in a payments app. So commit is a press-and-hold of about a second, and the source you're paying from is shown read-only at the very moment of commitment — you confirm exactly what's about to be charged, with nothing left to change. Why this is the best choice — the one irreversible action in the flow deserves the one piece of friction in the flow. The benefit: sending money is always something you chose to do, paired with biometric confirmation so it's also unmistakably you.

Confirm payment

฿420.00

to Som Tam Nua — Stall 14

≈ $11.50 USD · rate 36.52 · locked 00:42

1QR 1QR balance · USD
Face ID to pay

Hold for ~1s — one explicit commitment moment.

A specimen of the confirm screen — the fill shown here animates as you press in the live prototype, then hands off to "Sending ฿420.00…".

Shows its work: the source can't drift between screens

One pay-source line — brand chip, nickname, masked tail — rendered identically on the total, at the commit moment, and on the receipt.

A card you nicknamed shows that nickname with its masked tail everywhere it appears, driven by two shared helpers so the live screens and the durable receipt can never tell a different story. Why this is the best choice: if what you're paying with can quietly differ between the total, the tap, and the record, "total confidence" is a slogan, not a fact. One vocabulary across three contexts means the receipt always matches what you saw — and the masked identity rides along, so nothing sensitive is ever exposed to make the point.

1 · On the total

Travel card · Visa ···· 4291

The source leads the Method row, masked tail and all.

2 · At the commit moment

Travel card · Visa ···· 4291

A read-only pill on the confirm screen — what you're about to commit to.

3 · On the receipt

Travel card · Visa ···· 4291

The durable record matches the live screens — exactly.

The Baht pocket is the one context-aware line: it reads "฿ held" while you pay and "locked 36.52" on the receipt — same chip, honest about which moment you're in.

Screen 5 · Proof is a first-class output, not an afterthought

The flow doesn't end at "Paid." It ends at a complete, itemised, referenced receipt you can re-open offline, forever.

Tracing a charge to a statement line days later is the old way; the new way is a receipt that, at the moment of payment, names the merchant, the baht, the locked rate, the ฿0 fees, the source it paid from, and a unique reference. Why this is the best choice — a payment you can't re-examine is just a charge, but a record you keep is the proof the amount matched, and a reference makes it something a merchant or a card issuer can act on. The receipt records its source so even seed history is consistent. The benefit closes the loop: the rate prompt fires while the visit is still fresh, and the proof is two taps from Activity for good.

Paid

฿420.00

≈ $11.50 USD · to Som Tam Nua — Stall 14

Cleared · funds delivered in THB

Your proof

MerchantSom Tam Nua
Paid฿420.00 THB
Charged$11.50 USD
Rate used36.52 · mid-market
Fees฿0.00 · no markup
Paid with 1QR 1QR balance · USD
When29 May 2026 · 19:42 ICT
WhereChatuchak, Bangkok
Reference1QR-TH-8F4K
Rate your experience

Help the next traveler · 30 seconds — the prompt fires while the visit is still fresh.

Share proof Done

A specimen of the receipt — distinct from the total card; this is the durable record. In the prototype it opens offline and is reachable from Activity in two taps.

Activity · every row is a receipt

History isn't a list of charges you hope to recognise later. Each line is two taps from the proof behind it.

Rows are dual-currency and grouped by day, each carrying its category, time, and a "Cleared" state — and an inline ★ Rate prompt where you haven't rated yet, or your stars where you have. Why this is the best choice — a statement is a place charges go to become unverifiable, so the design makes the receipt the unit, not the row; "All synced" and "Cleared" retire the low-grade anxiety of wondering whether a payment actually went through. The benefit: any past payment is recoverable, shareable, and disputable in seconds, weeks after the trip.

Activity

All synced

Trip insights · ฿18,420 spent · ≈ $14.60 saved vs cards

Today

SN
Som Tam Nua — Stall 14
Food & drink 19:42 Cleared
★ Rate this visit
฿420.00
$11.50
G
Grab — ride to Asok
Transport 16:20 Cleared
★★★★★
฿185.00
$5.07

Yesterday

MT
Mango Tree
Food & drink 20:10 Cleared
★★★★☆
฿1,240.00
$33.95

Specimen rows — in the prototype every payment keeps its proof, and tapping any row opens the receipt to view or share, forever.

Screen 6 · The honest per-pay data, added up into a trip

"Saved vs cards" is the cumulative receipt for the whole promise — the anti-rip-off claim, totalled.

Each payment already shows what it saved against a typical card; Insights simply sums that honestly across the trip, charts the weekly FX saved, and shows where the money went. Why this is the best choice — a promise made once per payment is easy to forget, but a running total is hard to argue with, and it's built only from real cleared payments, not a marketing estimate. The corridor list states coverage plainly — full, most merchants, outbound only — so the product is honest about where it doesn't yet work. The benefit: confidence that compounds, and expectations that are set straight before the next border.

฿18,420
Spent this trip
≈ $14.60
Saved vs cards

Where it went · this trip

37 pays
Food & drink42%
Transport24%
Lodging21%
Shopping13%

Built from cleared payments only — the same rows Activity already shows, summed by category.

FX saved per week vs a card

$4.10
Wk 1
$5.80
Wk 2
$4.70
Wk 3

Mid-market rate every time — no DCC, no surprise conversion.

1QR works here

🇹🇭 Thailand · PromptPay● full
🇸🇬 Singapore · NETS● full
🇲🇾 Malaysia · DuitNow● full
🇻🇳 Vietnam · VietQR◐ most merchants
🇯🇵 Japan○ outbound only

Specimens of the Insights tiles, category donut, weekly chart, and corridor coverage — each built from the same cleared-payment data the prototype charts.

The hardest decision: your money moves only when you say so

Only the 1QR balance and the Baht pocket touch your wallet. Every card — a seed card or one you added — charges externally, wallet untouched.

The draw model is capability-clean: the 1QR balance debits your USD, the pocket debits the baht you converted, and any card is charged outside the wallet entirely. This started as a correctness fix — a custom card was once falling through and wrongly debiting the 1QR balance — and that's exactly the class of surprise that quietly destroys trust in a payments product. So the boundary became a property of the system, not a setting you have to find. Why this is the best choice: the worst possible surprise here is the wrong source being charged, so the rule is made legible and then enforced everywhere money moves.

Moves your wallet

The 1QR balance and the Baht pocket.

The balance debits your USD; the pocket debits the baht you converted at the locked rate. These are the only two sources that ever move money you're holding.

Never touches your wallet

Every card — seed or added.

Cards are charged externally and the wallet is left exactly where it was — by design, not by configuration. Verified in a real render: paying ฿420 from a card leaves USD and THB unchanged.

The opt-in Baht pocket Locked at 36.52 · opt-in per total

Convert once at the mid-market rate with a ฿0 fee, then spend at the rate you locked. It's offered per total and never becomes a silent default — the pocket only ever moves the money you deliberately put in it.

Screen 11 · Social proof built to resist gaming

The headline metric isn't stars — it's the share of verified payers who said the amount was exactly right.

Reviews come only from people who actually paid the merchant through 1QR, so there are no anonymous posts to fake, and the signature figure is the anti-rip-off one: of 1,204 verified payers, 99% confirmed the charge matched the price. Why this is the best choice — a traveller who can't read the menu needs structural honesty, not vibes, so the design adds language-light helpers (a point-and-pay order ranking, a spice consensus) and keeps the aggregates deliberately heavy: one new review ticks the count and barely nudges the mean, which is precisely what makes the number un-gameable. The benefit: a figure a stranger can trust on sight.

Som Tam Nua — Stall 14

Street food · Chatuchak · open now

Verified payers only

4.8 ★★★★★ · 1,204 reviews

99%
said the amount was exactly right
Of 1,204 verified payers, almost all confirmed the charge matched the price — no surprise markup.
1,204 1,205 one honest review: the count ticks, the ★4.8 mean barely moves.

What travelers rate highest

🍲 Food & taste 4.9
💸 Value 4.7
⚡ Service 4.6
✨ Cleanliness 4.5
MK

Mia K. 🇦🇺 verified payer

3 days ago · paid ฿380 · ★★★★★

Charged exactly what the board said. Pointed at the photo, paid, ate — no menu-reading needed.

amount matched Som tam 🌶️🌶️ medium

Specimens of the signature stat, the subscore bars, and a verified-payer review — the prototype adds the order ranking, photostrip, and filters.

Screen 15 · One managed model, masked-only cards

Every picker in the app reads one persisted set of methods, and no screen ever holds a real card number.

Cards are stored masked-only — brand, a minted tail, an optional nickname, never the full PAN — and the status pill leads the sub line so a long nickname can never collide with "Default" or "Fund-only." Why this is the best choice — a single source of truth is what lets the pay-source read identically end-to-end, and a masked-only store means the worst-case leak exposes nothing usable. Removing a method is destructive, so it gets a themed sheet showing the masked identity and a default-aware note, not a bare native dialog you'd dismiss on reflex. The benefit: managing money is calm, legible, and safe to get wrong.

Payment methods

1QR
1QR balance · USD
Default spends your USD balance
Travel card
Default-eligible · Visa ···· 4291
Bank account
Fund-only · ACH ···· 8810 · never default
Remove a method?

A themed sheet — never a native confirm() — names the masked identity (Visa ···· 4291) and notes that payments will fall back to the 1QR balance.

Specimen method rows — in the prototype these reorder, rename, and set-default live. Next build: a drag handle replaces ↑/↓.

Screen 9 · Wallet, identity, and the levers that actually shape trust

The controls that change how trust feels — the rate-lock window, your home currency — are surfaced, not buried three menus deep.

Profile leads with a calm at-a-glance state: balance, the held-baht pocket locked at your rate, the trip so far, and — quietly load-bearing — 0 disputes. Why this is the best choice — most apps hide the settings that matter under "Advanced," but in a trust product the rate-lock window and the home currency are the trust, so they sit one tap from the wallet. The identity-verified badge and the dispute count belong here too, where you take stock. The benefit: the things you'd want to check before trusting an app with your money abroad are the things you see first.

JR

Jordan Reyes

🇺🇸 Visiting from United States

Identity verified
1QR balance
$312.40
≈ ฿11,409 · home currency USD
+ Add money ⇄ Convert
฿
Baht pocket
Locked at 36.52 · spend at the real rate
฿0

Preferences that shape trust

Rate-lock window 60 sec ›
Home currency USD $ ›
Face ID to pay On ›
Where 1QR works 5 corridors ›

Thailand trip · 12 days · ฿18,420 spent · 37 payments · 0 disputes

Specimens of the balance card with its pocket row and the trust-shaping preferences — explore the full Profile in the prototype above.

v1 → v7: sharpening one promise, not stacking features

Each pass defended the same promise — see the true cost before your money moves — against the easier, less honest version of every screen.

The arc isn't a changelog. Early passes turned the Define-phase principles into a numbers-first total and a real wallet. The middle passes built the managed method set and made the pay source legible end-to-end. The late work is where the promise got defended: a correctness fix to how money is drawn, a durable receipt that records its source, the last native dialog replaced with a themed sheet, and a row-legibility and contrast pass — each verified by driving the real prototype in a headless browser, not just eyeballing it.

  • v1

    The principles.

    Numbers-first, language-light wireframes: baht dominant, home currency secondary, fees never fine print, proof as a first-class output. The promise before any chrome.

  • v2

    The honest total + the wallet.

    The itemised total at the mid-market rate with the explicit savings line; a functional wallet and the opt-in Baht pocket — Convert USD→THB at 36.52 with a ฿0 fee.

  • v3

    The managed method set.

    Add / remove / reorder / rename / set-default over one persisted model; masked-only cards — brand, a minted tail, an optional nickname, never a real number.

  • v4

    The pay source reads end-to-end.

    Brand chip + nickname + masked tail rendered identically on the total, at the commit moment, and on the receipt via shared helpers; the nickname rides onto the durable record.

  • v5

    Correctness & honest history.

    Fixed the draw model so only the 1QR balance and pocket touch the wallet and every card charges externally; each receipt now records the source it paid from, seed history included.

  • v6

    The last native dialog, gone.

    Replaced the browser confirm() on remove with a themed sheet showing the masked identity and a default-aware note; the empty "no cards" state became a real tap target into Add-a-card.

  • v7

    Legible rows & accessibility.

    Moved the status pill to lead the sub line so a long nickname never collides with it, and tightened row geometry — verified in real headless Chromium at 392px. Next: drag-to-reorder, which collapses ↑/↓ into one handle and is the root fix for the last wrapping row.

Explore more work

More explorations from the AI Product Design Lab — each a different facet of making AI products people can direct, verify, supervise, and trust.

steer exploration cover
Steer — intent before generation

Turn an under-specified prompt into a negotiated brief: the model surfaces what it inferred and flags ambiguity before it commits.

View exploration
ground exploration cover
Ground — verify what AI claims

Every claim traceable to a source with confidence and freshness; unsupported claims flagged; source conflicts shown, not smoothed over.

View exploration
recall exploration cover
Recall — legible AI memory

A memory layer you can see, attribute, edit, scope, and revoke — personalization as a negotiated, inspectable thing, not a black box.

View exploration