Back to selected work

Case study

ByteWallet

Fullstack DeveloperFebruary 2026 – Present

Personal finance · Gmail auto-record · API design · Multi-platform

A personal finance app for multi-wallet cashflow, friend transfers, split bills, and Gmail auto-recording of bank and e-wallet emails — Expo client, NestJS API, iOS, Android, and web.

System architecture

The system I built

I designed how these layers connect — interface, business rules, data, and delivery — not only the screens on top.

  1. 01

    User apps

    Expo mobile, Expo web, Personal AI, RightNow

  2. 02

    Core product

    Wallets, transactions, friends, Trace, split bills, analysis

  3. 03

    API

    NestJS REST + WebSocket, JWT and API-key guards

  4. 04

    AI + data

    Scoped AI keys, PostgreSQL, Redis, notifications

How the layers connect

100%

Labeled arrows show which parts talk to each other, and how.

User applications

Mobile app

Expo React Native

Web app

React / Expo web

Personal AI chat

Read-only integration

RightNow chat

Read + write integration

Client layer

Authentication

Email/password, Google OAuth, Remember Me

Local storage

AsyncStorage and Secure Store

AI integrations

Personal AI

Read-only finance access

RightNow

Read and write finance access

API key management

Create, list, revoke, hash, expiry

Core features

Multi-wallet

Per-wallet currency and Main wallet

Transactions

Income, expense, transfer, borrow, lend

Friends

Requests and friend transfers

AR/AP Trace

Payable and receivable debts

Split bills

Shared expenses and public share links

Analysis

Cashflow charts, heatmap, PDF export

ByteWallet API

HTTP + WebSocket

App and integration traffic

Auth guards

JWT, API keys, role, owner

Business logic

Wallets, transactions, debts, friends, split bills, AI, notifications

Security

API key hashing

SHA-256 storage

Owner guard

User isolation

Scope enforcement

finance:read and finance:write

Rate limiting

Per API key

Audit logging

Key ID and action

Data layer

PostgreSQL

Supabase

Redis

Cache and notifications

Notifications

In-app, WebSocket, Expo push

Personal AI chat

Read-only Q&A

Balance, spending, debt inquiry

RightNow chat

Finance Q&A

LLM tool calling

Bot commands

/expense, /income, /transfer with confirmation

Gallery item
Gallery item
Gallery item
Gallery item
ByteWallet
Drag any photo down to close

Problem

Everyday money is split across wallets, friends, and bank notification emails. ByteWallet needed one product for cashflow, P2P debts, and split bills — plus an opt-in path to turn Gmail bank alerts into ledger entries without pasting them by hand.

My contribution

  • Designed the product around multi-wallet cashflow, a reserved Main wallet for friend money, and NestJS modules with transactional boundaries
  • Built the Expo app (tabs, auth, wallet detail, Trace, split bills, analysis, Gmail sync settings) and the typed API client
  • Implemented auth (email/password, Google OAuth, OTP reset, JWT sliding sessions) and wallet rules that block income/expense on Main
  • Shipped Gmail auto-recording: readonly OAuth, AES-256-GCM refresh-token storage, Gemini parsing, SHA-256 dedup, pending review, and 15-minute polling with Sync Now
  • Modeled friend transfers, AR/AP Trace (repay, mark received, reject/refund), and split bills with time-limited public share links
  • Added scoped API keys for Personal AI (read) and RightNow (read/write), plus in-app, WebSocket, and push notifications
  • Deployed the web client on Cloudflare Pages and the NestJS API on Render, including cold-start wake

Engineering challenges

  • Parsing messy bank and e-wallet emails without double-counting the same alert
  • Keeping Gmail credentials encrypted at rest and never sending refresh tokens to the model
  • Enforcing Main-wallet rules while friend transfers and repayments still land immediately
  • Letting users review auto-detected mail (edit wallet, category, type) before it becomes a transaction
  • Shipping one codebase to iOS, Android, and web without treating the API as an afterthought

Why I made this decision

Why a reserved Main wallet?
Friend transfers and repayments needed a single, non-deletable destination so P2P money did not mix with everyday income and expense on spending wallets.
Why pending review for Gmail sync?
Gemini extraction is useful but not infallible. An opt-in queue lets people edit type, category, note, and wallet — or reject — before the ledger changes.
Why NestJS modules instead of a thin BFF?
Wallets, debts, Gmail sync, and API-key scopes needed guards, DTOs, and transactional services. A modular API kept those boundaries explicit.
Why Expo for the client?
One React Native app covering iOS, Android, and web matched the product surface (tabs, push, PDF export) without a separate native stack.

Delivery

  1. Git
  2. Development
  3. Local testing
  4. CI / build
  5. Cloudflare Pages + Render
  6. Production

Result

  • Live web app at bytewallet.pages.dev (iOS, Android, and web from Expo)

  • Gmail auto-record with encrypted tokens, Gemini parse, and pending review

  • Wallets, Trace AR/AP, split bills, notifications, and scoped AI API keys in one NestJS API

Built with

Expo / React NativeExpo RouterNestJSTypeORMPostgreSQLRedisGmail APIGemini AIJWT + API keys