A private, self-hosted Progressive Web App (PWA) for collaborative household financial management. Built for families who want one place to track every rupee — without handing their data to a third-party service.
Managing money as a family is genuinely hard:
- No shared visibility. One person pays the electricity bill, another handles groceries, and nobody has the full picture at the end of the month.
- Fragmented tools. Spreadsheets break, bank apps show only one person's accounts, and commercial apps like Mint or YNAB cost money and store sensitive data on their servers.
- Privacy within the household. Not every expense should be visible to every family member — personal medical costs or individual savings goals deserve discretion.
- Recurring payments are invisible until they hit. Subscriptions, EMIs, rent, and SIPs silently drain accounts and are only noticed when something bounces.
- Offline gaps. Mobile data drops; a finance app that stops working without internet is not reliable enough for daily use.
ShreeOne is a self-hosted web app that runs entirely on your own server or home machine. Your financial data never leaves your network.
| Need | How ShreeOne solves it |
|---|---|
| Shared family view | All members see a unified dashboard across all accounts |
| Role-based privacy | Three privacy levels — Private, Shared (couple), Family — per transaction |
| Recurring payments | Auto-processed daily; bills appear in the ledger without manual entry |
| Offline use | Full PWA with a service worker; transactions queue locally and sync when connectivity returns |
| Install on Android | "Add to Home Screen" from Chrome — launches like a native app |
| Self-hosted | Docker Compose brings up the entire stack in one command |
- Multi-account tracking — bank accounts, credit cards, wallets, savings
- Income & expense categorisation with custom categories per family
- Budget settings — monthly limits per category with alerts
- Recurring payments — subscriptions, EMIs, SIPs auto-posted at midnight daily
- Dashboard trends — income vs expense charts, category breakdowns, monthly comparisons
- Role-based access — Admin, Member, Viewer with granular permission overrides
- Transaction privacy — Private / Shared / Family visibility per entry
- Passkey / WebAuthn — passwordless login support alongside JWT
- Dark / Light / Auto theme
- Database backups — automated script retaining 7 days of history
- Offline-first PWA — IndexedDB queue, auto-sync on reconnect
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS, React Query v5, Zustand |
| PWA | vite-plugin-pwa, Service Worker, IndexedDB |
| Backend | Python 3.12, FastAPI, SQLAlchemy 2.0, Pydantic v2 |
| Auth | JWT (access 30 min / refresh 7 days) + WebAuthn passkeys |
| Database | PostgreSQL 16 |
| Scheduler | APScheduler (recurring payments at 00:00, token pruning at 01:00) |
| Infrastructure | Docker + Docker Compose, Nginx |
- Docker 24+
- Docker Compose v2+ (bundled with Docker Desktop)
- Git (Optional)
git clone <your-repo-url> shreeone
cd shreeonecp .env.example .envOpen .env and set strong values:
# Strong password for PostgreSQL
DB_PASSWORD=replace_with_a_strong_password
# Random secret for JWT signing — at least 32 bytes of hex
# Generate one: python3 -c "import secrets; print(secrets.token_hex(32))"
SECRET_KEY=replace_with_a_long_random_secret
# URL the browser uses to reach the app
# For local network access use your machine's LAN IP, e.g. http://192.168.1.100:5173
FRONTEND_URL=http://localhost:5173docker compose up -d --buildThis starts three containers:
| Container | Role | Port |
|---|---|---|
shreeone-db |
PostgreSQL 16 | internal |
shreeone-api |
FastAPI backend | internal |
shreeone-web |
Nginx + React SPA | 5173 |
Database tables are created automatically on first startup. Recurring payment processing runs immediately on startup and then daily at midnight.
Navigate to http://localhost:5173 (or your server's LAN IP on port 5173).
On first visit, register your family and create the first admin account.
curl http://localhost:5173/health
# {"status":"healthy","version":"1.0.0"}To use ShreeOne from phones or tablets on the same Wi-Fi:
-
Find your server's local IP address:
ip addr show | grep "inet " | grep -v 127.0.0.1 # e.g. 192.168.1.42
-
Update
.env:FRONTEND_URL=http://192.168.1.42:5173
-
Restart the backend container to pick up the new CORS origin:
docker compose up -d backend
-
Open
http://192.168.1.42:5173on any device on the network.
ShreeOne ships with a full PWA manifest and service worker. Installing it on Android gives a native-app experience: full-screen launch, offline support, and a home-screen icon.
- Open Chrome on your Android device.
- Navigate to the ShreeOne URL (e.g.
http://192.168.1.42:5173). - Log in to your account.
- Tap the three-dot menu (top-right corner).
- Tap "Add to Home screen" (or "Install app" if Chrome shows a banner).
- Confirm the name and tap Add.
The app icon appears on your home screen and in the app drawer. Launching it opens ShreeOne in standalone mode (no browser chrome) with:
- Offline access — cached pages and queued transactions work without internet.
- Background sync — queued operations (new transactions, edits) sync automatically when connectivity returns.
- Service worker updates — the app checks for updates in the background and prompts when a new version is ready.
| Issue | Fix |
|---|---|
| "Add to Home screen" not shown | Must be served over HTTPS or from localhost/LAN IP; ensure you are using Chrome, not a WebView |
| App loads but API calls fail offline | Confirm you visited and logged in at least once while online so the service worker could cache the shell |
| Updates not appearing | Pull-to-refresh or clear Chrome's site data for the URL |
HTTPS note: Chrome requires HTTPS for service workers on public domains. For a local home network deployment,
http://LAN addresses work fine. For internet-accessible deployment, place the app behind a reverse proxy (e.g. Caddy or Nginx) with a TLS certificate.
# Stop all containers (data preserved in Docker volume)
docker compose down
# Stop and remove the database volume (destructive — all data lost)
docker compose down --volumes
# Restart after a reboot
docker compose up -dA backup script is included at scripts/backup.sh. It dumps the database, compresses it, and retains the last 7 days of backups in the ./backups/ directory.
Run manually:
docker compose exec db sh /backups/../scripts/backup.shOr schedule it via cron on the host:
# Example: run at 2am every day
0 2 * * * docker compose -f /path/to/shreeone/docker-compose.yml exec -T db pg_dump -U postgres shreeone | gzip > /path/to/shreeone/backups/shreeone_$(date +\%Y\%m\%d).sql.gz| Variable | Required | Default | Description |
|---|---|---|---|
DB_PASSWORD |
Yes | — | PostgreSQL password |
SECRET_KEY |
Yes | — | JWT signing key (min 32 chars) |
FRONTEND_URL |
Yes | http://localhost:5173 |
Comma-separated allowed origins for CORS |
ACCESS_TOKEN_EXPIRE_MINUTES |
No | 30 |
JWT access token lifetime |
REFRESH_TOKEN_EXPIRE_DAYS |
No | 7 |
JWT refresh token lifetime |
When the backend is running, interactive API docs are available at:
- Swagger UI:
http://localhost:5173/api/docs(proxied via Nginx to the backend) - Alternatively hit the backend directly on its internal port if you expose it
shreeone/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI app, scheduler, CORS
│ │ ├── models.py # SQLAlchemy models (14 tables)
│ │ ├── crud.py # DB operations
│ │ ├── auth.py # JWT + WebAuthn helpers
│ │ ├── config.py # Pydantic settings
│ │ └── routers/ # auth, accounts, transactions, categories, dashboard, settings, sync, admin
│ ├── tests/ # pytest test suite
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ ├── src/
│ │ ├── pages/ # Login, Dashboard, Accounts, Transactions, Settings, ...
│ │ ├── components/ # Reusable UI components
│ │ ├── services/ # Axios API client, WebAuthn
│ │ ├── store/ # Zustand stores (auth, theme)
│ │ └── lib/ # IndexedDB offline queue
│ ├── public/ # Icons, manifest
│ ├── nginx.conf # Nginx config (serves SPA, proxies /api/)
│ ├── package.json
│ └── Dockerfile
├── scripts/
│ └── backup.sh
├── docker-compose.yml
└── .env.example
MIT License — feel free to use and modify.