The basic post covered HTML, CSS, vanilla JS, jQuery. Modern web development sits on top of that base: Node.js as a JS runtime everywhere, package managers to wire dependencies, bundlers (Vite, esbuild, webpack) to produce production assets, component frameworks (React, Vue, Svelte) to manage state + UI, CSS frameworks (Tailwind, Bootstrap) to keep styles consistent, icon sets (Font Awesome, Lucide) for visuals, and a deployment story for shipping the result. This post is a survey of the stack and the trade-offs. (3D / WebGL / Three.js has its own dedicated series — see the link at the end.)


Learning Outcome

  • Install and use Node.js + npm / pnpm / yarn.
  • Initialise a project with Vite, understand the dev server + build output.
  • Read and write a React or Vue component with state, props, events.
  • Pick between React, Vue, Svelte for a new project.
  • Use a CSS framework (Tailwind / Bootstrap) effectively.
  • Add icons with Font Awesome or Lucide.
  • Call REST / GraphQL APIs from the browser.
  • Deploy a static site (Vercel / Netlify / Cloudflare Pages / S3+CloudFront).

Chapter 1 — Node.js as a JS runtime

Node.js is V8 (Chrome's JS engine) outside the browser. It powers:

  • Build tools (Vite, webpack, esbuild, Rollup).
  • Local dev servers.
  • The package manager (npm).
  • Many backend frameworks (Express, Fastify, NestJS, Next.js API routes).
  • Build pipelines in CI.

Install via nodejs.org (LTS) or nvm (manage multiple versions). Verify:

1
2
3
node --version    # v20+ in 2026
npm --version

Run a script:

1
2
node app.js

REPL: node opens an interactive prompt similar to Python's.


Chapter 2 — Package managers

Three contenders today:

Tool Speed Disk Notes
npm OK duplicates per-project ships with Node
pnpm fastest content-addressed store, hard-linked modern default for many teams
yarn (Berry) fast Plug'n'Play option corporate use, monorepos

Pick one per project and stick with it. The lockfile (package-lock.json / pnpm-lock.yaml / yarn.lock) is committed.

Common commands (npm flavour)

1
2
3
4
5
6
7
8
npm init -y                       # create package.json
npm install react # add dependency
npm install -D vite # add devDependency
npm install # restore from lockfile (after clone)
npm run dev # run a script defined in package.json
npm uninstall pkg
npx some-cli # run a CLI without installing globally

A typical package.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "my-app",
"version": "0.1.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint src",
"format": "prettier --write ."
},
"dependencies": {
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
"devDependencies": {
"vite": "^5.0.0",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.0.0",
"prettier": "^3.0.0"
}
}

Chapter 3 — Build tools (Vite + ESM)

Old days: webpack + Babel + a 200-line config; cold start 30 sec, HMR 2-5 sec. Modern: Vite uses native ES modules in dev (zero bundling) and esbuild / Rollup for production builds. Cold start < 500 ms, HMR < 100 ms.

1
2
3
4
5
6
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev # opens http://localhost:5173
npm run build # outputs to dist/

Templates: vanilla, vanilla-ts, react, react-ts, vue, vue-ts, svelte, svelte-ts, solid, lit, preact, qwik. TypeScript is the default in modern teams.

Why ESM matters

1
2
<script type="module" src="/src/main.js"></script>

The browser fetches each import-ed module separately. Dev servers serve them un-bundled — only re-process the file you changed. Production builds still bundle (fewer requests, tree-shaking).


Chapter 4 — React vs Vue vs Svelte

The three live framework families. Brief comparison:

React Vue Svelte
Released 2013 2014 2016
Maintainer Meta core team core team
Component file .jsx / .tsx .vue (HTML+JS+CSS in one) .svelte
State hooks (useState, useReducer) reactivity (ref, reactive) language-level (let x = 0)
Templating JSX (JS-like) HTML template + directives HTML + minimal directives
Bundle size baseline ~45 KB gzipped ~30 KB ~5 KB (compiles away)
Job market dominant strong, especially APAC growing
Best for huge ecosystem, hiring balance of approachability + power smallest output, first-time learners

There is no universally best. React if hiring + ecosystem matters most. Vue for a balanced learning curve. Svelte for performance + simplicity at small-to-medium scale.


Chapter 5 — React essentials

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/App.tsx
import { useState } from 'react';

export default function App() {
const [count, setCount] = useState(0);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(c => c + 1)}>+1</button>
<ChildList items={['a', 'b', 'c']} />
</div>

);
}

function ChildList({ items }: { items: string[] }) {
return (
<ul>
{items.map((x, i) => <li key={i}>{x}</li>)}
</ul>

);
}

