A stack of ones,
finally worth watching.

Coffer turns loose cash into a number worth watching, no bank account required. Built after bar shifts where tip money never felt like real money until it was already spent, and owned solo from the first sketch to the version live with real testers today, including every bug found along the way.

Role: Product Designer & Product Owner Platform: Android (PWA) Stack: Vanilla HTML/CSS/JS Status: Live, in testing
Coffer splash screen showing sample savings goals
01Why This Exists

A paycheck is a number in an app. A stack of ones never quite was.

Working bar shifts, cash tips added up fast, but they never felt like real money. A paycheck is a number inside an app; a stack of ones from a Saturday shift felt disposable, easy to spend without a second thought, especially for me and a lot of my neurodivergent coworkers, who found consequence-free cash genuinely hard to sit on.

We tried the trick everyone already knows from TikTok: envelopes, a paper tracker with boxes to fill in for a savings challenge. It fell apart for a boring reason. The paper wasn't always on us, and every time it wasn't, the commitment it represented stopped meaning anything. No paper in hand meant no visible proof of progress, so it stopped changing how we actually spent.

What we actually wanted was simpler than any system: a big number going up, something closer to popping bubble wrap than filling out a form. Coffer is a bet that there's an audience who wants that same feeling, digitally, for real cash, without handing a bank account or card number to an app to get it. A lot of savings apps assume your money already lives inside them. Mine assumes it doesn't, and maybe shouldn't.

No bank account requiredLocal-only storage, nothing ever touches a real account or card.
Built from real bar shiftsNot a market gap found on a whiteboard, a problem lived first.
A bet, not a guaranteeStated honestly as an open bet on who wants this, not a proven certainty.
02Who It's For

Two testers, two different answers for what this actually does.

Real testers, not personas built from a template. What they each did with the app said more than any survey would have.

Coffer's match result screen next to a saved goal on the dashboard
Tester One
The Coworker Who Took Over My Shift
Before Coffer, his answer to not having enough money was always more hours, more shifts, work harder until the number moved.
Watching the app's total tick up from dollar amounts he'd normally never notice missing changed that math for him. A dollar that doesn't touch his day-to-day suddenly counted for something, which sounds obvious written down and did not feel obvious to him before he saw it happen.
Tester Two
The Envelope-Breaker
"In sight but out of hand." Money she could see and knew was hers, but couldn't spend on impulse because it wasn't sitting in a checking account attached to a debit card.
She started pulling money out of her bank account specifically to make it cash again, just so she'd have something physical to log. She compared it to a credit-builder savings account for the same reason, a use case never designed for. It suggested the app's real job might be less about tracking cash and more about building a small, deliberate barrier between a person and their own money.
03The Journey

What actually happens, not what I designed for.

Built from observed tester behavior, not an idealized flow. Every row is a real dimension of the same five stages, including the one I still don't have a real answer for.

Discovery
Onboarding
Habit Formation
Milestone Moment
Drop-off Risk
What's Happening
A friend already using Coffer mentions it in conversation.
Six-step quiz, then a customization screen, then a matched challenge.
Notifications pull attention back to the app between sessions.
A savings target gets hit, whatever that means to that person.
The challenge-recommendation screen presents one big option and several small ones.
Real Signal
100% of testers so far found it socially, none cold.
93% complete onboarding rather than skipping ahead.
Reminders, not any single feature, are what actually keeps someone saving.
No read yet on what a milestone feels like to a tester.
Banner blindness toward the large recommended option.
Design Response
None yet, trust in the referrer is currently doing all the work app-store copy would normally do.
Attention doesn't engage until customization, the point a plan starts to feel like the user's own.
Reminder copy tuned around three real prompts: forgot to save, growth update, spare change.
Named as an open question rather than filled in with a guess.
Logged as an actionable fix in the roadmap, not just an observation.
Status
Honest limitation
Working as intended
Working as intended
Open question
Fix planned
04Screen by Screen

Four screens, every one changed by a real report.

Real mockups, real reasoning. Nothing here is a redesign for its own sake.

Onboarding
Recommendation
Dashboard, Grid
Settings
Coffer onboarding slide, why we made Coffer
Discovery → Onboarding
Three slides, then straight into the quiz.

The first screen someone sees after opening the app for the first time makes the same case this whole case study opens with: no account, no cloud, nobody watching. That line does real work, since 93% of testers complete the full onboarding rather than skipping to explore alone, which means the pitch is landing before anyone has touched a single feature.

