Project Setup and File Structure
All six previous modules built toward this. You now have every tool BudgetBuddy needs. Module 07 puts the pieces together into a working app — starting from an empty folder.
What you are building
Section titled “What you are building”BudgetBuddy is a personal expense tracker that runs entirely in the browser:
- Add expenses with a description, amount, category, and date
- View all expenses in a sorted list
- Delete individual expenses
- Filter by category
- See a running total in the selected display currency
- Fetch live exchange rates from the ExchangeRate-API to convert totals into any supported currency
- Persist all expenses to localStorage so they survive page reloads
No server. No build tool. One HTML file, five JavaScript modules, and one stylesheet.
Create the project folder
Section titled “Create the project folder”budgetbuddy/ index.html favicon.svg style.css main.js expense.js storage.js api.js ui.jsCreate this folder structure now. All files start empty — you will fill them lesson by lesson.
The HTML shell
Section titled “The HTML shell”Write index.html first. This is the complete HTML structure BudgetBuddy uses — you will not need to change it:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>BudgetBuddy</title> <link rel="icon" type="image/svg+xml" href="favicon.svg" /> <link rel="stylesheet" href="style.css" /></head><body> <header> <h1>BudgetBuddy</h1> </header>
<main> <section class="add-expense"> <h2>Add Expense</h2> <form id="expense-form"> <div class="field"> <label for="description">Description</label> <input type="text" id="description" name="description" required /> </div> <div class="field"> <label for="amount">Amount</label> <input type="number" id="amount" name="amount" step="0.01" min="0.01" required /> </div> <div class="field"> <label for="category">Category</label> <select id="category" name="category"> <option value="Food">Food</option> <option value="Transport">Transport</option> <option value="Health">Health</option> <option value="Entertainment">Entertainment</option> <option value="Other">Other</option> </select> </div> <div class="field"> <label for="date">Date</label> <input type="date" id="date" name="date" /> </div> <button type="submit">Add Expense</button> </form> </section>
<section class="expense-summary"> <div class="totals"> <span id="total-label">Total:</span> <span id="total-amount">$0.00</span> </div> <div class="currency-controls"> <label for="currency-select">Display in:</label> <select id="currency-select"> <option value="USD">USD</option> <option value="EUR">EUR</option> <option value="GBP">GBP</option> <option value="CAD">CAD</option> <option value="JPY">JPY</option> <option value="AUD">AUD</option> </select> </div> </section>
<section class="expense-list"> <h2>Expenses</h2> <div class="filter-controls"> <label for="category-filter">Filter by:</label> <select id="category-filter"> <option value="All">All categories</option> <option value="Food">Food</option> <option value="Transport">Transport</option> <option value="Health">Health</option> <option value="Entertainment">Entertainment</option> <option value="Other">Other</option> </select> </div> <ul id="expense-list"></ul> <p id="empty-state" class="empty-state">No expenses yet. Add one above.</p> </section> </main>
<script type="module" src="main.js"></script></body></html>Confirm the entry point loads
Section titled “Confirm the entry point loads”Before writing any app logic, confirm the module system works. Add one line to main.js:
console.log('BudgetBuddy loading...');Start a local server from the budgetbuddy/ folder:
npx serve .Open the URL in Chrome, open DevTools → Console. You should see BudgetBuddy loading....
If you see a CORS error or module load failure, the most common cause is opening the file directly from the filesystem (file://) instead of through a server. Confirm the URL starts with http://localhost.
Add the import skeleton
Section titled “Add the import skeleton”Now stub out all five modules and the imports:
import Expense from './expense.js';import { saveExpenses, loadExpenses } from './storage.js';import { fetchRates, convertAmount } from './api.js';import { renderExpenses, updateTotal } from './ui.js';
console.log('BudgetBuddy loading...');Each imported file should exist (even if empty) — otherwise the browser will throw a module not found error. Create each file with a single export so the imports resolve:
// expense.js — placeholderexport default class Expense {}
// storage.js — placeholderexport function saveExpenses() {}export function loadExpenses() { return []; }
// api.js — placeholderexport async function fetchRates() { return { USD: 1 }; }export function convertAmount(a) { return a; }
// ui.js — placeholderexport function renderExpenses() {}export function updateTotal() {}Reload the page. No errors — all imports resolve. Now you have a clean starting point.
Exercise
Section titled “Exercise”- Create the
budgetbuddy/folder with all eight files (includingfavicon.svg). - Paste the full HTML into
index.html. - Create
favicon.svg— a simple SVG with a colored background and a$symbol. - Add stub exports to each module file.
- Confirm the page loads with no console errors.
- Open DevTools → Network tab and confirm each
.jsfile is loaded as a module (you will see them all listed).
- Scaffold first — create the file structure and confirm the entry point loads before writing app logic.
- The HTML structure is complete and will not change during the build.
- Stub exports prevent module-not-found errors while files are still empty.
type="module"in the script tag enables ES modules and defers execution until the HTML is parsed.