Chapters

Hide chapters

React Apprentice

First Edition · web · React 8.0.0 · Visual Studio Code

Section I: Rendering Right

Section 1: 7 chapters
Show chapters Hide chapters

1. Setting Up Your React Workspace
Written by Eli Ganim

Every React project starts the same way — with a working workspace. That means the tools that create your project, serve it in the browser while you code, and check your work as you type.

In this chapter, you’ll install Node.js, create a React and TypeScript project with a build tool called Vite and run it in your browser. Along the way, you’ll learn what each tool actually does, so nothing feels like magic.

You’ll also lay the first brick of the app you’ll build throughout this book — the Learning Tracker, an app for browsing courses, planning what to learn next and tracking your progress. Today, your app starts life as a heading and a single course title. By the end of the book, it’ll be a complete, tested app deployed to the web.

You’ll create everything in this chapter from scratch, so there’s no starter project to open. If you get stuck at any point, compare your work against the finished project in the final folder of this chapter’s materials.

The Toolchain at a Glance

Before you type any commands, it helps to know what you’re about to install and why. Modern web development relies on tools that run on your computer — not in the browser — to create projects, check code and serve your app while you work. Here’s the cast:

  • Node.js: A program that runs JavaScript outside the browser. The tools below are themselves written in JavaScript, so they need Node.js to run.
  • npm: Node’s package manager. It downloads packages — reusable libraries of code — and runs project commands called scripts. It’s installed automatically with Node.js.
  • Vite: The build tool, pronounced “veet” — French for “fast”. Vite creates new projects, serves your app during development with instant updates, and packages everything for production when you’re ready to ship.
  • React: The library this book is about. It lets you describe your interface as reusable components and keeps the page in sync with your data.
  • TypeScript: JavaScript plus type checking. It reads your code as you write it and catches data mistakes — like a misspelled property name — before you even reload the browser.

Here’s how they fit together:

The toolchain: Node.js runs npm and Vite, which serve your React and TypeScript code.
The toolchain: Node.js runs npm and Vite, which serve your React and TypeScript code.

Node.js runs the tooling, npm installs and launches it, Vite serves your project and your React and TypeScript code is what all of it exists to support. You’ll meet each tool in person over the next few pages.

Installing Node.js

You might already have Node.js installed. To check, open a terminal — on macOS, that’s Terminal in Applications ▸ Utilities; on Windows, search the Start menu for Terminal or PowerShell — and run:

node --version

If this prints a version number of v22.12.0 or higher, you’re done: skip ahead to the next section. If you see an error or an older version, you’ll install Node.js now.

Go to https://nodejs.org and download the LTS version — short for long-term support, the most stable release line. The site offers a couple of ways to get it; you want the prebuilt installer, not the setup script:

  • On macOS, choose the .pkg installer (skip the .gz option — that’s a compressed archive for manual installs, not what you want here).
  • On Windows, choose the .msi installer.

Run the installer and accept the default options.

When the installer finishes, close your terminal, open a new one and run node --version again. This time, you’ll see the version you installed.

Verify npm arrived with it:

npm --version

Any version number means you’re set.

Note: Vite currently requires Node.js version 20.19 or higher, and the requirement occasionally rises with new releases. If Vite complains about your Node.js version later in this chapter, check the current requirement at https://vite.dev/guide/ and install a newer LTS.

Creating the Project

Time to create the Learning Tracker. In your terminal, navigate to the folder where you keep your coding projects — for example, cd ~/Projects. Then run:

npm create vite@latest learning-tracker -- --template react-ts --no-interactive

That’s a dense command, so here’s what each part does:

  • npm create vite@latest: Tells npm to download and run the latest version of create-vite, Vite’s project generator.
  • learning-tracker: The name of your project. The generator creates a folder with this name.
  • –: A separator. Everything before it is for npm; everything after it goes to the generator.
  • –template react-ts: Picks the project template — react-ts is React with TypeScript. –no-interactive: Runs the generator without its usual prompts. In a terminal, create-vite starts in interactive mode by default; this flag tells it to use the name and template you passed instead of asking questions.

After a moment, you’ll see output like this:

Scaffolding project in /Users/you/Projects/learning-tracker...

Done. Now run:

  cd learning-tracker
  npm install
  npm run dev

The generator created the folder, filled it with a small starting project and now suggests your next three commands. You’ll run them one at a time, with a proper look at what each one does.

Note: If you run npm create vite@latest without the extra arguments, the generator asks questions instead: a project name, a framework and a variant. Answering learning-tracker, React and TypeScript gets you the same result.

First, move into your new project:

cd learning-tracker

Then open the learning-tracker folder in your code editor, so it’s ready for the tour coming up. If you don’t have one yet, Visual Studio Code is a free, popular choice with excellent TypeScript support.

Installing the Dependencies

The generator listed the packages your project needs — React among them — but it didn’t download them. That’s your next command. In the terminal, inside the project folder, run:

npm install