Rules of thumb:

  • JSX — HTML-like syntax that compiles to React.createElement(...).
  • useState for local state.
  • useEffect for side effects (data fetching, subscriptions).
  • Props are read-only inputs from parent.
  • Always give array children a stable key prop.
  • Component names are PascalCase.

Fetching data

1
2
3
4
5
6
7
8
9
10
import { useEffect, useState } from 'react';

export default function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('/api/users').then(r => r.json()).then(setUsers);
}, []); // empty deps → run once on mount
return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

For real apps, use TanStack Query (@tanstack/react-query) or SWR instead of hand-rolling effects.

Routing

React itself does not include routing. Add React Router (react-router-dom) for SPA routes, or use Next.js / Remix for a more opinionated framework with file-based routing + server rendering.


Chapter 6 — Vue essentials (composition API)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- App.vue -->
<script setup>
import { ref } from 'vue';
const count = ref(0);
const inc = () => count.value++;
</script>


<template>
<h1>Count: {{ count }}</h1>
<button @click="inc">+1</button>
</template>

<style scoped>
h1 { color: navy; }
</style>

Single-file components bundle template + logic + styles. ref wraps a value; access with .value in JS, unwrapped automatically in templates.

Routing: vue-router. State: pinia. Full-stack framework: Nuxt.


Chapter 7 — CSS frameworks

Approach Example When
Utility classes Tailwind, UnoCSS rapid prototyping, design systems, modern teams
Component CSS Bootstrap, Bulma quick admin/dashboard, less custom design
CSS-in-JS styled-components, Emotion React apps with dynamic styling
CSS Modules (built into Vite) scoped styles per component, no framework
Hand-written nothing full control, small projects, design-led

Tailwind (the modern default)

1
2
3
4
5
6
7
8
<div class="flex items-center gap-4 p-4 bg-white rounded-xl shadow">
<img src="..." class="h-12 w-12 rounded-full">
<div>
<p class="font-semibold">Ada Lovelace</p>
<p class="text-sm text-gray-500">Mathematician</p>
</div>
</div>

Install:

1
2
3
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Configure content: ["./index.html", "./src/**/*.{js,jsx,ts,tsx,vue}"] in tailwind.config.js and include @tailwind base; @tailwind components; @tailwind utilities; in your CSS entry.

Bootstrap (still widely used)

1
2
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3/dist/css/bootstrap.min.css" rel="stylesheet">
1
2
3
4
5
6
7
8
<button class="btn btn-primary">Click</button>
<div class="container">
<div class="row">
<div class="col-md-6">Left</div>
<div class="col-md-6">Right</div>
</div>
</div>

Heavier visual opinion, faster to assemble admin dashboards. Pair with the JS plugins (modals, dropdowns, tooltips).

Trick: mixing Tailwind + Bootstrap in the same project usually fights — both impose layout opinions. Pick one. For new projects, Tailwind almost always wins; for legacy + content-heavy, Bootstrap can still shine.


Chapter 8 — Icons

Library Bundle Use
Font Awesome huge if loaded all; tree-shake-friendly via React/Vue packages mainstream brand-icons + many UI icons
Lucide (fork of Feather) small, MIT, modern most React/Vue teams default in 2026
Heroicons from Tailwind team pairs with Tailwind nicely
Material Symbols Google Android / Material Design feel
Tabler Icons huge free set open-source designers' favourite

React usage (Lucide):

1
2
3
4
import { Search, Settings } from 'lucide-react';

<button><Search size={16} /> Search</button>

Avoid loading the whole Font Awesome CSS bundle in 2026 — too heavy. Use the per-icon import pattern for any library.


Chapter 9 — APIs: REST + GraphQL

REST

1
2
3
4
5
6
7
8
9
10
11
12
13
// GET
const r = await fetch('/api/users');
const users = await r.json();

// POST
const r2 = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
body: JSON.stringify({ name: 'Ada' }),
});
if (!r2.ok) throw new Error(`HTTP ${r2.status}`);
const created = await r2.json();

GraphQL

Single endpoint, client picks fields:

1
2
3
4
5
6
7
8
9
10
11
12
const query = `
query {
user(id: 1) { id name email posts { title } }
}
`;

const r = await fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query }),
});
const { data } = await r.json();

Tools: Apollo Client (React/Vue), urql, graphql-request.

Data-fetching libraries (the time-saver)

Hand-rolling fetch + loading + error state in every component is repetitive. Use:

  • TanStack Query (@tanstack/react-query, @tanstack/vue-query)
  • SWR (React)
  • Pinia Colada (Vue)

They handle caching, deduplication, retries, background refresh, pagination, and devtools. Standard in modern apps.


Chapter 10 — TypeScript (briefly)

JavaScript with optional static types. Catches whole classes of bugs at compile time + improves IDE autocomplete.

