Skip to content
Contact

Case studies / Tigg · Jul 2025 – Jun 2026

Sign-in as a sequence of recoverable states

Two arcs: the 2025 verification flow (designed in Figma first), and the 2026 sign-in redesign that made the Citizens Bank integration visible to every user.

AuthVisual designTagged release · Feb 2026Merged to production · May 2026

Role

UI/UX design (Figma first in 2025), frontend in three apps

Timeline

Jul 2025 – Jun 2026

Team

CEO, senior frontend engineer, frontend engineers, backend engineers, QA

Platform

Accounting web, POS web, account web app

Not mine

Backend verification and device-trust policy; the bank integration itself

Measured outcome

None measured; "looked more modern" reported by the CEO

the key decision

Every step of sign-in has a way back, and the front door carries one message at a time.

how deep do you want to go?

Auth
Diagram from the case study. Product screenshots are being added.
That's the brief. Switch to Story for the full argument, or Deep for states, iterations and implementation.
Chapter 01

A password form that learned to ask a second question

Until mid-2025, signing in to Tigg meant an email, a password and a button. Then the backend started deciding, device by device, whether to ask for a second step: a 6-digit code sent by email. That one change added states the old page had never had:

  • the device isn't identified yet;
  • a code is needed, but hasn't arrived;
  • the code is half typed, or wrong;
  • trust this device, or not;
  • and where do I manage the devices I trusted?

Each of these is a moment when someone can get stuck at the only door into the product. I treated sign-in as a sequence of states, and gave each one a visible way forward or back.

A year later the same page had a different job. Tigg had integrated with Citizens Bank, and the login is the one screen every user sees. In 2026 I redesigned it so the integration was the first thing people saw, without slowing down anyone who just wanted to sign in.

Chapter 02

Two arcs, three front doors

Tigg is several apps sharing one account system. The accounting app and the POS each have their own login page, and a companion account web app handles sign-up, password recovery and security settings. There is no single sign-on and no shared component library between the codebases. So a change to how sign-in behaves has to be designed once and then built three times.

2025: device verification2026: the Citizens Bank login
QuestionHow do people get through a conditional second step?How does everyone see a major bank integration?
DesignIn Figma first, then builtA visual redesign of the login page
My partDesign and frontend in all three appsDesign and frontend in both web apps
Not mineSending the codes, the device-trust policy, the sessions backendThe bank integration itself

The inputs came through Tigg's usual channels: the CEO's priorities, and problems reported by QA and support. No usability test was run for either arc.

Chapter 03

Every wait gets a state

I started by mapping sign-in as a state machine. The backend can say "verification needed" in two ways: as a flag in a successful response, or as a message in an error. Both had to lead to the same code-entry screen. After the code, the person had to follow exactly the same route as someone who didn't need one. A bank-report user still lands in their report view, and an expired password still leads to the change-password screen.

1 · Namespace loadingspinner before any form Unknown companyCLAIM THIS COMPANY Subscription not verifiedsupport contact not found no access OK 2 · Credentialsbutton: Preparing… (disabled) 3 · Credentials, readyfield errors stay here ready Log in 4 · Authenticatingbutton loading server error: message, inputs kept Outcome routing bank user → Bank report view expired → Change password first login → Change password else → the page they came from, or home OK verification needed (flag) or needed (error message) store context 5 · Code entrytimer from 60 s · trust onReturn to Login → 3 5b · Resend available"Resend now" timer 0 resend 6 digits → auto-submit 6 · Verifyinginputs disabled OK same outcome routing wrong code: message, clear six boxes, focus box 1 Edge. Device context lost in 5 or 6 → "Device fingerprint not ready. Please try refreshing the page." Legend. Blue states were added by device verification; grey states are pre-form errors.
Reconstruction, fictional dataSign-in as a state machine, drawn from the accounting login. The POS and the account app follow the same states.

Two waits are invisible to the person signing in, so I gave each one a state:

  • The device isn't ready. The browser needs a moment to identify the device. Until it has, the button reads "Preparing..." and can't be pressed, so an early click doesn't fail with a confusing error.
  • The email is on its way. The code screen says where the code was sent and shows a countdown: "Didn't receive a code? Resend in 00:45". In the last five seconds the digits turn red and blink, then the countdown becomes "Resend now". The number stays next to the colour, so the cue doesn't depend on colour alone.

The trust choice appears at the moment it matters, on the code screen: "Trust this Device for 60 days?", checked by default. A teammate wrote that wording and the first placeholder screen. I designed and built the flow around it.

Failures became recoverable too. A wrong code shows the server's message, clears all six boxes and puts the cursor back in the first one. After a failed sign-in, the email and password stay filled in. In September 2025 I also removed validation messages that pointed to the wrong field.

Figma designThe verification step as designed in 2025.
Chapter 04

Six boxes that behave like one field

The code input looks trivial: six boxes, one digit each. On phones it broke. Android and iOS keyboards offer the whole emailed code as a single suggestion, and one tap put all six digits into the first box. The rest were lost.

I fixed it in August 2025. Then I wrote down what the input has to do, however the code arrives:

InputResult
A digitFill the box, move to the next
Anything that isn't a digitIgnored
A full code, typed, pasted or autofilled into any boxSpread across all six
Backspace in an empty boxClear the previous box and move there
Arrow keysMove between boxes
Six digits presentSubmit once, and never while a request is running

Doing this once wasn't enough: all three apps had to follow the same rules, in two different code styles. Keeping them in step turned out to be a design task as much as an engineering one.

Chapter 05

2026: putting the bank at the front door

