Learning & Certifications · Web Development

Node.js + React:
Build Real Projects with AI

A hands-on 4-chapter course. No theory overload: you build from Chapter 1, Day 1. AI is your co-pilot throughout.

⚡ 4 Chapters 🧑‍💻 Basic → Intermediate 🤖 AI-Assisted 🛠 Project-First
1

Node.js in 30 Minutes

Runtime, npm, first server: everything you need to move fast

What Is Node.js, and Why It Matters

Node.js is JavaScript running outside the browser. Before Node, JavaScript only ran inside Chrome, Firefox, Safari. Node changed that. Now you write JS that runs on servers, reads files, talks to databases, and powers APIs.

It uses the V8 engine (same engine Chrome uses) and runs on a single thread with a non-blocking event loop. This means it handles thousands of simultaneous connections without breaking a sweat.

Infographic · Node.js Runtime Architecture
YOUR CODE JavaScript .js files NODE.JS V8 Engine Executes JS Event Loop Non-blocking I/O libuv · Thread Pool HTTP Server APIs · Websites File System Read · Write · Stream Database MongoDB · SQL npm ecosystem 2M+ packages install & reuse

Installing Node.js

1

Download Node.js: go to nodejs.org and download the LTS version (Long-Term Support). This includes npm automatically.

2

Verify installation: open your terminal and run:

terminal
node --version   # should print v20.x.x or higher
npm --version    # should print 10.x.x or higher
💡

If you work with multiple Node versions, use nvm (Node Version Manager). It lets you switch between versions instantly: nvm install 20 && nvm use 20

Your First Node.js Script

Create a file called hello.js and run it with Node. No browser needed.

hello.js
// Node.js has access to system resources the browser doesn't
const os = require('os');

console.log('Hello from Node.js!');
console.log('Platform:', os.platform());
console.log('CPU cores:', os.cpus().length);
console.log('Free memory:', Math.round(os.freemem() / 1024 / 1024), 'MB');
terminal
node hello.js
# Hello from Node.js!
# Platform: win32
# CPU cores: 8
# Free memory: 4096 MB

Building Your First HTTP Server

Node ships with a built-in http module. You don't need anything else to handle web requests.

server.js
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });

  const data = {
    message: 'Node.js server is running',
    url: req.url,
    method: req.method,
    timestamp: new Date().toISOString()
  };

  res.end(JSON.stringify(data, null, 2));
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000');
});
terminal
node server.js
# Server running at http://localhost:3000

# Open browser at http://localhost:3000 to see the JSON response

npm: The Package Manager

npm lets you install libraries written by others. Instead of building everything from scratch, you pull in proven code. Every Node project starts with:

terminal
mkdir my-project && cd my-project
npm init -y            # creates package.json with defaults
npm install express    # installs Express (web framework)
npm install nodemon -D # installs as dev dependency (auto-restart on change)
Mini Project

Express API: 10-line JSON Server

Create a real REST endpoint that returns structured data.

index.js
const express = require('express');
const app = express();

app.use(express.json());

const users = [
  { id: 1, name: 'Alice', role: 'Developer' },
  { id: 2, name: 'Bob',   role: 'Designer'  },
];

app.get('/api/users', (req, res) => {
  res.json({ success: true, count: users.length, data: users });
});

app.get('/api/users/:id', (req, res) => {
  const user = users.find(u => u.id === Number(req.params.id));
  user ? res.json(user) : res.status(404).json({ error: 'User not found' });
});

app.listen(3000, () => console.log('API ready at http://localhost:3000/api/users'));
expressREST APIJSONroutes
🤖

AI Tip: Paste your server.js into Claude or ChatGPT and ask: "Add POST and DELETE routes for users with in-memory storage." Watch how fast it scaffolds the full CRUD logic.

2

React: Think in Components

JSX, state, hooks: the building blocks of every modern web UI

What Is React?

React is a JavaScript library for building user interfaces. It was created by Facebook in 2013 and is now the most used frontend library in the world. The core idea: break your UI into reusable components. Each component is a function that returns HTML-like syntax called JSX.

Instead of manually updating the DOM, React watches your data (state) and automatically re-renders only the parts that changed. This makes UIs fast and predictable.

