Skip to content

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.

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.

budgetbuddy/
index.html
favicon.svg
style.css
main.js
expense.js
storage.js
api.js
ui.js

Create this folder structure now. All files start empty — you will fill them lesson by lesson.

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>

Before writing any app logic, confirm the module system works. Add one line to main.js:

main.js
console.log('BudgetBuddy loading...');

Start a local server from the budgetbuddy/ folder:

Terminal window
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.

Now stub out all five modules and the imports:

main.js
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 — placeholder
export default class Expense {}
// storage.js — placeholder
export function saveExpenses() {}
export function loadExpenses() { return []; }
// api.js — placeholder
export async function fetchRates() { return { USD: 1 }; }
export function convertAmount(a) { return a; }
// ui.js — placeholder
export function renderExpenses() {}
export function updateTotal() {}

Reload the page. No errors — all imports resolve. Now you have a clean starting point.

  1. Create the budgetbuddy/ folder with all eight files (including favicon.svg).
  2. Paste the full HTML into index.html.
  3. Create favicon.svg — a simple SVG with a colored background and a $ symbol.
  4. Add stub exports to each module file.
  5. Confirm the page loads with no console errors.
  6. Open DevTools → Network tab and confirm each .js file 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.