Attention doesn't really engage until the customization screen a couple steps later, where theme, layout, and notification preferences get chosen. That's the moment saving starts to feel like a plan someone made on purpose, not a tutorial being clicked through.

Coffer quiz results screen showing a matched savings challenge
Onboarding → Habit Formation
The screen that turns "I want to save" into an actual plan.

The first version scored candidate challenges by adding five separate factors together at roughly equal weight, so a challenge with three matching pain-point checkboxes could outscore one whose dollar amount was nowhere close to what someone typed in. A tester asked for the same amount every time toward a $1,000 to $1,500 goal and got recommended a $300 challenge that varied its amount every save, the opposite of both numbers entered.

Amount fit now dominates everything else, worth 16 points for a close match against a flat -10 penalty for a bad one. Stating a saving style like "same amount every time" actively costs points on a challenge that contradicts it, and pain-point checkboxes are capped at six combined points so stacking several can't outvote the amount someone actually entered.

Coffer dashboard in Grid layout showing a savings goal card
Habit Formation
List is about the numbers. Grid is about the photo.

Grid and List do two different jobs. List stays compact and content-first, built for the numbers. Grid exists because someone wants to see their goal, a vacation photo, a picture of the thing they're actually saving toward, so the photo has to read as the point of the card, not a small icon floating in a mostly empty box.

What got tried and rejected: the first version of the bigger Grid card resized the container but not what goes inside it. A preset icon scaled up fine since it's just a glyph, but an uploaded photo stayed pinned to its old fixed pixel size, sitting small and centered in a container built to be full-bleed. That gap only showed up once a real photo replaced a preset icon.

Coffer settings screen
Habit Formation → Trust
The screen that has to prove "local-only" is true, not just claimed.

Settings is where the app's core promise either holds up or doesn't: theme and layout controls, a plain-language explanation of the six-factor match engine so the recommendation screen doesn't feel like a black box, and an export/import backup flow, since "local-only" without a way to move your own data before switching phones is a promise with a real gap in it.

A developer-only reset button lives here too, wiping local storage and replaying onboarding from scratch. Built after repeatedly needing to test first-run behavior without uninstalling the app, a small tool that exists purely to make honest testing possible.

05Live Demo

Not a video. The actual app, running right here.

This is the real Coffer source code, not a recreation for the case study. Run through the quiz, create a goal, tap a few boxes.

This embedded copy runs in its own sandboxed browser storage, separate from the real deployed app, so nothing typed here touches live tester data, and nothing here persists once you leave the page. If it doesn't load below, it's a browser embedding quirk, not a broken app: open Coffer directly instead.
06Process & Iteration

Every real bug, root cause, and fix. Not the highlight reel.

A single-founder build means every one of these was found, diagnosed, and fixed solo. Shown here in full because the reasoning is the actual work, not the parts that happened to go right on the first try.

Bug Report

The recommendation engine ignored what people actually typed in

A tester wanted the same amount every time toward a $1,000 to $1,500 goal. The #1 recommendation was a $300 challenge with a varying amount every save, the opposite of both numbers entered. The matching logic behind the scenes added up several different signals to pick a winner, but nothing made sure the ones that actually mattered outweighed the ones that didn't. Getting the dollar amount close barely moved the score, saying "same amount every time" and getting handed a challenge that changes every time cost nothing at all, and checking off a few unrelated complaints could quietly add up to more influence than either of those.

How much the dollar amount mattered: barely → the single biggest factor
Picking a style that didn't match: no penalty → now counts against it
Stacked complaints boosting a bad match: unlimited → capped
Deeper Bug, Found By Auditing The Fix

The first fix wasn't actually the fix

Just making the dollar amount matter more looked like the fix, until every single combination the quiz can actually produce got tested by hand, around 64,000 of them across all four saving styles. Three of those styles, gradual, random, and mixed, were still getting matched to a challenge that couldn't actually deliver what they promised, 38 to 62 percent of the time depending on the style. One rule fixed all three at once: if someone picks a style, a challenge that doesn't genuinely match that style gets knocked far enough down the list that it stops winning by accident.

Every answer combination checked by hand: 64,000
How often it still got it wrong after the real fix: almost never
Coverage Gap

39 challenges, not 10, because the engine needed real options

The scoring fix could stop a bad recommendation, but with only 10 preset totals, plenty of legitimate amount and frequency combinations had no genuinely good match to point to in the first place. "I want a challenge where I can save a thousand dollars with just $1 bills" became the literal test case: 29 new presets across fixed-amount, gradual, random, and variety styles, spanning $1 to $500 per save, so every quiz combination has a real answer instead of a compromise.

