Skip to content

Project Setup and Architecture

Module 07 is a guided project build. You will apply every concept from the previous six modules to build and deploy ZeroBudget — a complete zero-based budgeting app. Start here before writing a single component.

ZeroBudget implements the every-dollar budgeting method: every dollar of income is assigned to a spending category before the month begins. The app tracks:

  • Income sources — multiple sources with names and amounts
  • Budget categories — 8 preset categories with user-editable spending limits
  • Left to assign — real-time difference between total income and total budgeted
  • Transactions — individual purchases logged to a category
  • Per-category stats — spent, remaining, and a color-coded progress bar
  • Month navigation — independent data per month with copy-forward and reset

You can explore the finished app and read the source before you build it.

Terminal window
npm create vite@latest zero-budget -- --template react
cd zero-budget
npm install

Create the folder structure:

src/
├── components/
│ ├── MonthNav/
│ ├── IncomeSection/
│ ├── LeftToAssign/
│ ├── CategoryCard/
│ ├── TransactionForm/
│ └── TransactionList/
├── context/
│ └── BudgetContext.jsx
├── data/
│ └── defaults.js
├── hooks/
│ ├── useBudget.js
│ └── useLocalStorage.js
├── App.css
├── App.jsx
├── index.css
└── main.jsx

Three arrays drive the entire app:

// Income source
{ id: 'uuid', name: 'Paycheck', amount: 3500 }
// Category
{ id: 'housing', name: 'Housing', budgeted: 1200 }
// Transaction
{ id: 'uuid', categoryId: 'housing', amount: 950, description: 'Rent', date: '2026-06-01' }

All three live together in a month object stored in localStorage:

{
incomeSources: [...],
categories: [...],
transactions: [...],
}

The localStorage key is zb-YYYY-MM — one entry per month.

These are computed from the arrays, not stored separately:

ValueFormula
totalIncomeincomeSources.reduce((sum, s) => sum + s.amount, 0)
totalBudgetedcategories.reduce((sum, c) => sum + c.budgeted, 0)
leftToAssigntotalIncome - totalBudgeted
spentByCategorytransactions.reduce(...) keyed by categoryId
spent (per card)spentByCategory[category.id] || 0
remaining (per card)category.budgeted - spent
pct (per card)(spent / category.budgeted) * 100
  • useBudget owns all state and computes all derived values.
  • BudgetContext broadcasts the hook’s return value to all components.
  • Components read from context — no prop drilling through App.
  • App is a layout component with local state only for the new-category form input.
  1. Scaffold the project with the command above.
  2. Create all the directories listed in the folder structure.
  3. Create src/data/defaults.js with the 8 default categories: Housing, Transportation, Food, Utilities, Clothing, Personal, Savings, Giving. Each should have a unique id string, a name, and budgeted: 0.
  4. Create an empty useLocalStorage.js in src/hooks/ and write the hook from Module 04, Lesson 03.
  • ZeroBudget stores income sources, categories, and transactions together in a month-keyed localStorage object.
  • All totals and per-category stats are derived from those three arrays — not stored separately.
  • The architecture: useBudget owns data → BudgetContext broadcasts it → components read it directly.
  • Build structure first, features second. Create every folder and every placeholder file before writing logic.