Capstone — Configuring a Real Project's Build Pipeline

Course 1 · Ch 9
Capstone — Configuring a Real Project's Build Pipeline
One small real project, every prior chapter's own concept exercised for real

A small dashboard app, built with Vite: a main page, a lazy-loaded settings panel, CSS Modules for styling, and an environment-driven API URL — combining every chapter this course has covered into one real, working configuration.

Project Layout

dashboard/ ├── src/ │ ├── main.js │ ├── Dashboard.module.css │ └── settings-panel.js ├── .env ├── postcss.config.js ├── vite.config.js └── package.json

Environment Variables

# .env VITE_API_URL=https://api.example.com

Vite only exposes environment variables prefixed with VITE_ to client-side code — a deliberate, security-conscious default that prevents accidentally leaking server-only secrets into a bundle shipped to every user's browser.

vite.config.js

export default { build: { outDir: 'dist', sourcemap: true // build-tooling1-4's own debugging bridge } };

postcss.config.js

export default { plugins: { autoprefixer: {} // build-tooling1-7's own browserslist-driven plugin } };

src/Dashboard.module.css

.settingsButton { display: flex; user-select: none; }

src/main.js — Everything Combined

import styles from './Dashboard.module.css'; // CSS Modules, build-tooling1-7 const apiUrl = import.meta.env.VITE_API_URL; // env var, Vite-specific access const button = document.querySelector('#settings-button'); button.className = styles.settingsButton; button.addEventListener('click', async () => { // dynamic import — code splitting, build-tooling1-8 const { openSettingsPanel } = await import('./settings-panel.js'); openSettingsPanel(apiUrl); });

package.json Scripts

{ "scripts": { "dev": "vite", // build-tooling1-5: native ESM + esbuild pre-bundling "build": "vite build" // build-tooling1-5: switches to Rollup underneath } }
Where's the Babel/esbuild config?
There isn't any — deliberately. Vite handles syntax transformation internally via esbuild (build-tooling1-6) without requiring the explicit loader configuration build-tooling1-3's own Webpack setup needed. This absence is itself a concrete example of the dev-experience gap this course traced from Chapter 3 through Chapter 5.

Chapter Attribution

Capstone pieceConceptFrom
The entire premise — why any of this config existsReal apps outgrow <script src>, npm packages need translationbuild-tooling1-1
import/export throughout, main.js as the entry pointThe dependency graph and entry-point modelbuild-tooling1-2
Choosing Vite instead of a webpack.config.jsThe exact trade-off Webpack's own complexity sets upbuild-tooling1-3
No explicit transpilation config neededVite's internal esbuild-based transpilation absorbs this job automaticallybuild-tooling1-4
vite.config.js, npm run dev / npm run buildNative-ESM dev server vs. Rollup-powered production buildbuild-tooling1-5
Why dev startup and rebuilds feel instantesbuild's own AOT-compiled, natively parallel speedbuild-tooling1-6
postcss.config.js, Dashboard.module.cssPostCSS/autoprefixer and CSS Modules' own scoped class namesbuild-tooling1-7
The dynamic import() on clickCode splitting — the settings panel loads only when actually neededbuild-tooling1-8
Honest scope note
This capstone deliberately stays within what this course actually taught. Left out, on purpose: a from-scratch Webpack configuration walkthrough (build-tooling1-3 covered the concepts; this capstone deliberately builds with Vite instead); any monorepo or multi-package tooling (a genuinely separate, larger topic); and custom plugin authoring for either Vite or PostCSS (using existing plugins was this course's own scope — writing new ones is not). None of these are gaps in what was taught — they're deliberate boundaries of a single, focused capstone.

Coding Challenges

Challenge 1

Explain why the .env file's variable is named VITE_API_URL rather than just API_URL, and explain what would happen to that value if the VITE_ prefix were removed.

📄 View solution
Challenge 2

Trace what happens when a user clicks the settings button in this capstone's own main.js. Which chapter's own concept does this exercise, and what real benefit does it provide for the very first page load, before the button is ever clicked?

📄 View solution
Challenge 3

Pick three rows from this chapter's own chapter-attribution table and explain, in one or two sentences each, exactly which piece of this capstone's configuration draws on that chapter's material and why it was needed here.

📄 View solution

Chapter 9 Quick Reference — Course Recap

  • build-tooling1-1 to -2 — why build tools exist, the dependency graph and entry-point model, CommonJS vs. ESM
  • build-tooling1-3 to -4 — Webpack's loaders/plugins and its own real config-complexity trade-off, Babel/tsc transpilation and source maps
  • build-tooling1-5 to -6 — Vite's native-ESM dev server as a direct response, and the real Go/Rust engineering reason it's fast
  • build-tooling1-7 to -8 — CSS's own build pipeline (PostCSS, CSS Modules), and production optimization (tree shaking, code splitting, minification)
  • build-tooling1-9 — all of the above, combined into one real, working project configuration
  • This closes the Build Tooling course — the invisible layer between the code you write and the code the browser actually runs is no longer invisible