FinTech · Social Finance · 2025

Billie
Finance.

A dark-mode personal finance companion for mobile web — combining multi-card management, Gemini AI coaching, and social spending competitions in a single conversational interface designed to make credit health feel winnable.

RoleDesign + Dev
PlatformMobile Web
StackReact · Tailwind · Gemini
TypeSide Project
Card EjectionSpending IntelCartel RankVault Q&ALocation OffersBalance MaskingMission XPAI CoachingCard EjectionSpending IntelCartel RankVault Q&ALocation OffersBalance MaskingMission XPAI Coaching

01 · Overview

Project at a Glance

A social-first personal finance app that reframes credit health as a competitive sport — combining a physics-driven card wallet, Gemini AI coaching, and peer leaderboards in a single mobile web interface.

🎯 The Problem

Young adults managing multiple credit cards struggle to act on financial data that feels abstract and punitive — existing apps frame credit health as a deficit rather than a skill to develop.

💡 The Solution

A single-screen mobile app that makes credit health competitive and rewarding — with animated card management, Gemini AI coaching, and peer groups (Cartels) that gamify financial discipline.

⚙️ Design Principle

Finance should feel like a game you can win, not an audit you're failing. Every screen rewards progress and socialises the habit.

📐 Scope

Single-file React application. Frontend-only with mock data — Gemini 2.5 Flash API powers AI features. DiceBear Personas API renders member avatars. localStorage persists onboarding state.

02 · Process

Double Diamond Method

The Double Diamond structured Billie's design across two diverge-converge cycles — first to diagnose why personal finance apps fail to stick, then to build the right social-first intervention.

Phase 01

Discover

Competitive audit of Mint, YNAB, Copilot, and Revolut revealed all four frame finance as deficit management. User sentiment patterns across App Store reviews surfaced guilt and anxiety as dominant themes — confirming a motivational gap, not an informational one.

Phase 02

Define

Defined the core problem as: users know they overspend — they lack a mechanism that makes improvement feel rewarding and visible. The goal shifted from 'help users understand their finances' to 'make credit health feel like a streak worth maintaining.'

Phase 03

Develop

Explored three directions: solo gamified challenges (low retention without social proof), a finance social network (privacy concerns at scale), and embedded peer groups within a card management app. The third path combined utility with accountability.

Phase 04

Deliver

Converged on Billie: a mobile card wallet with Cartels for social competition, a Gemini AI coach (the Vault) for contextual education, and a gamified XP system that rewards on-time payments and low utilisation — not just app opens.

Research Methods Used

📊

Competitive Audit

Systematic review of Mint, YNAB, Copilot, and Revolut across six dimensions: onboarding friction, emotional tone, social features, retention hooks, notification strategy, and error framing. Identified the universal absence of peer accountability as the structural gap.

💬

Sentiment Analysis

Analysis of App Store reviews across leading fintech apps for recurring emotional language. Guilt, anxiety, and feeling overwhelmed emerged as dominant themes in negative reviews — validating the hypothesis that emotional design, not missing features, drives abandonment.

🧪

Concept Testing

Three interaction prototypes tested across the solo gamified model, a finance social feed, and the Cartel group model. The Cartel structure showed the strongest stated intent to return and lowest reported financial anxiety — validating the social accountability mechanic.

03 · User Flow

App Walkthrough

Seven screens from first launch to AI-powered coaching. Tap any card to reveal the design rationale behind each screen.

Tap to flip
Screen 01Welcome & Onboarding
First run

Welcome to Billie

Track spending, join Cartels to compete, and learn from the Vault.

Get Started

Tap for design notes
Screen 01Welcome & Onboarding

Brand introduction presented as a modal overlay on first launch. Dismisses on 'Get Started' and writes a localStorage flag to suppress on all subsequent visits.

localStorage prevents re-showing the overlay, matching native app first-run behaviour without requiring a backend session model.

Dismissal sets React state immediately and persists asynchronously — the transition feels instant with zero perceived lag.

The Billie logomark SVG uses stroke-based paths on a black background, remaining crisp at all sizes without font or icon dependencies.

Tap to flip back
Screen 02Home Dashboard
Financial hub

Good Morning,

Alex

980 XP

Total Balance

$36,398

+2.4% this month

Send

Request

Recent Spending

🎬

Netflix

Today

-$14.99

🛒

Whole Foods

Today

-$124.50

"Do not save what is left after spending..."

— WARREN BUFFETT

Tap for design notes
Screen 02Home Dashboard

Consolidated view of total balance across all five cards, Send and Request quick actions, three recent transactions, nearby offers preview, and live Cartel activity feed.

