# How to Set Up a Vite React Project Manually: Complete Installation Guide

> Manually set up a Vite React project with this complete guide. Learn to install dependencies, configure Vite, and run your React app efficiently using npm run dev.

- Repository: [Vite/vite](https://github.com/vitejs/vite)
- Tags: getting-started
- Published: 2026-02-11

---

**To manually set up a Vite React project, initialize npm, install `react`, `react-dom`, `vite`, and `@vitejs/plugin-react`, create a [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js) file with the React plugin, add an [`index.html`](https://github.com/vitejs/vite/blob/main/index.html) entry point, write your React components in [`src/main.jsx`](https://github.com/vitejs/vite/blob/main/src/main.jsx), and run `npm run dev` after configuring the scripts in [`package.json`](https://github.com/vitejs/vite/blob/main/package.json).**

Setting up a Vite React project manually gives you complete control over your build configuration while leveraging Vite's lightning-fast Hot Module Replacement (HMR) and optimized production builds. Instead of using `create-vite` scaffolding, you can configure the exact dependencies and structure needed for your application by referencing the official templates in the `vitejs/vite` repository. This guide walks through the precise file structure, configuration options, and code required to bootstrap a React application with Vite from scratch, matching the implementation used in `packages/create-vite/template-react`.

## Initialize the Project Dependencies

### Create Project Directory and Initialize npm

Start by creating a clean workspace and generating a [`package.json`](https://github.com/vitejs/vite/blob/main/package.json) file that will manage your dependencies and scripts.

```bash
mkdir my-vite-react && cd my-vite-react
npm init -y

```

### Install React and Vite Dependencies

Add the core runtime libraries and development tools. React and ReactDOM power your application, while Vite serves as the development server and bundler.

```bash
npm i react react-dom
npm i -D vite @vitejs/plugin-react

```

**Why these matter:**

- `react` and `react-dom` provide the core React APIs and DOM rendering capabilities
- `vite` is the next-generation frontend tooling that handles module resolution and bundling
- `@vitejs/plugin-react` provides JSX/TSX transforms and **Fast Refresh** (HMR) specifically for React, as implemented in the official template

## Configure Vite for React

Create a **[`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js)** file at your project root. This configuration follows the canonical setup found in [`packages/create-vite/template-react/vite.config.js`](https://github.com/vitejs/vite/blob/main/packages/create-vite/template-react/vite.config.js) from the `vitejs/vite` repository.

```javascript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  // Optional: ensure React is treated as a singleton to avoid duplicate instances
  // resolve: { dedupe: ['react', 'react-dom'] },
});

```

**Key implementation details:**

- `defineConfig` provides type hints and ensures a clean configuration object shape
- The `react()` function registers the **@vitejs/plugin-react**, which internally handles JSX compilation and injects the Fast Refresh runtime for instantaneous component updates during development
- The optional `dedupe` configuration prevents multiple copies of React from appearing in your bundle when linking packages

## Create the Entry Files

Vite uses native ES modules and requires specific entry files to bootstrap your React application.

### HTML Entry Point

Create **[`index.html`](https://github.com/vitejs/vite/blob/main/index.html)** in the project root. Vite uses this as the application shell and automatically injects necessary scripts during development and production builds.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vite + React</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

```

**Critical details:**

- The script tag uses `type="module"` to enable native ES module loading
- The path [`/src/main.jsx`](https://github.com/vitejs/vite/blob/main//src/main.jsx) is resolved by Vite's dev server, matching the structure in [`packages/create-vite/template-react/index.html`](https://github.com/vitejs/vite/blob/main/packages/create-vite/template-react/index.html)

### React Application Entry

Create the **`src`** directory and add **[`main.jsx`](https://github.com/vitejs/vite/blob/main/main.jsx)**. This file bootstraps your React application using the modern React 18+ API.

```jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';

createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

**Implementation notes:**

- `createRoot` is the React 18+ API for concurrent features and improved hydration
- This matches the entry pattern found in [`packages/create-vite/template-react/src/main.jsx`](https://github.com/vitejs/vite/blob/main/packages/create-vite/template-react/src/main.jsx)
- **Fast Refresh** preserves component state when you edit files, provided by the plugin configured in [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js)

### Root Component

Create **[`src/App.jsx`](https://github.com/vitejs/vite/blob/main/src/App.jsx)** with a minimal component to verify your setup:

```jsx
export default function App() {
  return <h1>Hello Vite + React!</h1>;
}

```

## Add NPM Scripts and Run the Development Server

Edit **[`package.json`](https://github.com/vitejs/vite/blob/main/package.json)** to add the standard Vite command scripts used across all official templates:

```json
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

```

**Script purposes:**

- **`dev`**: Starts the Vite development server at `http://localhost:5173` (default) with Hot Module Replacement enabled
- **`build`**: Creates an optimized production bundle in the `dist/` directory using Rollup under the hood
- **`preview`**: Serves your production build locally to test the final output before deployment

Start your application:

```bash
npm run dev

```

Open `http://localhost:5173` in your browser. You will see "Hello Vite + React!" and can edit [`App.jsx`](https://github.com/vitejs/vite/blob/main/App.jsx) to see **Fast Refresh** update the page instantly without losing component state.

## Optional Enhancements for Production

### TypeScript Support

Rename your files to `.tsx` and install TypeScript definitions:

```bash
npm i -D typescript @types/react @types/react-dom

```

Vite automatically detects TypeScript configuration without additional plugins. Create a [`tsconfig.json`](https://github.com/vitejs/vite/blob/main/tsconfig.json) following the `packages/create-vite/template-react-ts` template for strict type checking.

### ESLint Configuration

Install the official React linting rules used in the Vite templates:

```bash
npm i -D eslint eslint-plugin-react-hooks eslint-plugin-react-refresh

```

Configure ESLint using an [`eslint.config.js`](https://github.com/vitejs/vite/blob/main/eslint.config.js) file that extends the recommended React and React Refresh rules found in [`packages/create-vite/template-react/eslint.config.js`](https://github.com/vitejs/vite/blob/main/packages/create-vite/template-react/eslint.config.js).

### Environment Variables

Create a `.env` file in your project root. Prefix variables with `VITE_` to expose them to your React code:

```bash
VITE_API_KEY=your_secret_key

```

Access these in your components via `import.meta.env.VITE_API_KEY`. Vite replaces these at build time, not runtime.

## Summary

- **Manual setup requires** `vite`, `@vitejs/plugin-react`, `react`, and `react-dom` installed via npm
- **Configuration happens** in [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js) using `defineConfig` and the `react()` plugin from `@vitejs/plugin-react`
- **Entry structure** needs an [`index.html`](https://github.com/vitejs/vite/blob/main/index.html) with a `type="module"` script pointing to [`src/main.jsx`](https://github.com/vitejs/vite/blob/main/src/main.jsx), which uses `createRoot` from `react-dom/client`
- **Development workflow** uses `npm run dev` for HMR, `npm run build` for production, and `npm run preview` for local testing
- **Code paths reference** the official `vitejs/vite` template files in `packages/create-vite/template-react/`

## Frequently Asked Questions

### Do I need to install `@vitejs/plugin-react-swc` instead of the standard React plugin?

The standard `@vitejs/plugin-react` uses Babel (or Oxc in newer Vite versions) for JSX transformation and provides Fast Refresh. **@vitejs/plugin-react-swc** is an alternative that uses the SWC compiler for significantly faster builds in large projects, but it requires separate installation (`npm i -D @vitejs/plugin-react-swc`) and different import syntax in [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js). For most applications starting out, the standard plugin provides the best compatibility.

### Why does my manual setup show a blank page when using `npm run dev`?

A blank page typically indicates that [`index.html`](https://github.com/vitejs/vite/blob/main/index.html) cannot find your React entry file. Verify that the script tag uses `type="module"` and that the path [`/src/main.jsx`](https://github.com/vitejs/vite/blob/main//src/main.jsx) matches your actual file location. Also ensure you have created the `src` directory and that [`main.jsx`](https://github.com/vitejs/vite/blob/main/main.jsx) properly imports `React` and calls `createRoot` on the `root` DOM element. Check the browser console for module resolution errors.

### How do I add path aliases like `@/` for imports in my manual Vite React setup?

Configure the `resolve.alias` option in [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js):

```javascript
import path from 'path';
export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
});

```

Then update your [`jsconfig.json`](https://github.com/vitejs/vite/blob/main/jsconfig.json) or [`tsconfig.json`](https://github.com/vitejs/vite/blob/main/tsconfig.json) to include matching paths configuration so your IDE recognizes the aliases.

### Can I use this manual setup for SSR (Server-Side Rendering) with React?

Yes, but you must follow the SSR guide in the Vite documentation ([`docs/guide/ssr.md`](https://github.com/vitejs/vite/blob/main/docs/guide/ssr.md)). You will need to create a server entry file (e.g., [`entry-server.jsx`](https://github.com/vitejs/vite/blob/main/entry-server.jsx)) and a client entry file, then configure your server to handle the SSR transform pipeline. The `@vitejs/plugin-react` supports SSR by default, but you must ensure your [`vite.config.js`](https://github.com/vitejs/vite/blob/main/vite.config.js) is loaded in both the server and client environments during the build process.