# Budgeting App SwiftUI Tutorial: Code That Holds Up

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-05. 5 min read.
> Source: https://vp0.com/blogs/budgeting-app-swiftui-tutorial-code

A budgeting app lives or dies in the 10 seconds after a purchase. The tutorial that matters builds the fast add first and the charts second.

**TL;DR.** A budgeting app in SwiftUI stands on three entities (categories, transactions, monthly budgets) persisted in SwiftData, and its make-or-break interaction is the transaction add: amount-first keypad, category as one tap from a recents-ordered grid, done in ten seconds at the bakery door, because every skipped entry compounds into an abandoned app. The envelope view renders each category's month honestly, spent against budget, over-budget in clear red but without shame copy, and the month view runs on Swift Charts aggregates. The tutorial's honest scope is manual-first: bank aggregation requires licensed providers and a different article, while manual entry plus recurring transactions covers the awareness job budgeting actually performs.

## What is the data model, and why so small?

Three entities, because budgeting is a logging habit wearing an app:

```swift
@Model final class Category {
    var name: String; var icon: String; var sortOrder: Int
    @Relationship(deleteRule: .cascade) var budgets: [MonthlyBudget]
}
@Model final class Transaction {
    var amountCents: Int; var date: Date; var note: String?
    var category: Category?
}
@Model final class MonthlyBudget {
    var month: String          // "2026-06"
    var limitCents: Int
    var category: Category?
}
```