Balance masking via the Eye toggle uses a single boolean state — no data is cleared, only the rendering path changes.

Tapping the balance card navigates directly to the Spendings tab — the most-used analytical feature is one tap from the home screen.

The XP badge is visible on the profile avatar without opening the profile screen, surfacing the gamification layer passively on every home visit.

Tap to flip back
Screen 03Spending Analysis
Transaction feed

Analysis

Spending & Offers

Limit

$102K

Spent

$36K

Left

$65K

Spendings

Offers

All

Dining

Groceries

Travel

🎬

Netflix

Entertainment

-$14.99

🛒

Whole Foods

Groceries

-$124.50

Starbucks

Dining

-$6.45

Tap for design notes
Screen 03Spending Analysis

Dual-tab view of filterable transaction history and location-aware merchant offers. Limit, Spent, and Left statistics surface the utilisation rate with a contextual 'ideal' anchor.

useMemo gates category extraction so the filter set never recomputes on unrelated state changes — the feed remains responsive at any transaction volume.

The Offers tab gates behind a geolocation permission request, providing a clear value proposition before asking for sensitive browser access.

Utilisation is shown with 'Ideal: under 30%' inline — users get the benchmark without navigating to a separate education screen.

Tap to flip back
Screen 04Cartel Leaderboard
Social layer

Alpha Spenders

Smart Leaderboard · 8 Members

Your Rank

#1

Top 5% Smart Spender

🏆
1

A

Alex

98

2

S

Sarah

95

3

M

Mike

88

Tap for design notes
Screen 04Cartel Leaderboard

Inside a Cartel, members are ranked by a composite credit score combining utilisation, payment timing, and trend direction. The sort runs client-side on the members array.

DiceBear Personas are seeded by member name, ensuring each avatar is visually consistent across sessions without storing or serving image assets.

The rank sort is a pure client-side array sort — no API call required, no loading state, instant rank updates within a session.

Trend indicators use distinct SVG icons (up arrow, down arrow, flat line) alongside colour — satisfying WCAG 1.4.1 for non-colour differentiation of state.

Tap to flip back
Screen 05The Vault · AI Coach
AI-powered

The Vault

Where smart spenders get an edge

💡 Today's Intel

✦ Analyze

Paying minimum on Card B costs extra interest. Prioritize it.

📈

2 more on-time payments and your score could jump a band.

🧠

Ask Vault anything…

Credit Utilisation

2 min

Minimum Payments

3 min

🎯 Missions

Drop utilisation below 40%

+50 XP
Tap for design notes
Screen 05The Vault · AI Coach

Gemini 2.5 Flash analyses the current transaction feed and returns three personalised coaching tips. The Ask Vault input accepts any free-form financial question.

The Gemini prompt includes an explicit instruction — 'supportive coaching tips, not roasts' — making encouragement framing a prompt constraint, not a UI choice.

JSON parsing is wrapped in try/catch; on failure the previous intel cards are preserved, so the Vault never shows a blank state on API error.

Ask Vault fires on both Enter key and tap, ensuring the interaction is equally efficient for keyboard and touch users.

Tap to flip back
Screen 06Card Wallet
Multi-card manager

Total Balance

$36,398

Utilization

35.7%

Platinum

$4,250

Business

$12,800

Travel

$3,100

Press to Eject Cards

Tap for design notes
Screen 06Card Wallet

An animated card stack ejects on press to reveal five payment cards. Selecting a card opens a full-screen detail view with balance, quick actions, and transaction history.

The eject mechanic uses CSS translateY driven by a single React boolean — no animation library is imported, keeping the dependency surface minimal.

Each card's gradient is defined in the cards data array rather than hardcoded in JSX, making the palette trivial to retheme per institution or brand.

The wallet overlay blurs and scales the background to 90% using CSS, signalling modal context without a route change or navigation stack push.

Tap to flip back
Screen 07Send Money
P2P transfer

Send Money

Amount

$

0.00

Recent Contacts

M

Mom

M

Mike

S

Sarah

E

Elon

Send Now

SENDING FROM

Platinum Card

Tap for design notes
Screen 07Send Money

A bottom-sheet overlay for initiating peer transfers. Recent contacts are surfaced as scrollable avatar chips above a full-width amount input field.

The overlay uses absolute positioning with a blurred backdrop — no route change, no navigation stack push, no URL mutation.

Contact avatars use the first letter of each name as a fallback glyph, eliminating all image asset requests for the contact row.

Both Send and Request flows share one overlay component with the action type as a prop, halving the JSX surface for two near-identical screens.

Tap to flip back

