Free lesson · JavaScript Basic to Advance
The Project: What We're Building
A Module That Builds One Thing
Modules 1 through 14 taught JavaScript in pieces. Module 1 covered history. Module 2 covered types. Each module focused on one area and went deep. By the time you finished Module 14, you had a comprehensive technical foundation plus an interview-preparation plan.
What you don't yet have is the experience of those pieces working together in one real project. That's what Module 15 does. We build one application from scratch, using concepts from across the course, and watch how they interact.
// What we're building: an async data dashboard
//
// - Fetches paginated data from an API
// - Caches results to avoid repeated requests
// - Renders an interactive UI with filtering and sorting
// - Handles errors and loading states gracefully
// - Cancels in-flight requests when the user navigates away
//
// In doing this, we'll touch:
// - Closures (Module 6) for the cache
// - Classes and prototypes (Modules 7-8) for the data layer
// - Promises and async/await (Module 9) for the fetch logic
// - Destructuring and spread (Module 10) throughout
// - ES Modules (Module 11) for file organization
// - DOM and events (Module 12) for the UI
// - Performance patterns (Module 13) where they matter
This Topic explains the project, its scope, and why we chose it. The next four Topics build it. The final Topic uses what we built as the concrete reference for interview questions across the entire course.
Olena here. I'm leading Module 15 because the capstone needs a consistent voice and my modules across the course (1-5, 10-12) have given me the broadest narrative through the material. Other founders join in the final Topic when their domain comes up — Nikhil on closures and runtime, Brandon on OO patterns, Emeka on async.
Why a Capstone Matters
In thirteen years of interviewing engineers across two companies (Zalando and Microsoft), I've watched a specific pattern: candidates can answer textbook questions about concepts but struggle to use those concepts together. They know what a Promise is. They know what event delegation is. They know what a closure is. But when the interviewer says "build me a small thing that does X, Y, and Z," they freeze — because all the practice they've done has been on isolated questions.
The fix is connected practice. Building one project that uses many concepts is fundamentally different from solving fifty problems that each use one concept. The connections are where senior engineering lives.
This module gives you one such project. Walk through it carefully. Then build your own variation, with different requirements, to make the patterns yours.
The Project: An Async Data Dashboard
We're building a paginated data dashboard. Imagine a UI showing a list of products, users, articles — anything paginated and large enough that you can't load everything at once.
Functional requirements:
- Fetch data from a paginated API endpoint
- Display results in a scrollable list with filtering and sorting
- Show loading states while fetching
- Show error states when requests fail, with a retry option
- Cancel pending requests if the user navigates away or changes filters
- Cache results so the same query doesn't refetch unnecessarily
- Support keyboard navigation (arrow keys, enter)
Non-functional requirements:
- Code is modular, with clear separation between data, UI, and state
- Errors are handled at the appropriate layer, not swallowed
- Performance is good — no unnecessary re-renders, no memory leaks
- Code is readable and would pass a senior code review
This is approximately the complexity of a "build me this small feature" prompt in a senior FAANG frontend interview. Real interviews often constrain the scope further ("just the data layer," "just the UI") because 45 minutes isn't enough for the whole thing. But the full version is a useful exercise because all the layers exist in real applications.
graph TD
A[User clicks/types] --> B[Event handler<br/>delegation]
B --> C[State change<br/>filter, sort, etc.]
C --> D[Data layer<br/>checks cache, fetches]
D --> E[Promise resolves<br/>or rejects]
E --> F[State updated]
F --> G[UI re-renders<br/>DOM updates]
style D fill:#7c3aed,color:#fff
style F fill:#10b981,color:#fff
This diagram shows the data flow in our dashboard. A user action like clicking or typing triggers an event handler attached via delegation. The handler updates the state — for example, changing a filter or sort. The state change triggers the data layer to check the cache, and if needed, fetch from the API. The Promise resolves with data or rejects with an error. The state updates with the result. Finally, the UI re-renders, updating the DOM. Each layer has a specific job, and the boundaries between them are where good code design lives.
What This Module Is Not
A few things this module deliberately doesn't do:
It's not a React tutorial. We're building in vanilla JavaScript to expose what frameworks abstract away. The patterns we use — state management, event delegation, render lifecycle — are what frameworks implement internally. Understanding them in vanilla form makes framework usage clearer.
It's not a production-ready application. The code is illustrative. A real production dashboard would have tests, accessibility audits, internationalization, analytics, error reporting, and many other concerns we skip for clarity.
It's not the canonical answer. There are many ways to build a dashboard. We're showing one way that demonstrates the most course concepts. Your way might differ — that's fine. The point is to see one complete thing, not to be told the only right way.
The Code Structure
We'll organize the project into a small set of modules:
dashboard/
├── index.html (entry HTML)
├── main.js (entry script, sets up the app)
├── data/
│ ├── api.js (fetch wrapper, error handling)
│ └── cache.js (closure-based cache)
├── state/
│ └── store.js (class-based state container)
├── ui/
│ ├── list.js (renders the list)
│ ├── filters.js (renders filter controls)
│ └── errors.js (renders error states)
└── lib/
└── utils.js (debounce, classnames, etc.)
This structure isn't sacred. It's one reasonable way to organize a small project. The key principle: separating data, state, and UI into distinct modules makes each easier to reason about and change.
We'll build the data layer first (Topic 15.3), then the UI layer (Topic 15.4), then the state and integration (Topic 15.5). Each Topic ends with running code you can extend.
Interactive animation: Three layers, one loop: a user event changes state, and the UI renders from it, with the data layer below.
What You Should Do With This Module
Three modes of engagement:
1. Read it. Walk through the four building Topics and the question bank. See how the pieces fit. This alone is valuable.
2. Build it alongside. Open an editor. Type the code as you read. The mechanical practice of typing — even copying — produces muscle memory the reading alone doesn't.
3. Build a variation. After you've worked through the module once, build your own version with different requirements. A todo app. A messaging UI. A search-with-suggestions interface. Use the same patterns but for different content. This is where the patterns become yours.
Mode 3 is what produces the senior fluency. Reading is necessary but not sufficient. Building a variation cements the connections that the project demonstrated.
Try It
Exercise: Before starting Topic 15.2, sketch on paper how you'd architect this dashboard. Don't write code yet. Just answer:
- What modules would you create? What goes in each?
- Where does the cache live, and what's the eviction policy?
- How does the UI know when to re-render?
- How do you cancel an in-flight request when the user changes filters?
- How do you prevent the user's typing from triggering too many requests?
Each question has a defensible answer that draws on something from the course. Closures for the cache. State change events for re-renders. AbortController for cancellation. Debounce for the typing problem.
If your sketch matches the architecture we use in the next Topics, you're in good shape. If it differs, that's also fine — there isn't one right answer. The exercise is seeing the choices.