Ready-made savings plans to choose from: 10 → 39
Results Page Overhaul

Standardizing time revealed a tradeoff nobody could see before

Some challenges described their pace in weeks, others in raw save counts, with no consistent way to compare them. Giving every preset a real cadence-days field and computing an honest duration surfaced something previously invisible: the exact same $1,000 goal takes 2.7 years with $1 bills but 12 months with $20 bills. The results screen also stopped showing every one of the 39 presets regardless of fit, gating anything below 70% of the top score behind a "look for more options" tile instead of presenting a weak match as a confident answer.

$1 bills to $1,000: 2.7 years
$20 bills, same goal: 12 months
Design Decision

The icon redesign measured what "bigger" actually meant

The original icon was a flat green square, technically fine and forgettable. The redesign asked for a light-green gradient with an enamel-pin feel, checked against real contrast math across three intensities rather than eyeballed, since a pale gradient and a white glyph fight each other once the top of the gradient gets too light. The bigger finding came after color was settled: the glyph itself only filled about 70 percent of its own canvas. Once measured properly, the fix was obvious, scale it up to roughly 85 percent visible fill, close to what most icon-heavy apps already do.

Shipped, Then Reverted

A hard drop-shadow on every icon, live for about a day

Trying to give the flat app more personality, every icon got a hard offset shadow behind its glyph, a one-line CSS rule that touched every icon in the app at once. Seeing it live for real was enough: it looked bad, and the call was immediate, revert it. A simple stroke-width increase on the icons stuck instead, bolder without the shadow gimmick, and without touching the dynamic per-theme recoloring the shadow version would have complicated.

The Same Lesson, Learned Twice

Flat cards got real depth, and dark mode broke the same way twice

The whole app had been intentionally flat, a single pixel border and solid fill on every card and button. Soft gradients and shadows fixed that, built from the app's own color tokens so the effect holds up across all six theme combinations. Both times this kind of highlight got added, mixing it toward literal white looked fine in light mode and quietly blew out contrast in dark mode, where a background that was never meant to get that light suddenly did. The fix, both times: mix toward a token already calibrated for the current theme, never toward a hardcoded white or black.

Geometry Bug, Caught Before Shipping

A phone-mockup tool that worked at a steep angle broke at a mild one

Building tooling to composite real screenshots into device mockups, a technique using a mask's four extreme pixels as the four corners of the screen worked perfectly on a dramatically tilted iPhone frame and produced sheared, unusable garbage on a mildly tilted one. The extreme-pixel trick only holds when a rotation is steep enough that each corner is uniquely extremal, for a near-upright rectangle the leftmost pixel sits mid-edge, not at a corner at all. Switched to a proper minimum-area-rectangle calculation that finds the true corners at any angle, verified against both the broken case and the original working case before trusting it.

Design Judgment, Not Just a Fix

A geometrically correct mockup still wasn't a good one

After the corner-detection bug above got properly fixed, the resulting tilted mockups were technically accurate and still didn't look good enough to ship. Reverted to the flat, plain treatment that was already working, and later replaced with mockups built by hand in Figma instead, which were immediately, noticeably better. Correct geometry and a real product photo turned out to be two different bars, and only one of them was worth shipping without more design work behind it.

Smaller fixes along the way

  • A stale service worker served the old app indefinitely on real installs, since its cache key never changed between builds. Switched to network-first with a versioned cache key.
  • A relative asset path bug 404'd every screenshot on the deployed site while working fine locally, because a clean URL with no trailing slash resolves relative paths differently than the equivalent local file path did.
  • A chroma-key fringe around composited mockups got worse when the instinct was to shrink the mask to fix it. The actual fix was the opposite: grow it.
  • A background-color sample for a status-bar overlay picked up page backdrop instead of app content, because the source screenshot had margin around the actual phone that a corner pixel doesn't account for.
  • A missing gallery image had been silently broken since an earlier edit, caught only while working on something unrelated and checking the live render instead of trusting the last known-good state.
07Design System

Flat on purpose. Almost too flat.

Coffer's visual language went through two real pivots this year, not one clean decision made up front.

Original flat iconBefore
Garden Enamel redesigned iconAfter

The old icon was a flat green square, technically fine and totally forgettable. The new one asked for a gradient with an enamel-pin feel, a bevel, a little gloss, believable as a small physical object. The glyph itself was also just too small, filling barely 70 percent of the space it had, so it got scaled up to what most icon-heavy apps already do.

Coffer dashboard in dark mode

