- TypeScript 53.8%
- Python 37.3%
- HTML 5.3%
- SCSS 2.8%
- Dockerfile 0.3%
- Other 0.5%
Replace spec-style README with a product-oriented one focused on: - The 'why weekly?' hook and the four rules - What the app can (and cannot) do — explicit non-goals section - Tech stack as a brief, low-prominence block - Concrete quick-start and deployment paths - Roadmap with concrete next steps Leaves room for LICENSE, badges and screenshots before first public release. No code change. |
||
|---|---|---|
| backend | ||
| docs | ||
| frontend | ||
| .env.prod.example | ||
| .gitignore | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| README.md | ||
| SPECS.md | ||
Pecunia
Every Monday, every euro has a job.
Pecunia is a small, opinionated budget app for people who'd rather know exactly what they can spend this week than agonize over a monthly spreadsheet. It's built around a single idea: money has a job, and every euro should know its job by Monday morning.
Single-user · Self-hosted · No bank sync · No telemetry · French UI
Why weekly?
Most budgeting apps ask you to think in months. But you don't live in months — you live in paychecks, weekends, and the gap until the next bill. Pecunia splits your life into Monday → Sunday weeks because:
- It matches the rhythm of weekly grocery runs, weekend leisure, and small recurring charges.
- The feedback loop is ~4× faster: if you blew last week's budget, you know on Sunday, not on the 30th.
- It pairs naturally with bi-weekly paychecks: every other Monday is a "budget refresh" instead of one giant "month reset".
The price of this view is a small one: Pecunia treats a month as 4 weeks (see What Pecunia is not). For most people, that approximation is fine. Pecunia is for the people who think it is.
The four rules
Pecunia is opinionated. The whole app encodes four rules — they are not optional.
- Every euro has a job. When a new week starts, your income has been divided into: fixed charges, weekly savings, sinking funds (amortizables), and a spendable remainder. Nothing is unallocated.
- Big purchases are planned, not panicked. A sinking fund (Pecunia calls it an amortizable) lets you pre-allocate a weekly amount toward a known future expense — a new laptop, a holiday, a replacement fridge.
- Closed weeks are closed. A week that has been settled cannot be retroactively edited. The history is the history. This is uncomfortable on purpose: it forces you to confront the truth of your week.
- Deficits are paid, not hidden. If you overspend, Pecunia first dips into your planned weekly savings to absorb the gap, then carries the remainder into next week. You can't spend what you've already saved — unless you really mean to (a "savings" expense does exactly that and requires you to have the money).
What you can do with it
- Dashboard — this week's status at a glance: budget, spent, remaining, savings counter, today's expenses, alerts (overspent / carry-over / amortizable completed).
- Quick expense entry — amount, description, category, source (budget or savings). Editable inline. Optimistic UI.
- Configuration — manage your fixed charges, incomes, weekly savings goal, with a live preview of what next week's budget will look like before you save.
- Sinking funds (amortizables) — create, pause, resume, delete, watch progress. Each is a card with a progress bar and a weeks counter; settlement advances them automatically.
- History — browse every past week, expand to see its expenses, color-coded by whether you saved or overspent.
- Statistics — KPIs (savings, budget respect rate, average spending) and four charts (budget evolution, savings cumulative, category breakdown, overspending incidents) with a period filter (week → year).
- Dark mode + responsive shell — desktop sidebar, mobile bottom nav, dark/light theme with system-preference detection and persistence.
- JWT auth — register, login, refresh, profile. No third party, no OAuth, no tracking pixels.
How it actually runs
Two containers, one database, one cron, plus an nginx that serves the SPA and proxies the API. That's it.
[ Browser ]
│
▼
[ Nginx :80 ] ── /api/* ──► [ Django · gunicorn :8000 ] ──► [ Postgres :5432 ]
│ ▲
└──── Angular SPA (static) │
│
[ Cron · 00:01 daily ] ──────────────────┘
close_expired_weeks
- Frontend — Angular 19, standalone components, Signals, OnPush,
lazy routes, Angular Material,
@swimlane/ngx-charts. - Backend — Django 5, DRF,
simplejwt,drf-spectacular,django-environ,argon2-cffi, gunicorn. Money isDecimaleverywhere withROUND_HALF_UPquantization. - Database — PostgreSQL 16.
- Tests —
pytest-djangoon the backend (services 100% covered, views ≥80%, all edge cases from the spec tested), Karma/Jasmine on the frontend (~330 tests across 32 spec files). Strict TDD: no commit ships without a test. - Methodology —
SPECS.mdis the single source of truth. Every change references a section of the spec.
Quick start
Production (Docker)
cp .env.prod.example .env.prod
# edit .env.prod (DJANGO_SECRET_KEY, POSTGRES_PASSWORD, allowed hosts)
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d
Nginx listens on :80. Put Caddy or Traefik in front for TLS.
Development (Docker)
docker compose up --build
- Frontend (hot-reload): http://localhost:4200
- Backend API: http://localhost:8000/api/
- Swagger docs: http://localhost:8000/api/docs/
- Database:
localhost:5433(user/db/pass =pecunia)
Development (without Docker)
See backend/README.md and frontend/README.md for venv/npm setup.
What Pecunia is not
Read this before opening an issue — it sets expectations.
- Not multi-user / household. One account = one person. Couples need to run two instances or merge externally. Intentional for v1.
- Not a bank aggregator. No Plaid, no Powens, no automatic transaction import. You enter expenses yourself. This is a feature for the privacy-conscious, not a missing feature.
- Not an investment tracker. No stocks, crypto, real estate, pensions. Out of scope.
- Not a credit-card / debt manager. No APR, no minimum payment calculations, no payoff strategies.
- Not multi-currency. One user = one currency, hardcoded to € and the French locale in v1.
- Not infinitely granular. A month is 4 weeks. A week is Monday → Sunday. Categories are fixed. These are simplifying choices, not bugs.
- Not 100% finished. The core budgeting model is feature-complete per the spec. Phase 5 (dark mode, responsive shell, prod compose) is in progress. Some accessibility and polish work remains.
Roadmap
Roughly ordered by expected payoff. Open an issue if one of these matters to you.
- Variable income — rolling 3-month average for freelancers whose paycheck size varies
- 3–6 month forecast — Pecunia has all the data; show it forward with a confidence band
- Recurring expenses — log Netflix, EDF, etc. once, repeat forever
- i18n — English UI in addition to French
- PWA install — offline cache, installable on a phone home screen
- CSV export — personal archiving and backup peace of mind
- Household mode — shared pool with per-user expense attribution
Contributing
The project is built in strict TDD: write a failing test, then the
implementation, then refactor. See
docs/orchestration-design.md for
the phase plan, sub-agent boundaries, and the "no commit without a
test" rule.
PRs welcome. Please open an issue first if your change touches the
spec — modifying SPECS.md requires explicit maintainer approval.
License
TBD — most likely MIT. A LICENSE file will land before the first
public release.
Pecunia is Latin for "money". The app is small, but the topic is not.