05 · Accessibility

WCAG 2.2 Compliance

Accessibility was evaluated against WCAG 2.2 AA throughout development. The dark palette, full-width touch targets, and semantic button elements meet most criteria — documented gaps below carry implementation specifications for the next iteration.

AA

1.4.3 Contrast (AA)

Colour Contrast

Primary text (#F0EEE9) on Billie's zinc-950 background exceeds 15:1. Secondary text (zinc-400 / #A8A49D) on dark surfaces meets the 4.5:1 AA threshold. Category colour chips always include a text label — colour never encodes state alone.

#F0EEE9 on zinc-950 — exceeds 15:1

AA

2.5.3 Touch Target

Touch Targets

All primary action buttons span the full container width with p-4 padding, far exceeding the 44×44px requirement. Icon-only controls (Send, Freeze, More on card detail) use w-14 h-14 — 56px — matching the enhanced WCAG 2.5.3 target size.

Full-width CTAs · 56px icon buttons

AA

2.4.7 Focus Visible

Focus & Labels

Key icon-only buttons carry explicit aria-label attributes — aria-label='Eject Cards' on the wallet trigger and aria-label='Open Profile' on the avatar button. Tailwind's focus:ring utilities provide visible focus indicators on all interactive elements.

aria-label on wallet eject · profile button

A

1.4.1 Use of Colour

Non-Colour Cues

Transaction amounts pair positive/negative icons with colour. Cartel trend indicators combine SVG direction icons (TrendingUp, TrendingDown, Activity) with emerald/red/gray colour — colour is never the sole differentiator for any state change throughout the app.

Icon + colour on all status states

A

2.1.1 Keyboard Access

Keyboard Operation

Every interactive element in Billie uses a semantic <button> element — there are no div-based click handlers across the entire codebase. The Ask Vault input fires on Enter key press as well as button tap, serving keyboard users equally.

All interactions on semantic <button>

AA

4.1.3 Status Messages

Live Regions

The Vault's AI answer panel animates in via Tailwind animate-in. A specification gap exists: the answer container does not yet carry aria-live='polite', meaning screen reader users must navigate to the element to hear the response. This is the priority fix for the next iteration.

Spec: aria-live on Vault AI answer panel

Full Criteria Review

CriterionRequirementImplementation
1.1.1 Non-text ContentAlt text for imagesDiceBear avatar <img> tags carry alt={memberName}; decorative SVG icons use aria-hidden
1.4.11 Non-text ContrastUI component contrast ≥ 3:1Button borders (rgba 0.12 white) against dark bg meet the 3:1 minimum; active states use full-opacity borders
2.4.4 Link PurposeDescriptive link textNav labels are descriptive nouns (Home, Vault, Cartel, Spendings, Wallet) — no 'click here' patterns exist
3.2.2 On InputNo unexpected context changeTab switching requires explicit taps; no auto-navigation triggered by input field changes anywhere in the app
3.3.1 Error IdentificationError messages presentGeolocation denial surfaces an inline fallback state with a clear prompt; there are no silent failure states
2.4.11 Focus Appearance (2.2)Focus indicator ≥ 2pxSpecification gap: explicit focus ring dimensions are not enforced. Next iteration to add focus-visible:ring-2 ring-offset-2 globally via Tailwind config.

06 · Inclusivity

Designed for Financial Anxiety

Financial anxiety disproportionately affects young adults, first-generation credit card holders, and people navigating debt cycles. Billie was designed to serve these users first — assuming limited financial literacy, high emotional stakes, and varied device capability.

🖐

Physical & Motor

Full-Width Touch Targets Throughout

All primary action buttons span the full container width. Icon-only controls (Send, Freeze, More) use w-14 h-14 — 56px — exceeding WCAG 2.5.3. The card eject trigger is a 56px-wide full-height button at the bottom of the wallet, impossible to miss.

56px icon buttonsFull-width CTAsNo small icon primaries
👁

Visual

High Contrast Dark Mode Throughout

Primary text on zinc-950 background exceeds 15:1 contrast. All status states (positive, negative, warning, neutral) use icon plus colour plus text label. The app is dark-first with no light mode toggle — eliminating contrast inconsistency at the cost of system preference support.

Exceeds 15:1 primary ratioZinc-950 baseColour + icon on all states
🧠

Cognitive

Encouragement, Not Deficit Framing

The Gemini prompt is explicitly constrained to 'supportive coaching tips, not roasts.' Mission XP rewards any improvement, not only perfection. Transaction category labels are neutral descriptors — Dining, Entertainment, Travel — without moral judgement attached.

Supportive AI promptsProgress-first copyNo penalty language
👂

Screen Readers

Semantic Markup and Explicit Labels

All icon-only interactives carry descriptive aria-label attributes. The full flow uses semantic <button> elements throughout — no div-based click handlers in the entire codebase. A specification gap exists for the Vault answer panel: aria-live='polite' is the planned fix for the next iteration.

aria-label on icon buttonsSemantic <button> elementsSpec: aria-live on AI panel

Keyboard & Switch Access

Fully Tab-Navigable Flow

Every interaction is reachable and activatable via Tab and Enter alone. Focus order follows visual reading sequence top-to-bottom. The Ask Vault input fires on Enter key — keyboard users can complete the full AI coaching flow without touching the mouse.

Tab + Enter throughoutLogical focus orderEnter fires Ask Vault
🗣

Financial Literacy

Plain Language and In-Context Education

Navigation labels are plain nouns — Vault, Cartel, Spendings. The Vault section provides short 'Decode' articles on credit concepts. The Gemini prompt instructs the model to 'answer clearly and simply (ELI5)', targeting accessibility for users without financial education backgrounds.

Jargon-free navigationVault decode articlesELI5 AI responses
🆘

Error Recovery

No Dead Ends in the Flow

Geolocation denial shows a clear 'permission required' state rather than an empty offers list. Gemini API failures preserve the previous intel cards — the Vault never renders a blank state. All async operations are wrapped in try/catch with non-destructive error handling.

Inline permission fallbacktry/catch on all AI callsState preserved on error
📱

Device & Connection

Mobile-First, Minimal Network Dependency

Billie makes no background API calls — Gemini is triggered only on explicit user actions. DiceBear avatars are fetched on demand per member view. The app loads from a single bundled file with no lazy-loaded chunks, making it resilient to slow connections.

AI on-demand onlyNo background requestsSingle-file bundle

Design Principle

"Design for the most financially anxious user first. If the interface adds shame, it will drive avoidance. If the improvement doesn't feel winnable, users will never return."

Traditional finance apps optimise for users who are already disciplined. Billie optimises for users who want to be. The gamification layer, the AI encouragement constraint, and the social accountability mechanic all serve this one design principle — make improvement feel possible for someone who has been failing so far.

07 · Technology

Technology

A deliberately lean stack — chosen to maximise demonstrability in a sandboxed environment and keep the entire codebase explorable in a single read.

React 18

useState · useEffect · useRef · useMemo

UI Framework

Tailwind CSS

zinc-950 palette · animate-in · opacity modifiers

Utility Styling

lucide-react

20+ icons · consistent 24px stroke weight

Icon System

Gemini 2.5 Flash

generateContent endpoint · JSON output · ELI5 prompts

AI Coaching

DiceBear Personas

Seed-based SVG avatars · name-consistent across sessions

Avatar System

localStorage

First-run onboarding flag · single boolean key

State Persistence

Why Gemini over the OpenAI API?

Gemini 2.5 Flash offers a generous free tier with fast response times — critical for a demo that calls the API live on user interaction.

Why Tailwind for a complex dark mobile UI?

Tailwind's zinc-950/900/800 scale maps directly to Billie's layered dark palette, reducing custom CSS to near-zero while enabling fine-grained visual hierarchy.

Why localStorage for onboarding state?

Billie has no backend authentication layer. localStorage provides the simplest persistent first-run detection without introducing a session model.

08 · Trade-offs

Considered Trade-offs

Three product decisions that shaped the character and constraints of Billie.

01 —

Social Layer as Primary Motivator

Cartels make credit health a shared competitive activity — the social obligation sustains the habit where personal discipline alone fails.

02 —

AI Coach, Not AI Judge

The Gemini prompt explicitly requests 'supportive coaching tips, not roasts.' The encouragement instruction lives in the prompt, not the interface.

03 —

Single-File Architecture

All state, UI, and AI calls live in one React file — sacrificing modularity for legibility. For a portfolio artefact, reviewability outweighs conventional separation of concerns.

AttributeDecision MadeAlternative Considered
AI providerGemini 2.5 Flash via REST fetchOpenAI GPT-4o-mini (costlier, requires SDK or same pattern)
Transaction datauseMemo-generated mock arrayCSV import / real bank API (out of scope for demo)
Avatar renderingDiceBear Personas via CDN img srcInitials-based SVG avatars (consistent without network dependency)
Wallet animationCSS translateY via React booleanFramer Motion (adds ~40KB, no additional expressiveness here)
Cartel scoringClient-side composite sort on member arrayBackend aggregate score with server persistence (no backend in scope)