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:
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@latestwithout 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 installagain 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:
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 useddev. Thebuildscript type-checks your code and packages the app for production, andpreviewserves that production build locally — both stars of Chapter 17.lintruns 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
importandexportkeywords are JavaScript modules — a JavaScript feature, not a React one. Every file is a module:export default Appat the bottom of App.tsx offersAppto other files, andimport 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 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.
-
Appis a plain function that returns markup — amainlandmark 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 Apphands the component to src/main.tsx, exactly as before.
Save the file and look at the browser:
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:
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:
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:
- Change the rendered course title to a course you actually want to take — maybe “Modern TypeScript” or “CSS Animation”.
- 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 installreads package.json and fills node_modules, while package-lock.json records exact versions for repeatable installs. -
npm run devstarts the development server athttp://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 theAppcomponent from src/App.tsx into it. - A .tsx file is TypeScript that can contain JSX markup, and TypeScript infers types from values without annotations.
-
importandexportare JavaScript module syntax, not React features. -
StrictModeenables 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?