Set Up a React App with Vite
A practical walkthrough for creating your first React 19 project with Vite — installing Node.js, scaffolding the app, understanding the file layout, and running the dev server.
What you'll learn
- ✓How to install Node.js the right way in 2026
- ✓How to scaffold a React 19 project with Vite
- ✓What every file in a fresh React project actually does
- ✓How the dev server, hot reload, and production build work
- ✓Why Create React App is deprecated and what to use instead
Prerequisites
- •A first reading of What is React?
- •Comfort with the terminal and JavaScript basics
This post takes you from a blank computer to a running React 19 application in roughly ten minutes. We use Vite, the modern toolchain that has effectively replaced Create React App across the React ecosystem.
Why Vite instead of Create React App
For most of the 2010s, the official way to start a React project was npx create-react-app. As of 2023 the React team officially deprecated Create React App and now recommends a real framework such as Next.js or a build tool such as Vite.
Vite has three advantages that matter on day one:
- Cold-start in under a second — Vite serves modules natively rather than bundling the whole app on startup
- Instant hot module reload — saving a file updates the page in tens of milliseconds
- A modern, minimal config — no ejecting, no webpack to understand
If you are reading an older tutorial that opens with npx create-react-app, mentally substitute the Vite commands below. The React code is identical either way.
Step 1: Install Node.js
React’s tooling runs on Node.js. You need Node 20 or newer — Node 22 is the current LTS as of 2026.
Check whether you already have it:
node --version
If you see v20.x.x or higher, skip to step 2. Otherwise install Node from one of these:
- macOS / Linux — the cleanest option is a version manager like
fnmornvm. They let you switch versions per project. - Windows — download the LTS installer from nodejs.org.
Once installed, verify both Node and npm are available:
node --version # v22.x.x
npm --version # 10.x.x
npm is the package manager bundled with Node. You can also use pnpm or Bun if you prefer — every command in this post works with those too.
Step 2: Create a React project with Vite
Pick a directory where you keep code, then run:
npm create vite@latest my-react-app
Vite asks two questions. Answer them as follows:
? Select a framework: › React
? Select a variant: › JavaScript
We use JavaScript for the rest of this series. TypeScript is excellent, and we cover it later — adding it now would distract from the React concepts themselves.
Vite scaffolds the project. Finish the setup:
cd my-react-app
npm install
npm run dev
Open the URL it prints — usually http://localhost:5173. You should see a Vite + React starter page with a counter. Click the counter to confirm interactivity is working.
That is a complete, modern React 19 project running on your machine.
Step 3: Tour the project
Open the project in your editor. The file tree looks like this:
my-react-app/
├── node_modules/
├── public/
│ └── vite.svg
├── src/
│ ├── assets/
│ │ └── react.svg
│ ├── App.css
│ ├── App.jsx
│ ├── index.css
│ └── main.jsx
├── .gitignore
├── index.html
├── package.json
├── vite.config.js
└── README.md
A short explanation of every file you will touch.
index.html
The single HTML file the browser actually loads. The important line:
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
This is the mount point. React renders your entire app into the #root div.
src/main.jsx
The entry point that boots React.
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
Three things worth noticing:
createRootis the React 18+ way to mount an app. The olderReactDOM.renderis gone.StrictModeis a development-only wrapper that highlights potential problems. Leave it in.<App />is the root component — everything you build lives below it.
src/App.jsx
Your first component. Open it and replace the contents with something minimal:
function App() {
return (
<div>
<h1>My React App</h1>
<p>This is rendered by React 19.</p>
</div>
);
}
export default App;
Save the file. The browser updates instantly — that is hot module reload in action. You will rely on this feedback loop for the rest of your React life.
src/index.css and App.css
Plain CSS. Vite imports them directly. You can keep them, replace them with Tailwind later, or delete them entirely.
package.json
The project manifest. The scripts section is what matters:
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
}
npm run dev— the development server you are already runningnpm run build— produces a production bundle indist/npm run preview— serves the production build locally so you can verify it
vite.config.js
Vite’s configuration. The default ships with the React plugin and almost nothing else, which is the point.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});
You will not need to edit this for a while.
Try it yourself. With the dev server running, open src/App.jsx and change the heading text. Save. Watch the browser update without a reload. Now introduce a deliberate syntax error — leave a tag unclosed. Vite displays a clear error overlay. Fix it, save, and the overlay disappears. This is the loop you want to internalise.
Step 4: Build for production
When you eventually want to deploy:
npm run build
Vite writes a static production bundle to dist/. To preview it locally:
npm run preview
The dist/ folder is what you upload to a host like Netlify, Vercel, or Cloudflare Pages. Deployment is outside the scope of this post, but it is essentially “drag the dist/ folder in.” Most hosts also integrate with GitHub for automatic deploys.
A first real edit
Let’s confirm everything is wired up by writing a tiny stateful component. Replace src/App.jsx with this:
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<main style={{ fontFamily: 'system-ui', padding: '2rem' }}>
<h1>Vite + React 19</h1>
<p>You clicked {count} times.</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</main>
);
}
export default App;
Save. Click the button in the browser. The count increments. You just used your first hook — useState — and you are now writing real React.
We will not dwell on what useState does mechanically here. Post 5 covers it in depth.
Try it yourself. Add a second button labelled Reset that sets count back to 0. Confirm both buttons work independently. If you can do this from memory after one read of the code above, you are ready for the next post.
Things that commonly trip people up
A short checklist for when something is not working.
npm: command not found— Node was not installed correctly. Restart the terminal first.- Port already in use — Vite picks
5174,5175, etc. automatically. Use the URL it prints. - Blank page, no error — open the browser’s DevTools console. React errors always appear there.
Cannot use import statement outside a module— you are running a.jsxfile directly with Node. Usenpm run dev; do not callnodeon a React file.- Hot reload not updating — confirm you are editing inside
src/. Files outsidesrc/are not watched.
Useful editor setup
Two extensions in VS Code are worth installing on day one:
- ESLint — surfaces problems as you type. Vite’s template ships with a working ESLint config.
- Prettier — formats your code on save. Pairs well with ESLint.
Optionally, install React DevTools for Chrome or Firefox. It adds two tabs to DevTools — Components and Profiler — that show your component tree, props, and state. It is the single most useful debugging tool in React.
Recap
You now have:
- Node.js installed and verified at version 20+
- A fresh React 19 project scaffolded with Vite
- An understanding of
index.html,main.jsx, andApp.jsx - A working dev server with hot module reload
- A production build command that produces a deployable
dist/folder - A first stateful component using
useState
Next steps
The next post zooms into the unit you will spend most of your React life writing: the component. We cover JSX rules, the difference between elements and components, the conventions that production codebases follow, and how to compose components into trees.
→ Next: React Components and JSX Explained
Questions or feedback? Email codeloomdevv@gmail.com.