You assign money to spending categories before you spend it — envelope budgeting. Self-hosted, single SQLite file, no external services: you own your data.
Budgets are shareable: invite a partner, flatmates, or a business into the same budget, each managing their own login.
The name is german — "genug" means "enough".
Assign each month's money to categories — targets fill up, overspending shows in red.
Record transactions per account; edit category, date, notes, and amount inline; toggle each between pending and validated.
- Shared budgets — Invite others into a budget; each manages their own login. Admin provisions users.
- Budget Plans — Separate budgets for personal, business, etc. Each with its own accounts, categories, and transactions.
- Accounts — Map your bank accounts and credit cards. Track validated vs. pending balances. Transfer between accounts.
- Categories — Organize spending areas. Archive unused ones. Set target balances.
- Transactions — Inline editing of category, date, notes, amount. Toggle validated. Filter by category, notes, date, amount.
- Monthly Budget Assignment — Assign money to categories per month. Move money between categories or cover overspending.
- i18n — German and English, switchable.
- Currencies — EUR, USD, GBP, CAD, AUD, JPY.
Runs as a single Node.js container against one SQLite file — no external database, cache, or services.
Prebuilt images are published to ghcr.io/lj-n/genug. A minimal Docker
Compose stack:
services:
genug:
image: ghcr.io/lj-n/genug:latest
restart: unless-stopped
ports:
- '3000:3000'
volumes:
- ./data:/app/data:rw
environment:
DATABASE_URL: '/app/data/genug.db'
ORIGIN: 'https://your.domain'The first login on a fresh instance creates the admin user.
For the full picture — image tags and rollback, reverse proxy and ORIGIN,
all environment variables, running without Docker, backups, upgrades, and
password recovery — see docs/self-hosting.md.
I wanted an envelope budgeting app for personal use that I could self-host and keep my own data in: one SQLite file, no external services.
Requires Node.js 22+ and npm 11.17+ (npm install -g npm@11): installs
enforce a 3-day release-age cooldown against npm supply-chain attacks, which
older npm versions would silently ignore.
npm install
npm run devA committed .env supplies a DATABASE_URL=local.db default, so no prefix is
needed. Override it in .env.local (gitignored) if you want a different path.
npm run test:unit # Vitest
npm run test:e2e # Playwrightnpm run lint
npm run checknpm run release # compute the next CalVer, stamp CHANGELOG.md, commit + tag
git push --follow-tagsVersions are CalVer (YYYY.0M.MICRO) and the changelog is hand-curated under
## [Unreleased].
See CONTRIBUTING.
genug is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).
Copyright (C) 2026 Linus Johannsen