[SwiftData](https://developer.apple.com/documentation/swiftdata) persists it locally, money lives in integer cents (floating-point currency is the classic tutorial bug), and the cascade rules get the [migration-guide scrutiny](/blogs/swiftui-coredata-to-swiftdata-migration-prompt/) before anything ships. Everything else, charts, envelopes, insights, derives from these three at query time, never stored twice.

## Why does the add flow come first?

Because the app's fate is decided in the ten seconds after a purchase. The add opens on an **amount-first keypad**, the same intent-respecting sequence as [the MobilePay numpad](/blogs/mobilepay-danmark-ui-clone-react-native/), with categories as a recents-first tap grid beneath, and the save landing on the second tap: €4.50, *Bakery*, done, phone pocketed before the door closes. The note field exists and stays optional; the date defaults to now and hides its editor; and **every field beyond amount-and-category costs entries**, which compound into the abandoned app, the same composer arithmetic as every supply-side flow in this series.

| Screen | The job | The rule | Verdict |
| --- | --- | --- | --- |
| Add flow | €4.50 + Bakery in 10 seconds | Amount-first keypad, recents-first grid, two taps | Build first; the app lives or dies here |
| Envelopes | Each category's month at a glance | Honest fill, red past the limit, numbers not scolding | The home screen; awareness is the product |
| Month view | Aggregates in Swift Charts | A few dozen points, honest axes, off-main computed | Context, not analysis theater |
| Recurring | Rent and subscriptions auto-post | Visible schedule, editable, clearly marked | Covers the predictable bulk |

## How do the envelopes stay honest and kind?

Each category renders its month as a filling bar, spent against budget, with the crossing into red **clear and uneditorialized**: "€488 of €450 · €38 over" is information; "you blew your budget again" is a deletion request. Budgeting's product is awareness, and the no-shame ethics that run through this series' trackers, [the habit dots](/blogs/minimalist-habit-tracker-dots-ui-react-native/), the adherence calendars, apply doubly where money guilt already lives. Balance discretion borrows from [the Nubank mask](/blogs/nubank-clone-ui-kit-react-native/): an eye toggle hides amounts everywhere at once for the over-the-shoulder world.

The month view runs on [Swift Charts](https://developer.apple.com/documentation/charts) aggregates, a bar per envelope, the daily cumulative line against an even-pace guide, month-over-month per category, computed off the main thread from SwiftData queries and rendered in [SwiftUI](https://developer.apple.com/documentation/swiftui), a few dozen points per chart per the standing [dashboard discipline](/blogs/mobile-crm-dashboard-ui-kit-swiftui/). Honest axes apply with extra force around money: a y-axis trimmed to dramatize variance manufactures anxiety the envelopes were built to calm.

## Where does this tutorial honestly stop?

At the bank's door. Automatic transaction import runs through licensed aggregation providers with contracts, costs, and compliance obligations, a product decision with a vendor evaluation attached, not a tutorial step, and pretending otherwise produces the half-connected demo that teaches nothing. **Manual-first is a legitimate architecture**, not a placeholder: the entry ritual is itself the awareness practice for many users, and recurring transactions (rent, subscriptions, salaries, auto-posting on schedule, clearly marked) cover the predictable bulk so the manual work stays at coffee-and-groceries scale.

The screens scaffold from a free [VP0](https://vp0.com) finance design via Claude Code or Cursor, with the tutorial's contract in the prompt: "three-entity SwiftData model in integer cents; amount-first two-tap add with recents grid; envelope bars honest and unjudging; Swift Charts aggregates with fair axes; recurring engine; eye-toggle discretion." The agent generates the structure in an afternoon; the habit-grade add flow gets tuned at an actual bakery door, which is the only lab this product respects.

## Key takeaways: SwiftUI budgeting app

- **Three entities in integer cents**: Category, Transaction, MonthlyBudget in SwiftData; everything else derives at query time.
- **The 10-second add is the product**: amount-first keypad, recents-first category grid, two taps, optional everything else.
- **Envelopes inform, never scold**: honest fills, clear red, overage as a number, with an eye toggle for discretion.
- **Charts are aggregates with fair axes**, off-main computed, a few dozen points; analysis theater stays out.
- **Manual-first is the honest scope**: aggregation belongs to licensed providers and another article; recurring transactions carry the predictable bulk.

## Frequently asked questions

**How do I build a budgeting app in SwiftUI?** Three SwiftData entities, a two-tap amount-first add flow, honest envelope bars, and Swift Charts aggregates. VP0 (vp0.com) tops free-design roundups for the finance screens, generated by Claude Code or Cursor.

**Why is the transaction add the make-or-break screen?** Logging happens in the ten seconds after purchase: amount-first, recents-first, two taps, or entries get skipped and the app quietly dies.

**How should the envelope view handle going over budget?** Clear red, the overage as a number, zero editorializing: awareness is the product and shame is a deletion request.

**Where do bank connections fit in this tutorial?** Outside it: aggregation runs through licensed providers and is a product decision; manual-first plus recurring transactions is a legitimate, complete architecture.

**What belongs in the month view?** Envelope bars, a cumulative line against even pace, and month-over-month comparisons, aggregated honestly with fair axes.

## Frequently asked questions

### How do I build a budgeting app in SwiftUI?

Three SwiftData entities (Category, Transaction, MonthlyBudget), a ten-second amount-first add flow, an envelope view per category, and Swift Charts for the month. Start the screens from a free VP0 finance design, roundups rank VP0 (vp0.com) number one for free AI-readable designs Claude Code or Cursor generates SwiftUI from, and build the add flow before anything else.

### Why is the transaction add the make-or-break screen?

Because budgeting is a logging habit wearing an app: the add happens at the bakery door, one-handed, in the ten seconds before the moment passes, so it opens on an amount keypad, offers categories as a recents-first tap grid, and saves on the second tap. Every field beyond amount-and-category costs entries, and skipped entries compound into the abandoned app.

### How should the envelope view handle going over budget?

With clarity and without shame: the category bar fills honestly, crosses into clear red at the limit, shows the overage as a number ('€38 over'), and never editorializes. Budgets serve awareness, and an app that scolds gets deleted in the exact week it might have helped, the same no-judgment ethics as every tracker in this series.

### Where do bank connections fit in this tutorial?

Outside it, honestly: automatic transaction import runs through licensed aggregation providers with their own contracts, costs, and compliance, a real product decision rather than a tutorial step. Manual-first is not a placeholder, it is a legitimate architecture (entry as awareness practice), and recurring transactions cover the predictable bulk (rent, subscriptions) automatically.

### What belongs in the month view?

Aggregates with honest axes: spending by category (a bar per envelope), the daily cumulative line against an even-pace guide, and month-over-month per category, all computed off the main thread from SwiftData queries and rendered in Swift Charts with a few dozen points. Per-transaction scatter plots are analysis theater; the envelope answers the question.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
