The Story Behind Wallet++

💡 What Inspired Me

The idea for Wallet++ came from a simple frustration: managing personal finances shouldn't be complicated. I found myself drowning in receipts, struggling to remember transactions, and spending more time organizing my finances than actually understanding them.

I wanted to build something that felt magical—where you could just snap a photo of a receipt, speak a transaction into your phone, or have a conversation with an AI about your spending habits. The vision was to create a financial companion that felt as intuitive as talking to a friend, but with the intelligence of a financial advisor.

The name "Wallet++" reflects this philosophy: it's not just a wallet, it's a wallet that's been enhanced, upgraded, and made better—just like how we use ++ in programming to increment and improve.

🎓 What I Learned

Building Wallet++ was a journey of discovery across multiple domains:

AI Integration & Vision APIs

I learned how to work with Groq's Vision API for OCR, understanding how to convert PDFs to images, handle different file formats, and extract structured data from unstructured documents. The challenge of parsing receipts and bank statements taught me about data validation, error handling, and graceful degradation when AI doesn't get it perfect.

Modern React & Next.js

This project pushed me to master Next.js 15 and React 19, including:

  • Server-side API routes for secure AI interactions
  • Client-side state management with Zustand
  • Optimistic UI updates for better user experience
  • Proper TypeScript typing throughout the application

Database Design & Real-time Updates

Working with Supabase taught me about:

  • PostgreSQL schema design for financial data
  • Row-level security policies
  • Efficient querying with proper indexing
  • Handling duplicate transactions intelligently

UI/UX Design

I studied Apple's Human Interface Guidelines to create an interface that feels premium and intuitive. This included:

  • Thoughtful animations with Framer Motion
  • Responsive design patterns
  • Accessibility considerations
  • Creating delightful micro-interactions

PDF Generation & Data Visualization

I learned to generate professional PDF reports using jsPDF and create interactive charts with Recharts. The visual planning canvas using React Flow taught me about graph-based data structures and drag-and-drop interactions.

Technical Architecture

┌─────────────────────────────────────────┐
│         Next.js 16 Frontend            │
│  ┌──────────┐  ┌──────────┐  ┌──────┐  │
│  │  React   │  │ Zustand  │  │ UI   │  │
│  │   19     │  │  Store   │  │Shadcn│  │
│  └──────────┘  └──────────┘  └──────┘  │
└─────────────────────────────────────────┘
                    │
        ┌───────────┼───────────┐
        │           │           │
┌───────▼───┐ ┌────▼────┐ ┌────▼────┐
│ Supabase  │ │  Groq   │ │  PDF    │
│ PostgreSQL│ │   AI    │ │Generator│
└───────────┘ └─────────┘ └─────────┘

🚧 Challenges I Faced

1. PDF to Image Conversion

The Problem: PDFs couldn't be sent directly to Groq Vision API, and the PDF.js worker kept failing with CDN issues.

The Solution: I implemented client-side PDF conversion by:

  • Copying the PDF.js worker file locally to the public folder
  • Converting the first page of PDFs to PNG images before OCR
  • Handling errors gracefully with user-friendly messages

What I Learned: Sometimes the best solution is to handle things client-side rather than relying on external services.

2. Animation Disappearing Elements

The Problem: Components would appear and then immediately disappear due to CSS animation conflicts.

The Solution: Removed problematic animate-fade-in classes that set opacity: 0 initially. The animations weren't completing properly with conditional rendering, so I simplified the approach.

What I Learned: Animations need to be carefully tested with conditional rendering and state changes.

3. Duplicate Transaction Detection

The Problem: Initially, duplicates were being skipped entirely, but users might intentionally have duplicate transactions.

The Solution: Changed the approach to flag duplicates for user review rather than automatically skipping them. Added validation to skip duplicate checks when data is incomplete.

What I Learned: User control is more important than automation—always give users the final say.

4. TypeScript Build Errors

The Problem: Multiple TypeScript errors during build, including missing properties and type mismatches.

The Solution:

  • Added missing canvas property to PDF render parameters
  • Fixed Supabase update type assertions to use proper Database types
  • Ensured all type definitions matched the actual implementation

What I Learned: TypeScript's strict typing catches errors early, but requires careful attention to type definitions.

5. Data Validation & User Experience

The Problem: Users could submit incomplete transactions, causing database errors.

The Solution: Implemented comprehensive client-side validation:

  • Validates all required fields before submission
  • Shows clear error messages at the top of the review modal
  • Disables confirm button when validation fails
  • Provides per-transaction error feedback

What I Learned: Always validate on the client side for better UX, but never trust client-side validation alone.

6. Chat History Management

The Problem: Managing multiple conversations and pagination was complex.

The Solution: Simplified to a single conversation model with automatic separators when there's a 10-minute gap. This made the UX cleaner and the code simpler.

What I Learned: Sometimes simplifying the feature is better than building complex pagination systems.

7. Metrics Calculation

The Problem: Some metrics were confusing or not industry-standard.

The Solution: Researched financial industry standards and refined metrics:

  • Changed "Avg Transaction" to "Avg Expense" for clarity
  • Added "Daily Spending" vs "Expense Ratio" based on time period
  • Improved savings rate calculation to handle edge cases
  • Added useful metrics like "Largest Transaction" and "Most Frequent Category"

What I Learned: Always validate your calculations against industry standards and real-world use cases.

🎯 Key Decisions

Why Groq?

I chose Groq for its speed and cost-effectiveness. The API is fast, reliable, and offers multiple models (Llama 3.1, Whisper, Vision) in one platform.

Why Supabase?

Supabase provided everything I needed: PostgreSQL database, authentication, and real-time capabilities. The row-level security made it easy to implement user-specific data access.

Why Shadcn UI?

Shadcn UI gave me beautiful, accessible components that I could customize. The component-based approach meant I could modify components to fit my exact needs.

Why Zustand?

Zustand is lightweight and simple. For a project of this scope, it provided all the state management I needed without the complexity of Redux.

🚀 What's Next?

While Wallet++ is functional and polished, there's always room to grow:

  • Mobile App: Native iOS and Android apps for better mobile experience
  • Budgeting Tools: Set budgets and get alerts when approaching limits
  • Recurring Transactions: Automatically detect and suggest recurring expenses
  • Multi-Currency: Support for international users
  • Bank Integration: Direct API connections to banks for automatic transaction import
  • Advanced AI: More sophisticated financial planning and goal tracking

💭 Final Thoughts

Building Wallet++ taught me that great software isn't just about features—it's about creating an experience that feels effortless. Every decision, from the gradient logo to the smooth animations, was made with the user in mind.

The most rewarding part was solving real problems: making PDF scanning work reliably, ensuring data validation prevents errors, and creating an AI assistant that actually feels helpful rather than gimmicky.

This project represents not just a finance tracker, but a vision of how AI can make our daily lives easier. It's a wallet that doesn't just hold your money—it helps you understand it, plan with it, and make better financial decisions.


Built with ❤️ by Stefan Khor and lots of ☕ during late-night coding sessions._

Built With

Share this project:

Updates