Infographic · React Component Tree & Data Flow
<App /> Root Component <Header /> Nav · Logo · Menu <Main /> Content Area <Sidebar /> Links · Widgets <CardList /> maps data → cards <Form /> Input · Submit props ↓ props ↓ useState · useEffect · Context

Setting Up React with Vite

Forget Create React App; it's outdated. Vite is the modern standard. It starts in under a second and builds 10x faster.

terminal
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
# App running at http://localhost:5173

JSX: HTML Inside JavaScript

JSX looks like HTML but it's actually JavaScript. React compiles it to React.createElement() calls automatically. You write the familiar HTML syntax, React handles the rest.

App.jsx
// A component is just a function that returns JSX
function Welcome({ name, role }) {
  return (
    <div className="card">
      <h2>Hello, {name}!</h2>
      <p>Role: <strong>{role}</strong></p>
      {role === 'admin' && <button>Admin Panel</button>}
    </div>
  );
}

// Use it like an HTML tag; pass data as attributes (props)
function App() {
  return (
    <div>
      <Welcome name="Alice" role="admin" />
      <Welcome name="Bob"   role="user"  />
    </div>
  );
}

State with useState

State is data that changes over time. When state updates, React re-renders the component automatically. You never touch the DOM directly.

Counter.jsx
import { useState } from 'react';

function Counter() {
  // [currentValue, functionToUpdateIt] = useState(initialValue)
  const [count, setCount] = useState(0);
  const [color, setColor] = useState('blue');

  const increment = () => {
    setCount(prev => prev + 1);
    if (count >= 9) setColor('red');
  };

  return (
    <div>
      <h1 style={{ color }}>Count: {count}</h1>
      <button onClick={increment}>+1</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

export default Counter;

Fetching Data with useEffect

useEffect runs code after the component renders. It's where you fetch data, set up subscriptions, or interact with external APIs.

UserList.jsx
import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers]     = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError]     = useState(null);

  useEffect(() => {
    // Runs once when component mounts (empty dependency array [])
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(res  => res.json())
      .then(data => { setUsers(data); setLoading(false); })
      .catch(err => { setError(err.message); setLoading(false); });
  }, []);

  if (loading) return <p>Loading...</p>;
  if (error)   return <p>Error: {error}</p>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          {user.name} - {user.email}
        </li>
      ))}
    </ul>
  );
}
🤖

AI Tip: Tell Claude: "Convert my UserList component to use async/await and add a search filter that updates as I type." This is a perfect AI task: it's a clear, contained refactor.

3

Full-Stack: Connect Node + React

Build a real Express API and consume it from React

The Full-Stack Mental Model

When people say "full-stack with Node + React" they mean: React runs in the browser and Node/Express runs on the server. React asks the server for data, the server reads a database and sends JSON back, React renders the result.

Infographic · Client ↔ Server Data Flow
BROWSER React App useEffect → fetch() setState → re-render localhost:5173 HTTP Request GET /api/users JSON Response [ {id,name}, ... ] SERVER Node + Express app.get('/api/users') res.json(data) localhost:3000 Database MongoDB PostgreSQL CORS Required

Setting Up the Express API

server/index.js
const express = require('express');
const cors    = require('cors');
const app     = express();

// CORS lets your React app (port 5173) talk to this server (port 3000)
app.use(cors());
app.use(express.json());

// In-memory data store (replace with a database later)
let tasks = [
  { id: 1, title: 'Learn Node.js',  done: false },
  { id: 2, title: 'Learn React',    done: false },
  { id: 3, title: 'Build full-stack app', done: false },
];

app.get('/api/tasks',     (req, res) => res.json(tasks));
app.post('/api/tasks',    (req, res) => {
  const task = { id: Date.now(), title: req.body.title, done: false };
  tasks.push(task);
  res.status(201).json(task);
});
app.patch('/api/tasks/:id', (req, res) => {
  const task = tasks.find(t => t.id === Number(req.params.id));
  if (!task) return res.status(404).json({ error: 'Not found' });
  task.done = !task.done;
  res.json(task);
});

app.listen(3000, () => console.log('API on http://localhost:3000'));
terminal
npm install cors
node server/index.js

Consuming the API from React

src/App.jsx
import { useState, useEffect } from 'react';

const API = 'http://localhost:3000/api';

