Files
Lucas Winther 5c6cee0f0b
Continuous Integration / lint-and-test (push) Successful in 18s
Continuous Integration / docker-build-and-push (push) Successful in 1m11s
docs: refresh current behavior and outstanding work
2026-10-03 16:50:58 +02:00

7.4 KiB
Executable File

Product

Platform

web

Users

One person: the owner of the money, managing their own budget. They are leaving a spreadsheet, so they already know their own categories, already think in months, and value speed of entry over guidance. They tolerate rough edges in exchange for the tool doing exactly what they mean.

Confirmed permanently single-user. One person, one browser, one dataset. There are no accounts, no second role, and no shared or household use planned.

Product Purpose

Envelope budgeting for a single person, replacing a spreadsheet.

Money is divided each month into named envelopes ("posts"). Unspent allocation carries into the next month; overspending carries forward as debt. The app answers two questions at a glance: how much is left in this envelope, and did I overspend.

Success is that the owner stops maintaining a spreadsheet, and that a month's purchases can be entered fast enough not to be a chore.

Positioning

Two things a general budgeting app does not do:

  • Envelope rollover is the whole model, not a feature. Every figure derives from one left-fold across months, so a balance is always the honest consequence of every prior month.
  • The data never leaves the browser and never needs an account. IndexedDB is the only store. That is a deliberate product position, not a missing backend.

Operating Context

The owner records spending after the fact, often in batches — a grocery trip is twenty lines entered in one sitting, not twenty separate visits. Income arrives monthly and varies, so it is entered per month rather than assumed.

Purchases frequently belong to more than one envelope (food bought at a social event), and larger purchases are spread across several months deliberately rather than absorbed by one.

Money is handled in DKK, USD and EUR, with DKK as the base.

Capabilities and Constraints

Confirmed and in place:

  • Nested budget folders organize posts, bills, and optionally individual purchases. A single-post bill starts beneath that post but can be moved independently. Folder Bills due reports scheduled bill prices for the selected month; posts alone hold envelope balances. A purchase's separate row never changes which posts its splits charge.
  • Posts (envelopes) with monthly allocation, created and archived by the owner. Posts are archived, never deleted, because purchases reference them.
  • A post with no applicable allocation rule still records spending and shows its balance, but is not labelled overspent. An explicit zero allocation is a budget rule and can be overspent.
  • Allocation is either a fixed amount or a percentage of that month's income.
  • A purchase can be split across several posts, by percentage or by fixed amounts, and can also be spread across future months as a payment plan. The two compose.
  • A purchase may have no post. It remains visible in its month and counts in Spent, while leaving envelope balances unchanged.
  • Per-month income, entered directly, varying month to month.
  • The month header shows actual available: that month's entered income minus actual spending, including unassigned purchases and refunds. Monthly breakdown can be hidden and Expected collapsed; these choices persist in this browser.
  • Multi-currency against a user-maintained exchange-rate table. New budgets start with DKK, USD, EUR, GBP, JPY, AUD, CAD and MXN; existing currency tables stay under the owner's control. An optional on-demand fetch fails soft and is never required. Decimal places are one setting across all currencies.
  • JSON export/import and ODS (spreadsheet) export, both generated in the browser. On each app start, a separate browser-stored session backup is made before editing is available; recent daily, weekly and monthly checkpoints can be downloaded or restored from Settings. These checkpoints share the browser origin with the live data, so JSON export is still needed for protection against losing browser storage.
  • Offline-capable installable PWA. Currently deploys as one static artifact to both GitHub Pages (under a subpath) and a self-hosted Docker image.
  • Recurring costs — a bill that repeats every N months, every N days, or every N weeks on a weekday, optionally split across posts like any purchase. A cost may have no post: it remains expected without moving an envelope's projected balance, and confirming it records unassigned spending. A cost is anchored one of two ways: calendar holds a fixed grid of due dates, so paying two months at once still leaves nothing due until the one after; a cost anchored to its last charge has no grid at all and can be charged any number of times in one cycle, its next due date always one cycle after whichever charge was most recent — a phone plan that recharges early when its data runs out is the case this exists for. Each due date on the calendar model is a projected occurrence the owner confirms into a real purchase; a recurring cost can be created from a purchase while it is being entered. Choosing an existing bill in Add purchase is enabled explicitly in Settings; existing purchase associations remain editable. The month view shows what is still expected alongside a second, projected balance per post, so a known bill is visible before it is paid without touching the reconciled figure a bank statement is checked against.

Terminology: an envelope is called a post. A finance plan is a purchase spread across months. An override is a one-month exception to a post's allocation. A recurring cost is a bill expected to repeat; each due date it projects is an occurrence; confirming an occurrence turns it into a real purchase.

Undecided: nothing outstanding at the product level.

Brand Commitments

The product is called Budget 2.0. No logo, wordmark, or brand assets exist, and none have been commissioned.

Evidence on Hand

None, and none may be invented. This is a personal tool: there are no customers, testimonials, case studies, usage statistics, press, pricing, or third-party integrations. Any future surface must not manufacture them.

The only real content is the owner's own budget data, which never leaves their browser and is therefore never available as example material. Illustrative data must be visibly synthetic.

Product Principles

  1. Over-budget is always allowed. The app reports the truth and never blocks, clamps, or hides overspending. A negative balance is a normal value.
  2. Changing an allocation must never destroy history. Adjusting what a post gets going forward leaves what it got before intact and still visible.
  3. Splitting a purchase across posts must stay easy. It is a routine act, not an advanced feature, and must not be buried behind extra steps.
  4. The data stays portable and in the owner's hands. Export is always available and always complete; nothing traps a budget inside the app.
  5. Entry speed is a feature. Recording a month of spending is the most repeated act in the product, and friction there is the reason spreadsheets get abandoned.

Accessibility & Inclusion

No condition-specific requirement was established by the owner. The existing implementation holds itself to WCAG AA contrast, visible keyboard focus, and respecting reduced-motion preferences; keyboard-first entry is a stated goal of the fast-entry flow rather than only an accessibility accommodation.