Sharia-compliant personal finance app for Tunisian young workers. AI-driven halal/haram transaction classification, receipt OCR, lunar-calendar Zakat, EN/FR/AR with RTL. NestJS + Next.js 16 + Expo + OVH AI Endpoints.
# Halal Wallet
**A Sharia-compliant personal finance app for Tunisian young workers.**
Web + mobile, with AI-driven halal/haram transaction classification, receipt OCR,
Zakat tracking on the lunar calendar, and a multilingual interface in EN / FR / AR.
Stack · Quick start · Architecture ·
AI features · Roadmap · License
---
## Why this exists
Conventional personal-finance apps are blind to Islamic finance principles. They
happily categorize a wine-bar charge as "Restaurants" and quietly accumulate
interest income that a practicing Muslim cannot keep. Halal Wallet's premise is
simple: **every transaction should be classified halal / haram / doubtful at
the moment it enters your wallet**, and Zakat should be tracked on the
lunar (Hijri) calendar the same way it has been for fourteen centuries.
The target user is a young Tunisian worker who already uses Wally, Bankin', or
the e-Dinar app to track spending but has no way to align that tracking with
their faith.
## Stack
- **Monorepo** — pnpm workspaces, packages namespaced under `@zubbi/*`
- **Backend** — NestJS + Prisma + PostgreSQL
- **Web** — Next.js 16 (App Router) + Tailwind v4 + shadcn/ui + react-i18next
- **Mobile** — Expo SDK 53 + Expo Router + NativeWind + react-i18next
- **Auth** — Passport-JWT (access + refresh) + phone OTP. No third-party identity provider.
- **AI** — OVH AI Endpoints (OpenAI-compatible). All AI calls live in `packages/ai` and run **server-side only** from NestJS — the OVH API key never reaches the browser or device.
- **Storage** — abstract `StorageService`. Dev driver writes to `./storage` on disk; production driver writes to S3-compatible OVH Object Storage. Only file paths are persisted in Postgres.
- **i18n** — every UI string flows through `t()`. Three languages: English, French, Arabic. Arabic renders right-to-left.
### Money is integer millimes, end of story
All monetary amounts are stored and transmitted as **integer millimes**
(1 Tunisian Dinar = 1000 millimes). Format …