--- title: Splitwise emoji: 💸 colorFrom: green colorTo: blue sdk: docker app_port: 7860 pinned: false --- # Splitwise-style expense splitter Shared expenses for a small group of friends: equal / percent / exact splits, receipt photos, balances with simplified debts, settlements, and an admin who manages users. Data lives in a private Hugging Face Storage Bucket as an append-only event log (`events/*.json` → hourly compaction into `ledger.jsonl`) plus `users.json`. There is no database. See `docs/superpowers/specs/2026-08-29-splitwise-clone-design.md`. ## Space configuration Set these in the Space **Settings → Variables and secrets**: | Name | Kind | Value | |---|---|---| | `HF_TOKEN` | secret | fine-grained token with **write** access to the bucket below | | `HF_BUCKET` | variable | `buckets/assafvayner/splitwise-data` | | `HF_PREFIX` | variable | directory inside the bucket for this deployment, e.g. `prod` (integration tests use `test//`); empty = bucket root | | `SESSION_SECRET` | secret | `openssl rand -base64 32` — must be at least 32 characters | | `ORIGIN` | variable | the public URL of the Space, e.g. `https://assafvayner-splitwise.hf.space` (required for form submissions) | | `CURRENCY` | variable | 3-letter uppercase ISO 4217 code, default `USD` | | `COMPACTION_INTERVAL_MS` | variable | default `3600000` (1 hour) | `BODY_SIZE_LIMIT=8M`, `STORAGE=hf`, `PORT`, `HOST` and `NODE_ENV` are baked into the Dockerfile; there is no need to set them in the Space. `ADDRESS_HEADER=x-forwarded-for` and `XFF_DEPTH=1` are baked in too, so the per-IP login rate limiter sees the real client address through the Spaces proxy rather than the proxy's own. First boot creates the `admin` user with password `1234`; the first admin login forces a password change. Then create your friends' accounts on `/admin`. ## Local development ```bash cp .env.example .env # STORAGE=local writes to .data/ npm install npm run dev ``` `npm test` runs the unit tests only — it never touches the bucket. `npm run test:e2e` runs the Playwright smoke test against a production build. `npm run test:integration` (a separate `vitest.integration.config.ts`) runs the real-bucket tests under a throwaway `test//` prefix (needs `HF_TOKEN`/`HF_BUCKET` in `.env`; skipped otherwise). ## Deploy ```bash git remote add space https://huggingface.co/spaces/assafvayner/splitwise git push space main ```