
Cushion
2026 · iOS app · SwiftIn build
Envelope budgeting with no bank login, ever — because connecting accounts means a server, an account, and a third party holding someone's banking credentials.
- Swift 6
- SwiftUI
- SwiftData
- CloudKit
The problem
Every competitor solves budgeting by connecting your bank, which forces a backend, an account to attach it to, and an aggregator holding your credentials on their behalf. It also costs the Data Not Collected privacy label. The alternative — manual entry — is only viable if entering a transaction takes three seconds rather than thirty.
What I built
- No per-month budget rows at all. An envelope's balance is derived from the ledger every time, which means carryover is not a feature — it is the absence of a reset. Most envelope apps get this backwards and then have to build carryover on top.
- One invariant holds after every single mutation: total cash equals unassigned plus the sum of every envelope. It is asserted after each operation in the test suite, so an arithmetic bug fails a test rather than quietly losing someone's money.
- Money is integer minor units throughout. Never a Double, never a Float — floating-point money is a rounding error waiting to become a support ticket.
- Statement import reads a CSV or OFX file the bank already offers, parsed on the device with no network request and no credentials anywhere.
- Core logic lives in a Swift package with no UI, no SwiftData and no platform imports, so the 46 tests run from the command line in milliseconds without a simulator.
What I took from it
Gating carryover behind the paid tier was in the first draft of the plan and was a real error. Leftover money staying in the envelope *is* the envelope method — charging for it ships a broken product wearing the method's name. Unlimited envelopes and full history are free for the same reason: hiding someone's own spending record behind a subscription reads as ransom.


