Chapter 1 of ?
js 9 min read

JavaScript Mastery — Chapter 38: JS Interactive Capstone Projects

Module 10: Projects, Practice & Certification • Chapter 38

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.

1. DOM Event Listeners click, submit, input, drag Dispatches 2. Central State Store Proxy or Immutable State Re-renders 3. DOM Renderer Batch Fragment Update 4. Storage Sync (localStorage) Automatic draft rehydration

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.

0 tasks remaining

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
Hands-on Challenge

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.

1. In a production single-page application, why is Unidirectional Data Flow preferred over directly mutating DOM nodes from scattered event listeners?
It encrypts DOM nodes
State is kept in a single source of truth, making UI synchronization predictable and bug-free
It bypasses CSS parsing
Browsers enforce it via the HTML5 specification
2. How should you handle a Geolocation API request in modern async/await code?
Geolocation is already an async function that returns a Promise
Wrap navigator.geolocation.getCurrentPosition() inside new Promise((resolve, reject) => ...)
Use JSON.stringify()
Call window.location.reload()
3. What is the recommended strategy when persisting dynamic objects into localStorage?
Store them directly as raw objects
Serialize via JSON.stringify() on write, and parse via JSON.parse() inside a try/catch block on read
Pass them through an ArrayBuffer
Convert to Base64
4. Why is Event Delegation particularly advantageous in a dynamic Task List or Shopping Cart?
It automatically sorts tasks alphabetically
Dynamically added or deleted items do not require manual listener attachment or cleanup
It runs on a separate GPU thread
It prevents XSS attacks
5. Which container prevents layout reflows when rendering dozens of list items into the DOM?
DocumentFragment
HTMLCanvasElement
Web Worker
ArrayBuffer
Done with this chapter?
Mark it complete to track your progress and unlock your certificate.
Next Up
—

Learner Reviews

Write a Review
Share your experience to help other learners.
Your Rating *
★ ★ ★ ★ ★