JS Interactive Capstone Projects
Synthesize every concept learned across the series into four real-world production web applications: an Offline-Ready Task Manager, a Dynamic Quiz Engine, a Weather Dashboard, and an E-Commerce Shopping Cart.
Modern Vanilla JS Web App Architecture
Professional vanilla web apps adopt clean architectural patterns: unidirectional data flow, a centralized state store, isolated UI renderers, and abstracted API clients.
Project 1: The Offline-Ready Task Manager
This project unites localStorage, DOM manipulation with DocumentFragment, and Event Delegation into a high-speed CRUD productivity app.
State Store Pattern in Action
class TaskStore {
constructor(storageKey = 'tasks_v1') {
this.key = storageKey;
this.tasks = JSON.parse(localStorage.getItem(this.key) || '[]');
}
add(title) {
const task = { id: Date.now(), title, completed: false };
this.tasks.push(task);
this.persist();
return task;
}
toggle(id) {
const task = this.tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
this.persist();
}
}
remove(id) {
this.tasks = this.tasks.filter(t => t.id !== id);
this.persist();
}
persist() {
localStorage.setItem(this.key, JSON.stringify(this.tasks));
}
}
Run in Playground
Interactive Lab: Playable Task Manager Sandbox
Live App
Test this live mini-app right here! Add tasks, click items to toggle completion, or delete them. Notice how state automatically survives page refreshes via localStorage.
Project 2: Live Weather & Geolocation Dashboard
Combine the native navigator.geolocation browser API with asynchronous fetch() to retrieve real-time meteorological forecasts from the open-source Open-Meteo REST API without requiring any private API keys.
Geolocation + Fetch Integration
async function loadLocalWeather() {
if (!navigator.geolocation) {
throw new Error('Geolocation is not supported by your browser');
}
// 1. Promisify Geolocation API
const pos = await new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject, { timeout: 10000 });
});
const { latitude, longitude } = pos.coords;
// 2. Fetch live forecast with AbortSignal timeout
const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t_weather=true`;
const res = await fetch(url, { signal: AbortSignal.timeout(6000) });
if (!res.ok) throw new Error('Weather API service error');
const data = await res.json();
console.log(`Current Temp: ${data.current_weather.temperature}°C`);
return data.current_weather;
}
Test in Playground
Build a Reactive E-Commerce Cart with Coupons & Tax
Implement a Cart class with methods to addItem(id, price, qty), removeItem(id), applyCoupon('SAVE10'), and calculate the grand total including 8% sales tax.
class Cart {
constructor() {
this.items = new Map();
this.discountPercent = 0;
}
addItem(id, price, qty = 1) {
if (this.items.has(id)) {
this.items.get(id).qty += qty;
} else {
this.items.set(id, { id, price, qty });
}
}
removeItem(id) {
this.items.delete(id);
}
applyCoupon(code) {
if (code === 'SAVE10') this.discountPercent = 10;
else if (code === 'SAVE20') this.discountPercent = 20;
else throw new Error('Invalid coupon code');
}
getTotals() {
let subtotal = 0;
for (const item of this.items.values()) {
subtotal += item.price * item.qty;
}
const discount = (subtotal * this.discountPercent) / 100;
const taxableSubtotal = subtotal - discount;
const tax = taxableSubtotal * 0.08; // 8% Tax
const total = taxableSubtotal + tax;
return { subtotal, discount, tax, total };
}
}
Chapter 38 Knowledge Check
Validate your understanding of web application architecture, state synchronization, and DOM component patterns.
localStorage?