Skip to content

marcbeep/dime

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

89 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dime

Dime is a strict, minimal envelope budgeting app. Every unit gets assigned; envelopes and the Pot never go negative.


Quick Start

cd server && npm install && cd ..
docker-compose up
# app: http://localhost:3000

Deploy (Railway): push to GitHub → create Railway project → deploy from GitHub → add PostgreSQL (sets DATABASE_URL). PORT defaults to 3000.


Core Model

Envelopes

  • “Categories” are now envelopes (e.g., Rent, Groceries, Fun, Emergency).
  • Envelopes cannot go below 0.

The Pot (special envelope)

  • Pot holds all unassigned money from spendable assets.
  • No direct spending from Pot; assign to envelopes first.
  • Pot cannot go below 0.
  • Formula: Pot = sum(spendable asset balances) − sum(envelope allocations).

Accounts

  • Class: asset or debt.
  • Spendable: true/false (e.g., Checking = asset+spendable; Crypto = asset+non-spendable; Credit Card = debt+spendable; Mortgage = debt+non-spendable).
  • Only spendable assets contribute to the Pot.
  • Balances reflect reality: debts are often negative (e.g., credit cards). No additional non-negativity rule for accounts is enforced.

Rules (enforced)

  1. No overspending: envelope ≥ 0 at all times.
  2. No over-assigning: Pot ≥ 0 at all times.
  3. No Pot spending: spend from an envelope only.
  4. No over-moving: envelope → envelope transfers ≤ source balance.
  5. Moves are paired: account move creates equal & opposite entries.
  6. Debt payments reduce spendable assets: ensure Pot covers them (de-allocate first if needed).

Money Flow

Income → Spendable Asset → Pot → Envelopes → Spending

  • Debit card / checking spend: asset ↓, envelope ↓.
  • Credit card spend: debt more negative, envelope ↓, Pot unchanged.
  • Paying the card: spendable asset ↓; Pot must cover.

Credit card example (correct): Start: Card −100, Groceries 10 → spend 10 on Groceries via card → Groceries 0, Card −110, Pot unchanged.


Transactions & Transfers

  • Transactions

    • in (>0): income/deposit
    • out (<0): expense/withdrawal
    • move (±): transfer between accounts (paired, linked)
    • Spending must reference a non-Pot envelope with sufficient funds.
  • Envelope Transfers (budget only): reallocate between envelopes; Pot unchanged.


Data (minimal)

Account

{
  "id": "uuid",
  "user_id": "uuid",
  "name": "str",
  "class": "asset|debt",
  "spendable": true,
  "balance": 2450000,
  "created_at": "ISO",
  "updated_at": "ISO"
}

Envelope

{ "id": "uuid", "user_id": "uuid", "name": "str", "created_at": "ISO" }

Transaction

{
  "id": "uuid",
  "user_id": "uuid",
  "account_id": "uuid",
  "type": "in|out|move",
  "amount": -45230,
  "date": "YYYY-MM-DD",
  "payee_id": null,
  "envelope_id": "uuid|null",
  "linked_transaction_id": null,
  "created_at": "ISO",
  "updated_at": "ISO"
}

Envelope Transfer

{
  "id": "uuid",
  "user_id": "uuid",
  "from_envelope_id": "uuid",
  "to_envelope_id": "uuid",
  "amount": 100000,
  "date": "YYYY-MM-DD",
  "reason": null,
  "created_at": "ISO"
}

Currency & Validation

  • Amounts are milliunits (1/1000): $123.45 → 123450.
  • IDs are UUIDs.
  • Type ↔ sign: in > 0, out < 0, move paired.
  • Envelope ≥ 0, Pot ≥ 0.
  • Envelope transfers ≤ source.
  • Account balances = sum of their transactions; deleting one side of a move deletes both.

API (outline)

Collections: /api/accounts, /api/envelopes, /api/transactions, /api/envelope-transfers, /api/payees Items: /api/{resource}/{id}

Success:

{ "success": true, "data": { ... } }

Error:

{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "..." } }

About

An envelope budgeting app, alternative to YNAB.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published