English | Русский
Your money, your control - anywhere, anytime.
Finapp helps you easily track and manage personal finances. The repository is a pnpm monorepo with the Nuxt application and the documentation site.
Interactive map of the codebase architecture: finapp-graph.ilko.me/en
- Simple: No clutter, no distractions - just your transactions and balances.
- Fast: Works offline and syncs instantly across devices.
- Private: You own your data - stored locally first and synced through your own Supabase backend.
- Flexible: Supports multiple currencies with automatic exchange rates.
- Portable: Optimized for mobile and desktop, installable as a PWA.
- Wallets: 6 types - cash, bank accounts, credit cards, deposits, crypto, debt.
- Transactions: expense, income, transfer, adjustment with a built-in calculator.
- Categories: hierarchical parent-child categories with custom icons and colors.
- Multi-currency: 165+ currencies with automatic daily exchange rates.
- Dashboard with summary, expense, and income tabs.
- Bar and line charts with an average line.
- Flexible date ranges: day, week, month, year, or custom period.
- Category breakdown with multiple display modes.
- Multi-select filters by wallet and category.
- Offline-first PWA that works without an internet connection.
- Local-first SQLite storage with automatic background sync on reconnect.
- Real-time sync across devices via PowerSync.
- Light, Dark, and System color modes.
- 20+ primary colors and 5 neutral palettes.
- Adjustable border radius.
- Per-tab dashboard widget configuration.
- English and Russian interface.
- Vue 3
- Nuxt 4
- Pinia
- @nuxt/ui v4 and Tailwind CSS v4
- Supabase (Postgres)
- PowerSync
- Supabase Auth
- Docus
- pnpm workspaces
finapp/
app/ # Nuxt application, Supabase + PowerSync config, tests, app assets
docs/ # Docus documentation site
The root package contains workspace scripts only. App and docs dependencies are kept in their own package manifests.
- Node.js
>=24.12.0 - pnpm
11.x - Docker and the Supabase CLI for the local backend
git clone https://github.com/ilkome/finapp.git finapp
cd finapp
pnpm installCopy the app environment example and fill in your Supabase and PowerSync values:
cp app/.env.example app/.envRequired environment variables:
VITE_SUPABASE_URL=your_supabase_url
VITE_SUPABASE_ANON_KEY=your_supabase_anon_key
VITE_POWERSYNC_URL=your_powersync_urlFor local development these point at the local stack started below: Supabase on http://localhost:54321 and PowerSync on http://localhost:8080.
The backend is local self-hosted Supabase (Postgres + Auth) plus a self-hosted PowerSync service. Run these once from the app/ workspace:
cd app
# 1. Start Supabase (Postgres + Auth on :54321)
supabase start
# 2. Apply the PowerSync replication setup (role + publication)
docker exec -i supabase_db_app psql -U postgres -d postgres < supabase/powersync_setup.sql
# 3. Start the PowerSync service (:8080)
docker compose -f powersync/docker-compose.yaml up -dThe login screen offers Sign in with Google and Demo mode. Email/password stays enabled in the Supabase backend - used by the local seed test user for E2E - but is not exposed in the UI.
supabase db reset applies app/supabase/seed.sql, which creates a fixed email/password test user (e2e@finapp.local) plus a demo-derived dataset (8 wallets, 32 categories, ~860 transactions). This lets agents / Playwright enter real PowerSync mode without Google OAuth. Apply it to a running DB without a reset:
docker exec -i supabase_db_app psql -U postgres -d postgres < app/supabase/seed.sqlSee Testing for the test-user sign-in flow (app/scripts/dev-login.mjs) and how the seed is regenerated.
The login screen shows a Sign in with Google button. To make it work against the local stack:
-
In the Google Cloud Console, create an OAuth 2.0 Client ID (Web application) and add the local Supabase callback as an authorized redirect URI:
http://127.0.0.1:54321/auth/v1/callback -
Put the client id/secret in
app/.env(the Supabase CLI loads.envfrom the directory you run it in; these feedenv()inapp/supabase/config.tomland are not shipped to the client):SUPABASE_AUTH_EXTERNAL_GOOGLE_CLIENT_ID=your_google_client_id SUPABASE_AUTH_EXTERNAL_GOOGLE_SECRET=your_google_client_secret
-
Restart Supabase so it re-reads the config and env (
supabase stop && supabase start).
The Google provider is already enabled in app/supabase/config.toml ([auth.external.google], skip_nonce_check = true for local). Leaving the env vars empty just keeps the button non-functional - email/password still works. For production, configure Google in the hosted Supabase dashboard instead (see Deployment).
The app workspace uses several .env files (all gitignored except .env.example):
| File | Purpose |
|---|---|
app/.env |
Dev values, read by Nuxt |
app/.env.prod |
Prod values, used by pnpm dev:prod |
With the local backend running, start the Nuxt app:
pnpm devThe app runs at http://localhost:3050.
Run the documentation site:
pnpm docs:devThe docs run at http://localhost:3051.
Run the app and docs dev servers together:
pnpm dev:all| Command | Description |
|---|---|
pnpm dev |
Start the app dev server |
pnpm docs:dev |
Start the documentation dev server |
pnpm dev:all |
Start app and docs dev servers in parallel |
pnpm build |
Build all workspace packages that define build |
pnpm generate |
Generate the app for static hosting |
pnpm docs:build |
Build the documentation site |
pnpm lint |
Run root-owned linting for the monorepo |
pnpm lint:app |
Run linting for the app package |
pnpm lint:docs |
Run linting for the docs package |
pnpm lint:fix |
Run linting with automatic fixes |
pnpm test |
Run tests in workspace packages |
pnpm typecheck |
Run type checks in workspace packages |
User guides, development notes, and technical reference live in docs/content.
Start the docs site with pnpm docs:dev.
The previous version of Finapp, built on Firebase, is available in the firebase branch.
- Telegram: @ilkome