The app had also been intentionally flat: a single pixel border and a solid fill on everything. A hard drop-shadow on every icon got tried and reverted the same day it shipped. Soft gradients and shadows on cards and buttons, built from the app's own colors, were the fix that actually stuck.

One honest process noteDark mode is where this keeps almost going wrong. A highlight mixed toward literal white looks fine in a light theme and blows out contrast in a dark one. The fix, twice now: mix toward a token already calibrated for the current theme, never a hardcoded white or black.
39

Preset challenges

Fixed-amount, ramping, variety, and random-pattern challenges spanning every target from under $300 to $6,000+, so there's a real match instead of a generic one.

6-factor match engine

Amount fit16 pts
Timeline fit8 pts
Saving style9 pts, up to −20
Save frequency6 pts
Goal type fit6 pts
Pain point tuning±6 pts

6 themes, live

Green, Blue, or Pink, each in light and dark. Tap a swatch, the whole page below reacts, including the foundations walkthrough right after this.

Currently showing: Green, Light

List & Grid

List keeps it about the numbers. Grid is the visual mode, full-bleed goal photos front and center.

Local-only

Everything lives on the device. Export a JSON backup any time, import it back on a new phone.

Milestone celebrations

A quiet nudge at 25%, 50%, and 75% progress, no notifications required, no account needed to see them.

Tip-only, no ads, no IAP

No ads and no in-app purchases. If it's useful, there's a tip link. That's the whole business model.

The actual foundations, not a description of them

Every color below is a real token from the app, not a palette picked for this page. Pick a theme up in the swatches above and these update to match it, same as the app itself.

Color

Surface
Surface#FFFFFF
Pale
Pale#EBF3EA
Wash
Wash#DFEAD2
Rich
Rich#ADD4B1
Button
Button#C7D0B9
Success
Success#3F7D52
Ink
Ink#17301B
Mid
Mid#626F5D

Typography

Save smarter.
Plus Jakarta Sans · 800 · Headlines
Here's your match
Plus Jakarta Sans · 700 · Titles
$25 Challenge
Plus Jakarta Sans · 600 · Emphasis
Scored 24 pts across your goal, timeline, pace, and saving style.
DM Sans · 500 · Body
No account, no cloud, nobody watching.
DM Sans · 400 · Body, small

Icons

Lucide, at the same 2.5 stroke-width as the real app, not the thinner default.

piggy-bank
shield
plane
trending-up
shuffle
sparkles
bell
lightbulb
party-popper
download
upload
pencil
trash-2
check
search
palette

Buttons, live

Not a description of the button style. The actual button style, hover over it.

08What Would Be Measured Next

No formal tracking yet. Here's the plan.

There isn't a tracking habit in place, honestly, closer to noticing whatever comes up in a conversation with a tester than checking a number on any kind of schedule. That's a real gap worth naming directly. What follows is the plan for what to start watching, not a report of numbers that already exist.
Metric 01

Total-viewed frequency

How often someone opens the app just to look at their total, separate from logging a save. A high number means the growth itself does emotional work on its own. A low one means the number only matters mid-habit, not as something worth checking by itself.

Metric 02

Un-prompted saves

How often a save gets logged without a notification prompting it. The real signal for whether the habit has become someone's own, instead of something the app has to keep pushing from outside.

Metric 03

Notification response, and who even needs it

How long it takes someone to act after a notification, and what share of people need that nudge at all. One tester sets her own calendar reminders on top of what the app already sends. If most people are like her, a piece of what felt load-bearing might actually be optional.

09Reflection

The call I'm still not sure about.

  • Kept it flat, still not settled on itI'm a visual person, I like movement, my attention gets bored easily, and there's a version of this app with more personality that I know how to build. Every time I tried adding more, it felt like it competed with the content instead of supporting it. I'm sticking with flat for now. I wouldn't call it settled.
  • Device testing came too lateThe app behaves differently on a phone than staring at it on a monitor for most of a build, thumb reach, how a gesture actually feels, all of it. If I started over, real hands on a real device would start a lot sooner.
  • A quality-of-life mindset, not an enterprise oneYears of corporate design work quietly train you out of noticing small inconveniences, the stuff too minor to justify its own ticket. Gaming never trained that out of me. A patch that fixes one small annoyance is still a real patch.
There's a market for almost anything, but that doesn't mean a tool already exists for it. I kept assuming the things that bothered me personally were too small to matter to anyone else, until I handed them to other people and watched them agree.
Angela Clemons, on building Coffer
Let's Connect

Angela Clemons

Product Designer & Product Owner · Savings and Habit-Formation Products · Local-First Design