npm reads the project’s package list from package.json, downloads every package it names — plus the packages those packages need — and stores them all in a folder called node_modules. After a few seconds, you’ll see a summary like added 27 packages. A few warnings in the output are normal; you only need to act if you see an actual error.

Two things appeared in your project, and both deserve a quick introduction:

  • node_modules: The folder holding every downloaded package. It’s big, you never edit anything inside it and you can always delete it and run npm install again to rebuild it.
  • package-lock.json: A record of the exact version of every package npm installed. Thanks to this file, installing the project on another computer produces the same result. Leave it alone — npm maintains it for you.

Starting the Development Server

Now for the payoff. Run:

npm run dev

This runs the script named dev from package.json, which starts Vite’s development server — a small local web server that serves your app and refreshes it as you code. The terminal shows something like:

  VITE v8.1.4  ready in 113 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose

The Local line is your app’s address. localhost means “this computer” — the server isn’t on the internet, it’s a private preview only you can see. Open http://localhost:5173 in your browser:

Vite's starter page, proof that your whole toolchain works.
Vite's starter page, proof that your whole toolchain works.

What you’re looking at is Vite’s placeholder app — a “hello world” page confirming that Node.js, npm, Vite, React and TypeScript all did their jobs. Congratulations: you’re running a React app.

When you eventually want to stop the server, press q followed by Enter in the terminal, or Ctrl-C. For now, leave it running — you’ll want it for the rest of the chapter.

Seeing Live Updates

The development server’s best trick is updating the browser the instant you save a file. You’ll prove that now, and make your first code edit in the process.

In your editor, open src/App.tsx. Don’t worry about understanding the file yet — you’ll tour it in a moment and replace it soon after. Find this line:

<h1>Get started</h1>

Change it to:

<h1>Hello, React!</h1>

Save the file and watch the browser. The heading changes to Hello, React! immediately — no reload, no lost page state, nothing to click. This is Vite’s hot module replacement, or HMR: during development, Vite swaps your changed code into the running page. It only exists during development, but it’s what makes React work feel like a conversation with the browser.

Change the heading back to Get started and save again, so your project matches the tour coming up next.

Touring the Essential Files

The generator created about fifteen files. Most of them are configuration you can safely ignore for a long time. Only four matter right now, and you’ll visit them from the outside in.

package.json

Open package.json in the project root. It’s your project’s identity card. The two parts worth reading today are the scripts and the dependencies:

"scripts": {
  "dev": "vite",
  "build": "tsc -b && vite build",
  "lint": "oxlint",
  "preview": "vite preview"
},
"dependencies": {
  "react": "^19.2.7",
  "react-dom": "^19.2.7"
}

Here’s what they mean:

  • scripts: Command shortcuts you run with npm run <name>. You already used dev. The build script type-checks your code and packages the app for production, and preview serves that production build locally — both stars of Chapter 17. lint runs a code-quality checker.
  • dependencies: Packages your app itself uses — React, and React’s bridge to the browser, react-dom.

Below dependencies, a devDependencies section lists the tools used only while developing, like Vite and TypeScript. The version numbers on your machine may be newer than the ones printed here — that’s fine.

index.html

Open index.html, also in the project root. This is the only HTML page in the entire project. The interesting part is the body:

<body>
  <div id="root"></div>
  <script type="module" src="/src/main.tsx"></script>
</body>

Two things happen here. The page declares one empty div with the id root — the container React will fill with your UI. Then it loads a single script, src/main.tsx. Every pixel you saw in the browser came from that script filling that empty div.

src/main.tsx

Open src/main.tsx — the file index.html loads, and the place where React starts:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

Take it line by line. The imports pull in StrictMode from React, createRoot from React’s browser bridge, the app’s global stylesheet and the App component from src/App.tsx — the file you edited earlier.

Then comes the launch: createRoot receives the root div from the page and returns a React root — React’s connection to that spot in the page. Calling render asks React to display App there. The exclamation mark after getElementById('root') is you telling TypeScript “this element definitely exists” — without it, TypeScript would warn that the element might not be found.

StrictMode is a wrapper that switches on extra checks during development to surface common mistakes early. It adds nothing in production. You’ll see exactly what it checks in Chapters 10 and 12; for now, know it’s a helpful safety net, not something to remove.

Note: The import and export keywords are JavaScript modules — a JavaScript feature, not a React one. Every file is a module: export default App at the bottom of App.tsx offers App to other files, and import App from './App.tsx' accepts the offer. You’ll organize components with modules in Chapter 3.

One more thing about this file: its extension. A .tsx file is a TypeScript file that can also contain the HTML-like markup you’ve been looking at, called JSX — Chapter 3 covers it properly. TypeScript reads these files as you type and flags mistakes in your editor, long before the browser gets involved.

src/App.tsx

You’ve already peeked at src/App.tsx. In essence, it’s one function named App that returns markup describing everything you saw in the browser — the logo, the heading, the counter button, the links — with export default App at the bottom. It’s the entire visible app in one file.

Step back and trace the whole journey:

The render path: from browser request to your component's UI.
The render path: from browser request to your component's UI.