The Citizens Bank integration was a major feature, and it needed to be in front of every user. The existing login showed "What's New with Tigg" as a pale side column with two small post cards. In that layout, a bank partnership looked as important as a routine monthly update.

The redesign was mainly visual. The sign-in form stayed where it was, on the right. On the left, the list became one featured post at hero scale: a dark, image-led panel with the date, title, excerpt, a "Learn More" button and previous/next controls. At launch in late May 2026, that post was "Citizens Bank International Now Integrated with Tigg".

2025 · a list of posts 2026 · one featured post What's New with Tigg Sign in to Company company.tigg.app Email address Enter password Forgot Password? Log in Need an account? Sign Up Month D, YYYY Citizens Bank International Now Integrated with Tigg Learn More View all blogs ‹ › Sign in to Company company.tigg.app Email address Enter password Forgot Password? Log in Need an account? Sign Up 1 2 3 4 1 One featured post over Login Background 2 "Learn More" opens the post in a new tab 3 ‹ › step through the newest two; "View all blogs" 4 The form is unchanged: same fields, same place Before: a pale #FAFAFA column titled "What's New with Tigg", two small cards, the same form on the right
Reconstruction, fictional dataThe accounting login in 2025 and 2026. The form didn't change; the side column became one featured message. The numbered marks point to the parts of the featured panel: date and title, call to action, the link to all posts, and post navigation. The post title is the real announcement; the date is a placeholder.

Signing in still had to come first. On a phone the form appears first and the announcement follows below, with its call to action pinned while the excerpt scrolls. If the posts fail to load, the panel shows "Unable to load the update." with a reload button, and the form beside it keeps working. I didn't redraw the verification, forgot-password and sign-up screens in 2026; only the login page changed. I also applied the same visual change to the companion account app.

Product screenshot, test company dataThe shipped login, desktop and phone.
Chapter 06

Results and what I learned

The 2025 verification flow was in Tigg's first tagged releases in February 2026. The 2026 redesign was merged to production on 27 May 2026 and included in a tagged release on 3 June.

It looked more modern.Reported to me by the CEO

Measured outcome: none. I have no data on sign-in success, resend rates, time to sign in, or clicks on the featured post. If I were measuring it, I'd log one event for each state change, including how the code was entered (typed, pasted or autofilled). I'd also track clicks on the featured post during a campaign.

The security feature is the recovery path. Most of the work was in the states after something goes wrong: a wrong code, a late email, a lost field.

A small component can carry a contract. Six boxes had to behave like one field for paste and autofill, in three codebases.

A visual redesign can do business work. Making the bank integration the first thing every user sees didn't need a single flow change.

Deep dive 07

States, edge cases and the first sign-in on a new device

Person Login page Device context Auth API Email opens <company>.tigg.app compute (async) ready email, password, Log in credentials + device context verification needed 6-digit code "Verify it's you", 60 s code arrives, on the same or another device type, paste or autofill code + trust choice (auto-submit) success route onward "Preparing..." button disabled
Reconstruction, fictional dataThe first sign-in on a new device. The device check and the email in transit are both invisible waits; each one has its own visual state. Backend behaviour isn't shown.
StateWhat the person sees
Device not ready"Preparing..." on a disabled button
Required fields emptyField messages under email and password
Sign-in refusedThe server's message under the form; typed values kept
Code incomplete"Please enter a complete 6-digit verification code"
Code wrong or expiredThe server's message; all boxes cleared; cursor in box 1
Resend cooling down"Resend in 00:ss", red and blinking in the last five seconds
Resend failed"Failed to resend verification code"
Unknown company address"The company url … doesn't exist", with a way to claim it
Subscription not verifiedA message with the support contact
Posts loading or failedA spinner, or "Unable to load the update." with reload

Other edge cases I designed for:

  • surrounding spaces are trimmed from emails, and emails are lowercased so capitals don't cause a failed sign-in;
  • a deep link brings people back to where they were going after sign-in, and an unsafe link falls back to the home page;
  • after verification, an expired or first-time password still goes to the change-password screen.
Loadingspinner Loaded (i of n) ‹ › moves i by one; n ≤ 2 Prev muted at i = 0 Next muted at i = n − 1 panel keyed by i: animation replays Failed or empty "Unable to load the update." reload icon posts error, or no posts reload: refetch
DiagramThe featured-post panel. It shows at most two posts, and whatever happens here, the form on the other half of the page isn't affected.
Deep dive 08

Built, then removed

Several pieces of the 2025 work didn't survive in their first form. I count these removals as part of the design.

WhatWhat happenedMy reading, looking back
"Remember me" checkboxRemoved in August 2025Device trust replaced it with a decision the server enforces
A trusted-devices page inside accounting settingsBuilt in August 2025, removed a month later, before any tagged releaseDevices belong to the account, not to one app, so device management went to the companion account app. On the same day I extended the device list there
"Remove all devices"I hid it in August 2025; another engineer later brought it back with a loading state and disabled it when there's nothing to remove
A port of the accounting sign-in code into the POSAbandoned after two exploratory attempts; a flow written in the POS's own style shipped insteadFitting the POS codebase beat importing a second way of doing things
A news column on the POS loginBuilt but never switched on, which saves a request on every sign-in

In the account app, turning two-step verification on or off asks for the current password first. Trusted and untrusted devices are listed separately, and each can be removed after confirming.

Notes on sources

The dates come from the tickets and version history. The reasons in the right-hand column are my reading in hindsight, not notes from the time. The diagrams are redrawn from the shipped code and the Figma layer names, with fictional data.

Deep chapters (states, iterations, implementation) are hidden in Story mode. Switch to Deep at the top to read them.