Masareef (مصاريف, "expenses") is a mindful, offline-first personal spending tracker built for Egypt — wallets, fast logging, budgets, insights, and recurring bills, with a bank-notification auto-capture engine and last-write-wins cloud sync across devices. Built with Expo SDK 57, React Native 0.86, a local SQLite source of truth, and a Next.js + Neon backend.
Masareef (مصاريف) is Egyptian Arabic for expenses. The goal: see where your money goes without the friction of most finance apps — log spending in seconds, let bank notifications fill in the rest, and never fight the tool.
Coming soon
Masareef is in Google Play closed testing — a public production release is on the way. Android-first, English (v1), EGP.
Screens
| Home | Review queue | Insights |
|---|---|---|
![]() |
![]() |
![]() |
| Budgets | Wallets | Add |
![]() |
![]() |
![]() |
| Recurring | Settings | |
![]() |
![]() |
Why Masareef
Most finance apps make you fight for every entry, then ask you to trust the cloud with your raw transactions. Masareef flips both: logging is a couple of taps, your bank's own notifications do the data entry, and everything lives on your device first.
- Offline-first, instant — a local SQLite database is the single source of truth, so every read and write is immediate and works with no signal. Cloud sync is a best-effort background reconciler, never a blocker.
- Auto-capture, not auto-trust — paste (or, with permission, auto-read) a bank notification/SMS and Masareef parses the amount, merchant, and bank into a review queue. Nothing touches your balances until you confirm.
- Privacy by design — a one-tap Hide balances mask, and analytics that never carry amounts, merchants, or balances — structural events only.
- Polished in light & dark — a "Nocturne" identity that follows the system by default, built on a dual palette with no hardcoded colors.
Features
Wallets
- Track cash, bank accounts, cards, and mobile wallets side by side, each with its own balance and color
- Edit a wallet's balance directly — the opening balance is back-solved from the ledger so history stays intact
- Per-card Hide balances toggle for shoulder-surfing privacy
Fast logging
- A purpose-built numpad + category picker to record an expense, income, or transfer in a couple of taps
- Comma-grouped amounts, an animated category slider, and date editing
- Money is stored as integer piastres end to end — never floats — and rendered through one formatting path
Auto-track (bank capture)
- A notification-listener bridge (Play-safe) + optional SMS parses bank messages into a review queue
- Bank-only allowlist gate — no "any number" noise from OTPs, promos, or invoices
- Handles fan-out / IPN messages, transfers (routed to the right wallet by name), Arabic + English, and reference-based dedupe
- Learns merchant → category rules as you confirm, and auto-categorizes on the next match
- Killed-app capture: the headless task can parse, accept, and notify without the app being open
Budgets & insights
- Per-category monthly limits with live progress rings and opt-in budget-alert notifications
- Month totals, average daily spend, biggest expense, and a spend-by-category breakdown with interactive charts
- A month-end forecast, a weekday spending heatmap, and a per-period spending-summary digest
Recurring
- Model monthly bills and subscriptions with catch-up for missed cycles
- An upcoming-recurring strip so nothing surprises you
Cloud sync
- Sign in and your wallets, transactions, budgets, and categories follow you to any device
- Fully offline-first: edits happen locally and instantly, then reconcile in the background (last-write-wins by timestamp)
- Two clocks kept separate — a client clock decides who wins, a server cursor decides what's new — so sync is immune to device clock skew; deletes propagate as tombstones and the network layer never throws
Extras
- CSV export + JSON backup/restore (file pick, paste, or share-intent)
- Worldwide banks + multi-currency (active-currency minor units) and nearby-ATM finder (keyless Overpass)
- Haptics, toast + undo, empty-state CTAs, and an in-app "How Masareef works" guide
How it's built
Offline-first by design: the local SQLite database is the single source of truth for the UI. Cloud sync runs as a best-effort background reconciler against a Next.js 16 + Drizzle + Neon (Postgres) backend on Vercel — local changes are flagged and pushed, remote changes pulled, and conflicts resolve last-write-wins by timestamp. Money is integer piastres from the database to the pixel; a single formatting path renders it. Session lives in SecureStore via better-auth + @better-auth/expo.
Tech stack
| Layer | Choice |
|---|---|
| Framework | Expo SDK 57 (managed) + Expo Router (typed routes, declarative auth guards) |
| Runtime | React Native 0.86 / React 19, React Compiler enabled |
| Language | TypeScript, strict mode |
| UI | NativeWind 4 (Tailwind) + a dual light/dark palette (usePalette()) |
| Client state | Zustand, persisted to MMKV |
| Local data | expo-sqlite — source of truth, offline-first |
| Cloud sync | custom last-write-wins engine over a typed pull/push contract |
| Backend | Next.js 16 + Drizzle + Neon (Postgres) on Vercel |
| Server state | TanStack Query |
| Auth | better-auth + @better-auth/expo (session in SecureStore) |
| Auto-track | notification-listener bridge (Play-safe) + SMS parser + capture queue |
| Animation | react-native-reanimated · SVG via react-native-svg |
| Icons | lucide-react-native |
| Analytics | PostHog (privacy-safe — no amounts, merchants, or balances) |
Non-negotiables
- Offline-first. The local SQLite DB is the source of truth; the app is fully usable with no connection and sync is never a blocker.
- Money is integer piastres. Never floats, end to end — one formatting path renders every amount.
- Auto-capture never auto-trusts. Parsed bank messages land in a review queue; nothing changes a balance until the user confirms.
- Analytics carry no financial data. Structural events only — never amounts, merchants, or balances.