The browser asks the development server for the page and receives index.html. That page loads src/main.tsx, which creates a React root in the empty div and renders App into it. src/App.tsx returns what the UI should be, and React makes the browser match it. Every React app in this book — however large it grows — follows this exact path.

Replacing the Template UI

Vite’s placeholder page has done its job. Time to evict it and move the Learning Tracker in.

Replace the entire contents of src/App.tsx with:

import './App.css'

function App() {
  return (
    <main>
      <h1>Learning Tracker</h1>
    </main>
  )
}

export default App

This is the whole app now, so take stock of what each part does:

  • The import keeps the app’s stylesheet connected. You’ll restyle the app properly in Chapter 6.
  • App is a plain function that returns markup — a main landmark holding one heading. Describing UI with functions like this one is the core of React, and Chapter 2 digs into why it works this way.
  • export default App hands the component to src/main.tsx, exactly as before.

Save the file and look at the browser:

The Learning Tracker begins: one heading, endless potential.
The Learning Tracker begins: one heading, endless potential.

The template page is gone, replaced by your heading. Don’t worry about the leftover template files, like the logo images — they’re harmless, and you’ll clean house in Chapter 7.

Rendering Your First Data

The heading is fixed text. Real interfaces show data — course names, prices, scores — and the UI changes when the data change. Your last task of the chapter is to render your first piece of data.

In src/App.tsx, add this line inside App, just above return:

const courseTitle = 'React Basics'

There’s nothing React-specific here — it’s an ordinary JavaScript constant living inside the component function.

Now, put it on screen. Below the <h1> line, add:

<p>Now learning: {courseTitle}</p>

The curly braces are new. Inside JSX markup, braces open a window back into JavaScript: React evaluates whatever expression is inside and renders the result. Here, that’s the value of courseTitle.

Save the file and check the browser:

The page now renders a value from your code.
The page now renders a value from your code.

Now prove to yourself that the UI follows the data. Change 'React Basics' to any course title you like and save — the page updates. You changed data, and the UI followed. That single idea is the beating heart of React, and Chapter 2 explores it in depth.

Before moving on, set the value back to 'React Basics' so your project matches the next chapter’s starting point.

Notice what you didn’t write — any type annotations. Hover over courseTitle in your editor, and you’ll see TypeScript already knows its type from the value you assigned. This is type inference, and it’s how most types in this book will appear — you’ll write annotations only when they earn their keep.

Exploring the Developer Tools

Two browser tools will accompany you for the rest of the book, and both deserve a quick hello while your app is running.

First, the browser’s built-in DevTools. Right-click anywhere on your page and choose Inspect. In the Elements panel — Inspector in Firefox — expand the div with the id root. There they are — the main, h1 and p elements your component returned, living in the page as real elements.

Second, React Developer Tools, a browser extension made by the React team. Visit https://react.dev/learn/react-developer-tools and follow the installation link for your browser. After installing, reopen DevTools and find the new Components tab:

React DevTools shows your app as React sees it: a tree of components.
React DevTools shows your app as React sees it: a tree of components.

Where the Elements panel shows the page as the browser sees it, the Components tab shows it as React sees it — a tree of components, with App at the top. The tree holds exactly one component today, but as the Learning Tracker grows, this panel becomes your X-ray machine. You’ll use it for serious debugging in Chapter 16.

Challenge: Make the Tracker Yours

Time to fly solo for the first time. Your challenge has two parts:

  1. Change the rendered course title to a course you actually want to take — maybe “Modern TypeScript” or “CSS Animation”.
  2. Add a subtitle — a line of fixed text under the main heading, like Track every course you plan to learn, using an <h2> element.

A couple of hints:

  • The subtitle is one new line inside main, right below the <h1>.
  • Fixed text needs no curly braces — braces are only for JavaScript values.

You’ll find the solution in the challenge folder of this chapter’s materials. Give it an honest try first — this is the first entry in a habit that’ll serve you through the whole book.

Key Points

  • Node.js runs JavaScript tooling on your computer, and npm — installed with it — downloads packages and runs project scripts.
  • Vite creates your project, serves it during development and builds it for production.
  • npm install reads package.json and fills node_modules, while package-lock.json records exact versions for repeatable installs.
  • npm run dev starts the development server at http://localhost:5173, and hot module replacement applies saved changes instantly.
  • index.html holds one empty div; src/main.tsx creates a React root there and renders the App component from src/App.tsx into it.
  • A .tsx file is TypeScript that can contain JSX markup, and TypeScript infers types from values without annotations.
  • import and export are JavaScript module syntax, not React features.
  • StrictMode enables development-only checks and is best left in place.
  • Curly braces in JSX embed JavaScript values into the UI — change the data, and the UI follows.

Where to Go From Here?

You now have what every React developer starts the day with: an editor, a live development server and instant feedback. More importantly, you know what each link in the chain is for.

In the next chapter, you’ll build the Learning Tracker’s first real feature — a course card — and use it to answer the question that makes everything else click: Why does React exist at all?

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.