← Back to Projects Mobile App · Personal Project

Billz — Personal Expense Tracker

React Native Expo TypeScript Expo Router AsyncStorage
My role: Full-stack mobile development

About the Project

Billz is a personal expense-tracking app I designed and built for Android. The name comes from a simple idea: keep your bills in check. It gives you a clear view of what you're spending, what's left in your budget, and whether your overall financial health is on track — without demanding more effort than the act of spending itself.

The app has three focused screens: a Home dashboard that shows your remaining budget, how much you've spent, and your latest transactions; an Expenses screen where you can filter by category, see recurring bills, and track subscriptions; and a Profile screen for income, savings, category management, and preferences.

Billz supports both Arabic and English with full RTL layout switching, and lets users choose their theme (dark/light) and currency. The Android APK is available to download and install now.

My Role & Contribution

Billz is a solo project — I made every decision from the app structure to the visual design to the data model. Building something you'd actually use yourself is a different kind of pressure: the feature set has to be minimal enough to finish, and honest enough to be useful.

01App architecture & navigation

Designed the three-tab navigation structure with Expo Router, keeping each screen self-contained and the codebase flat.

02UI design & dark theme

Created the visual system — teal accent on black, card-based layout, emoji categories — and made it switchable between dark and light.

03Expense data model

Built the local-first data layer: expenses, income, savings, categories, subscriptions and recurring bills — all stored on-device so the app works with no internet.

04Bilingual support (AR / EN)

Wired up Arabic/English language switching with automatic RTL layout flip — no separate Arabic components, just logical CSS properties throughout.

App Features

  • Budget overview — see remaining budget, amount spent, and progress bar at a glance.
  • Financial health badge — a single "Good / Watch out" indicator so you always know where you stand.
  • Expense entry — add expenses with emoji categories (Groceries, Car, Fast Food, Entertainment…).
  • Category filters — tap a chip to view only expenses in that category instantly.
  • Recurring bills — log fixed monthly costs so they're never forgotten.
  • Subscriptions — track services (YouTube, Netflix…) with days-until-next-bill countdown.
  • Income & savings setup — enter your income type and log a savings amount in Profile.
  • Bilingual UI (AR / EN) — full RTL layout flip when switching to Arabic.
  • Dark / light theme — switch anytime from Profile → Preferences.
  • Data export / import — back up and restore your data without cloud dependency.

Try the App — Download

The Android build is ready to install now. iOS and store listings are on the way.

Download APK (Android) v1.0 · Android 8.0+

More platforms coming soon

Store listings and an iOS build are in progress.

Google Play Store

Android · Free

Apple App Store

iOS · Free

How It Was Built — Technical Details

1 · Expo Router — three-tab navigation

The bottom tab bar (Home / Expenses / Profile) is driven by Expo Router's file-based layout. Each tab is its own directory under app/(tabs)/, keeping screen logic isolated and the navigation stack declarative.

2 · Local-first storage with AsyncStorage

All data — expenses, income, savings, categories, subscriptions — lives in AsyncStorage. The app is fully functional with no internet connection. Data export/import lets users back up to a file without needing a backend.

3 · Dynamic theme system

A useColorScheme hook reads the persisted preference and exposes a design-token object to every component. Switching theme in Profile → Preferences updates the context and the entire app repaints instantly with no reload.

4 · Bilingual RTL support

Switching to Arabic triggers React Native's built-in RTL engine. All layout uses logical properties (marginStart, paddingEnd, alignSelf) so the entire UI mirrors correctly without any Arabic-specific component variants.

5 · Subscription reminder logic

Each subscription stores its billing date. A small utility function computes "days until next bill" by comparing the stored date with today. The result shows as a chip ("30 days", "TOMORROW") directly on the subscription card.

Challenges

01

Budget remaining — staying accurate across add/delete

The "remaining" figure on the home screen must always equal income minus the sum of all expenses. Getting this to update in real time — including when the user adds, edits or deletes an expense mid-session — required a single derived-state pattern rather than storing the remaining value separately.

02

Category system — flexible but not overwhelming

Users want to customise categories, but a fully open system can become messy fast. The solution was a base set of emoji categories (Groceries, Car/Transport, Fast Food, Entertainment) that are toggleable and extensible with subcategories — structure without rigidity.

03

RTL + LTR in one codebase

No hardcoded "left" or "right" values anywhere — every spacing value uses React Native's logical properties. This discipline is invisible when it works and painful to retrofit when it doesn't, so it had to be enforced from screen one.

04

Data portability without a backend

Users shouldn't lose their data if they switch phones. Without a cloud backend, the solution was a JSON export/import flow that serialises the full data model to a file the user can save and restore. This also doubles as a manual backup.

Impact

Billz makes the invisible visible. Most people don't know how much they've spent this month until they check their bank statement — Billz puts that number on the home screen every time you open the app.

3 screens

covering the full cycle: track expenses, review by category, manage income and settings.

AR + EN

full bilingual support with RTL layout from a single shared codebase.

0 backend

fully local-first — works offline, no sign-up, no data sent to any server.

Lessons Learned

  • Local-first is the right default for personal finance apps — users do not want their spending data on a server they didn't choose.
  • RTL discipline is a day-one commitment, not a refactor. One hardcoded left margin buried in a component can break an entire Arabic screen.
  • A minimal feature set ships. Every feature I cut made the app more likely to actually exist in users' hands.
  • Derived state is safer than stored state — the budget remaining should always be calculated, not saved, so it can never go stale.