Design ruling · R86 · 2 Aug 2026
You said the shipped screen felt like a quick mockup, not something people would pay for. This is the design that replaces it. Nothing gets built until you approve or revise these two things.
Build one connection flow. One state machine, one set of components, one copy table. Render it inside two different page frames: the first-run onboarding frame, and the standalone bank-connections manager.
The alternative is what exists today — two separate builds that already disagree with each other.
Stop inventing styles. Use the 70-component design system already shipping in the app, and add only two missing pieces: a four-stage progress indicator, and a read-only bank row.
Silence is not approval. Reply with “approve both”, or say what to change.
When you connected your real Amex, three things went wrong on screen. None of them in the data layer. All of them in the experience.
I confirmed all three in the code. I did not take the report on trust. The celebration really does fire the instant the connection is saved, before any spending has been pulled in.
Today this is a card that says “No bank connected.” That is a dead end, not a screen that sells anything. It becomes an explainer that tells you what is about to happen:
Beside it sits a “Know what to expect” card. It sets the card-naming expectation honestly before you commit, instead of surprising you afterwards:
American Express identifies card names automatically. Other banks may return only a generic card label and its last four digits. After sync, we’ll ask you to match labels such as “Card ·1234” to the card product in your wallet.
One progress card stays on screen the whole time and always names the current wait. No more dead air. Progress is ordinal. Four named stages, never a fake percentage.
| Stage | What it says | If it drags |
|---|---|---|
| Preparing | Creating a secure Plaid session… | After 8s: “Still preparing the secure session. Keep this page open.” |
| Bank sign-in | Opening Plaid’s secure bank window… | A failure becomes a real error, never an endless spinner |
| Saving | Plaid accepted your selection. Saving the bank connection… | “Your connection now exists. Leaving this page will not cancel it.” |
| Importing | Your bank is connected. Importing recent spending… | After 20s: “This is taking longer than usual. You can finish in the background.” |
Confetti moves to the end. It fires only after the connection is saved, the first import has actually finished, and the success screen is visibly painted. It cannot fire over a page that still says “No bank connected.”
You see which bank is connected, when it last synced, and which cards were recognised. The screen keeps the distinction between a card the system matched itself and one you picked:
✓ Auto-matched✓ You choseCard type required
Cards it cannot identify get a “Choose type” action instead of a guess. The system never guesses an ambiguous rewards product. Guessing wrong quietly corrupts every recommendation after it.
Anything it cannot show honestly says so:
Only cards with categorized spending in the latest synced month appear here. A selected account may appear after a later sync.
Every failure state gets durable, specific copy — never a toast that vanishes, never a generic “something went wrong”. Here is the one that matters most. If the app cannot tell whether a connection was created, it hides the Connect button and asks you to check status first. That stops you creating a second bank connection that bills every month.
If you close Plaid partway, the app checks whether a connection was actually created before it tells you anything. It never says “cancelled” when a billable connection quietly exists.
I tested the spec against the actual code. Everything it claims held up:
Prepared by the autonomous relay poller on 2 August 2026, while you were away. This
page is a readable summary for review on a phone. The full 453-line spec, including the build
contract and its 21 acceptance gates, is in the relay repo at
exchange/from-auditor/DESIGN-SPEC-R86-PLAID-VISUAL-INTERACTION-2026-08-02.md.
Nothing here is a commitment to a ship date.