1
2
3
4
5
6
type User = { id: number; name: string; email: string };

function greet(u: User): string {
return `Hello, ${u.name}`;
}

Vite templates ship with TS preconfigured. Use TS for any project bigger than a one-page demo — the productivity payoff comes quickly.


Chapter 11 — Deployment

Target Tool Best for
Static hosting Vercel, Netlify, Cloudflare Pages, GitHub Pages SPAs, marketing sites, docs
S3 + CloudFront AWS full control, fits a wider AWS stack
Full-stack edge Vercel (Next.js), Cloudflare Workers, Deno Deploy SSR + APIs + edge
Containers Fly.io, Render, AWS ECS/Fargate Node.js servers, WebSockets, background jobs
VPS DigitalOcean, Hetzner, Linode hand-rolled, cheap

A typical Vite build → static deploy:

1
2
3
4
5
npm run build     # outputs dist/
# Vercel: just `vercel deploy` or git-push integration
# Netlify: drag-and-drop dist/ in the dashboard, or `netlify deploy --prod`
# Cloudflare Pages: connect GitHub repo

For React/Vue SPAs that need a backend, the easiest stack in 2026 is Next.js on Vercel or Nuxt on Vercel/Cloudflare — they unify frontend + serverless backend + edge functions in one deployment.


Chapter 12 — Performance baseline

Hit these targets in Lighthouse for a polished site:

Metric Target
LCP (Largest Contentful Paint) < 2.5 s
INP (Interaction to Next Paint) < 200 ms
CLS (Cumulative Layout Shift) < 0.1
First-load JS (uncompressed) < 200 KB
Image format AVIF / WebP, not PNG/JPG raw
Fonts font-display: swap, subset, self-host

Tools: Lighthouse (in DevTools), PageSpeed Insights, WebPageTest.

Common wins:

  1. Lazy-load below-the-fold images (loading="lazy").
  2. Code-split routes (React.lazy, dynamic import()).
  3. Compress images (use a build-time tool — @astrojs/image, sharp).
  4. Preload the hero font.
  5. Remove unused JS (the bundle analyzer flags it).

Practice Exercises

Exercise 1 — Vite + React/Vue starter

npm create vite@latest. Build a single-page counter app. Push to GitHub. Deploy to Vercel.

Exercise 2 — TanStack Query

Fetch https://jsonplaceholder.typicode.com/users with TanStack Query. Render the list with loading + error states. Add a refresh button.

Exercise 3 — Tailwind UI

Build a 3-card pricing layout with Tailwind. Responsive: stacked on mobile, 3 columns on desktop. Use Lucide icons in the feature lists.

Exercise 4 — Full mini-app

A note-taking app: list + create + delete + edit. State via React Context or Pinia. Data fetched via TanStack Query against a mock JSON server (json-server). TypeScript. Tailwind. Deploy to Vercel.


Cheat-sheet

What How
Init project npm create vite@latest
Add dep npm install pkg
Add dev dep npm install -D pkg
Run script npm run dev
React state const [x, setX] = useState(0)
React effect useEffect(() => { ... }, [deps])
Vue state const x = ref(0)
Vue effect watchEffect(() => { ... })
Routing (React) react-router-dom / Next.js
Routing (Vue) vue-router / Nuxt
Data fetching TanStack Query / SWR
Style toolkit Tailwind (modern) / Bootstrap (legacy)
Icon Lucide / Heroicons / Font Awesome
Types TypeScript everywhere
Deploy static Vercel / Netlify / Cloudflare Pages
Deploy full-stack Next.js on Vercel
Audit perf Lighthouse / PageSpeed Insights

Where to next

For 3D, WebGL, WebGPU, Three.js, React Three Fiber, shaders, instancing, physics, AI-assisted 3D and the rest — see the dedicated Three.js series (posts threejs_00 through threejs_13). That topic deserved its own multi-post arc rather than a single chapter.

Other areas that warrant their own deep-dive posts in future:

  • Next.js / Nuxt — full-stack frameworks built on React / Vue with file-based routing, server components, edge.
  • State management — Zustand, Jotai, Redux Toolkit (React); Pinia (Vue).
  • Testing — Vitest + Testing Library, Playwright for E2E.
  • Animations — Framer Motion (React), GSAP, View Transitions API.
  • PWA — service workers, offline, install-to-home-screen.
  • WebSockets / real-time — Socket.IO, native WebSocket, SSE.
  • Web Components / Lit — framework-agnostic components.
  • Astro / Qwik — modern islands / resumability frameworks for content sites.

References

Note: this post is in progress. Planned additions: Next.js full walkthrough, Server Components explained, deep dive on Web Animations API. (WebGPU + Three.js is covered in the separate Three.js series.)