Finote – Master Your Finances

Finote – Master Your Finances

A personal finance manager with multi-wallet support, real-time spending analytics, and receipt capture.

Type

Mobile App

Role

Mobile Developer

Built

Q4 2025

Updated

Q4 2025

Source

GitHub

Tech Stack

react-native
Expo
TypeScript
Firebase
Zod
Zustand
cloudinary
reanimated
gifted-charts
01

Why I Built This

Every finance app I tried either felt like enterprise software or lacked the features I actually needed. I wanted something in between — a personal tool that could handle multiple wallets, show me clear spending trends, and let me snap receipts on the go. So I built it myself.

Finote was also my deep dive into React Native. I wanted to move beyond web and understand mobile-specific constraints: gesture handling, 60fps animations on lower-end devices, and offline-first data patterns.

02

How It Works

The app revolves around wallets — you create buckets like Salary, Freelance, or Cash, and log transactions against them. Each transaction can have a category, amount, notes, and an optional receipt photo.

The home screen shows a real-time snapshot: total balance across wallets, recent transactions, and an interactive bar chart (weekly or yearly view) powered by react-native-gifted-charts. You can drill into any wallet to see its individual history and trends.

All data syncs through Firebase — Firestore for structured data, Firebase Auth for login. Receipt images upload to Cloudinary for optimization and CDN delivery, keeping the app lightweight even with heavy media usage.

03

Key Decisions

Zustand over Context for state management

React Context re-renders the entire tree on any change. For a finance app where the transaction list, wallet balances, and chart data all update independently, Zustand's selector-based subscriptions made a significant difference in keeping the UI snappy.

Optimistic UI for transaction creation

When a user logs a transaction, the local state updates immediately. Firestore syncs in the background. If the sync fails, the state rolls back with a toast notification. This pattern eliminates the perceived latency of network requests and keeps the app feeling instant.

Reanimated for custom animations

The default Animated API couldn't hit 60fps for the custom tab bar and chart transitions I wanted. Reanimated runs animations on the native thread, which made complex gestures and spring-based transitions smooth even on mid-range devices.

Blob uploads instead of base64

My first attempt at receipt uploads sent base64-encoded strings directly. This bloated payloads and blocked the main thread during encoding. Switching to Blob-based FormData uploads cut transfer sizes and made uploads non-blocking, keeping the app responsive during file transfers.

04

What I Learned

Mobile data density requires careful design. Rendering financial data on small screens is a constant tradeoff between granularity and readability. I customized Gifted Charts extensively to ensure touch targets stayed accessible and animations held at 60fps even with yearly datasets.

Offline-first thinking changes your architecture. Even though Finote isn't fully offline-capable, designing with optimistic updates and background sync forced me to think about state consistency in ways that web development rarely does.

React Native has its own performance culture. Bridge calls, JS thread blocking, and re-render cascades are problems you don't encounter on the web. Profiling with Flipper and understanding the Reanimated worklet model were essential skills I picked up.

Up Next

StarForge – AI SaaS Template

A sleek AI SaaS landing page with a user-friendly design that enhances engagement.

Web App