A voice-first, local-first personal finance companion for iPhone and iPad.
MiaoJi turns natural Mandarin speech into structured expense entries, keeps the ledger available offline, and optionally synchronizes it across devices through Supabase. Its focused SwiftUI interface combines fast entry, budgets, category insights, search, CSV export, and light/dark appearance support.
Note
MiaoJi is under active development. Review the privacy and deployment notes before using the voice pipeline with sensitive financial information.
![]() |
![]() |
![]() |
![]() |
| Fast entry | Spending insights | Searchable history | Personal controls |
- Voice-first capture — record Mandarin expense descriptions and turn multiple purchases into categorized drafts.
- Local-first ledger — records, categories, budgets, currency preferences, and appearance settings remain usable offline.
- Optional cloud sync — email OTP authentication and row-level security keep each Supabase account snapshot isolated.
- Useful analytics — monthly, quarterly, and yearly trends, category distribution, budget progress, and concise conclusions.
- Practical controls — manual income/expense entry, editing, filters, multiple currencies, custom categories, and CSV export.
- Native experience — SwiftUI interface for iPhone and iPad with light and dark themes.
flowchart LR
A["SwiftUI client"] -->|"M4A upload"| B["Flask API"]
B --> C["Supabase Storage"]
B -->|"Audio + category schema"| D["DashScope multimodal model"]
D -->|"Normalized expense drafts"| B
B --> A
A <-->|"Email OTP + account snapshot"| E["Supabase Auth & Postgres"]
| Layer | Technology | Responsibility |
|---|---|---|
| Client | Swift 5, SwiftUI, AVFoundation | Recording, ledger UI, local persistence, CSV export |
| API | Python, Flask | Audio validation, storage upload, AI response normalization |
| Data | Supabase Auth, Postgres, Storage | OTP authentication, RLS-protected snapshots, audio objects |
| AI | DashScope OpenAI-compatible API | Mandarin audio understanding and structured expense extraction |
.
├── client/ # SwiftUI application, unit tests, and UI tests
├── server/ # Flask voice-processing API and tests
├── supabase/ # Database migration and Supabase setup notes
└── docs/assets/ # Brand assets and product previews
- macOS with Xcode 16 or later
- iOS/iPadOS 18 or later
- Python 3.9 or later
- A Supabase project
- A DashScope API key for voice parsing
git clone https://github.com/KapiYue/miaoji.git
cd miaojiRun every SQL file in [supabase/migrations](supabase/migrations) in filename order using the Supabase SQL Editor. Then configure email OTP templates as described in [supabase/README.md](supabase/README.md).
The voice pipeline uses a private Storage bucket named user-audio. The API creates short-lived signed URLs and deletes uploaded recordings after parsing; configure a 24-hour lifecycle cleanup as a fallback for interrupted requests.
Update [client/MiaoJiConfig.xcconfig](client/MiaoJiConfig.xcconfig):
MIAOJI_API_BASE_URL = http:/$()/127.0.0.1:8000
SUPABASE_URL = https:/$()/YOUR_PROJECT.supabase.co
SUPABASE_PUBLISHABLE_KEY = YOUR_PUBLISHABLE_KEY
Never place a Supabase service_role key in the iOS application. Open [client/MiaoJiAccout.xcodeproj](client/MiaoJiAccout.xcodeproj) in Xcode, select the MiaoJiAccout scheme, and run it on a simulator or device.
cd server
python3 -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txt
cp .env.example .env
python -m flask --app app run --host 0.0.0.0 --port 8000Fill in server/.env before starting the API. Server-side secrets must never be committed.
Run the backend test suite:
python -m unittest server/test_app.pyRun the iOS tests from Xcode with Product → Test, or from the command line with an installed simulator:
xcodebuild test \
-project client/MiaoJiAccout.xcodeproj \
-scheme MiaoJiAccout \
-destination 'platform=iOS Simulator,name=iPhone 16 Pro'- Ledger data is stored locally and can optionally be synchronized to Supabase.
- Voice recordings are uploaded to the configured Supabase Storage bucket and sent to the configured DashScope model for parsing.
- The Flask API requires the Supabase
service_rolekey; keep it exclusively on a trusted server. - Review
[SECURITY.md](SECURITY.md)for vulnerability reporting and[supabase/README.md](supabase/README.md)for RLS setup. - Follow
[docs/app-store-release-checklist.md](docs/app-store-release-checklist.md)before creating an App Store archive.
Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) and follow our [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) before opening an issue or pull request.
MiaoJi is available under the MIT License.
- Repository: github.com/KapiYue/miaoji
- Maintainer: zdjoey@126.com