export default function App() {
  const [tasks,    setTasks]    = useState([]);
  const [newTitle, setNewTitle] = useState('');

  useEffect(() => {
    fetch(`${API}/tasks`).then(r => r.json()).then(setTasks);
  }, []);

  const addTask = async () => {
    if (!newTitle.trim()) return;
    const res  = await fetch(`${API}/tasks`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ title: newTitle }),
    });
    const task = await res.json();
    setTasks(prev => [...prev, task]);
    setNewTitle('');
  };

  const toggle = async (id) => {
    const res     = await fetch(`${API}/tasks/${id}`, { method: 'PATCH' });
    const updated = await res.json();
    setTasks(prev => prev.map(t => t.id === id ? updated : t));
  };

  return (
    <div style={{ maxWidth: 500, margin: '2rem auto', fontFamily: 'sans-serif' }}>
      <h1>Full-Stack Task List</h1>
      <div style={{ display: 'flex', gap: '0.5rem', marginBottom: '1rem' }}>
        <input
          value={newTitle}
          onChange={e => setNewTitle(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && addTask()}
          placeholder="New task..."
          style={{ flex: 1, padding: '0.5rem' }}
        />
        <button onClick={addTask}>Add</button>
      </div>
      <ul style={{ listStyle: 'none', padding: 0 }}>
        {tasks.map(task => (
          <li key={task.id}
            onClick={() => toggle(task.id)}
            style={{ padding: '0.75rem', cursor: 'pointer',
                     textDecoration: task.done ? 'line-through' : 'none',
                     opacity: task.done ? 0.5 : 1 }}>
            {task.done ? '✅' : '⬜'} {task.title}
          </li>
        ))}
      </ul>
    </div>
  );
}

You now have a working full-stack app. Run the Express server in one terminal, Vite in another, and you have a live task manager talking across client and server.

4

Build Faster with AI

Use Claude and ChatGPT as your pair programmer: scaffold, debug, refactor

The AI-Assisted Dev Workflow

AI doesn't replace learning; it accelerates it. Once you understand components, state, and APIs (Chapters 1-3), AI helps you move 5x faster by handling boilerplate, suggesting patterns, and explaining errors instantly.

Infographic · AI-Assisted Development Loop
💡 IDEA what to build 🤖 PROMPT ask Claude/GPT </> CODE scaffold & edit 🧪 TEST run · debug 🔧 DEBUG paste error to AI SHIP IT faster every loop

Prompt Patterns That Actually Work

Bad prompts get generic code. Good prompts give you exactly what you need. Here are the patterns that work best for Node.js and React development:

🤖 Scaffold Prompt

"Create a React component called ProductCard that accepts name, price, image, and inStock as props. Use Tailwind CSS classes. Show an 'Out of Stock' badge when inStock is false. Include TypeScript types."

🤖 Debug Prompt

"I'm getting this error in my React app: [paste the full error + stack trace]. Here's the component causing it: [paste component]. What's wrong and how do I fix it?"

🤖 Refactor Prompt

"Refactor this Express route to use async/await and add proper error handling with try/catch. Also add input validation for the request body fields: [paste your route]."

🤖 Explain Prompt

"Explain this code to me like I'm just learning React. Walk through each line and explain why it's needed: [paste code]."

Final Project: AI-Assisted Task Manager

You've already built the base in Chapter 3. Now upgrade it with AI. Here's your AI task sequence:

1

Add persistence. Prompt: "Add a JSON file as a simple database for my Express tasks API. Read on startup, write on every change."

2

Add filtering. Prompt: "Add a filter bar to my React task list. Filter by: All, Active, Completed. Keep the logic in state."

3

Style it. Prompt: "Style my Task Manager with a dark theme using plain CSS. Cards, hover effects, smooth transitions."

4

Add auth (stretch). Prompt: "Add a simple JWT authentication to my Express API with login endpoint and protected task routes."

⚠️

Always read AI-generated code before running it. AI makes mistakes: wrong method names, outdated APIs, missing edge cases. Use it to scaffold, then review and adapt. The more you code, the better you'll catch AI errors.

What to Learn Next

💡

The fastest way to learn is to build. Take any idea (a bookmark manager, a weather dashboard, a budget tracker) and build it with Node + React + AI. Every real project teaches you 10x more than any tutorial.

Node.js + React: Build Real Projects with AI · richardgamarra.com · Learning & Certifications