Setup
Fastest way to a working React + TypeScript project with Vite. From zero to dev server in under a minute.
Create the Project
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
Dev server runs at http://localhost:5173 with hot module replacement (HMR). Changes appear instantly without full page reloads.
Project Structure
my-app/
├── index.html # Entry HTML - Vite uses this as the entry point
├── package.json
├── tsconfig.json # TypeScript config
├── tsconfig.app.json # App-specific TS config (extends base)
├── vite.config.ts # Vite config
├── public/ # Static assets (copied as-is to build output)
│ └── vite.svg
└── src/
├── main.tsx # Entry point - renders App into #root
├── App.tsx # Root component
├── App.css # Component styles
├── index.css # Global styles
└── vite-env.d.ts # Vite type declarations
Key files to understand:
// src/main.tsx - the entry point
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./index.css";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>
);
Tip:
StrictModeruns your components twice in development to catch bugs (impure renders, missing cleanup). It does nothing in production. Leave it on.
// src/App.tsx - your root component
function App() {
return (
<main>
<h1>My App</h1>
</main>
);
}
export default App;
Add Tailwind CSS
npm install -D tailwindcss @tailwindcss/vite
Add the plugin to Vite config:
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
});
Replace src/index.css with:
@import "tailwindcss";
Test it works:
// src/App.tsx
function App() {
return (
<main className="min-h-screen bg-zinc-950 text-zinc-100 flex items-center justify-center">
<h1 className="text-4xl font-bold">It works</h1>
</main>
);
}
export default App;
Add Path Aliases
Avoid ../../.. import chains. Configure @/ to point to src/:
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import path from "path";
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
// tsconfig.app.json - add to compilerOptions
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Now you can import anywhere:
import { Button } from "@/components/Button";
import { useAuth } from "@/hooks/useAuth";
Recommended Project Layout
src/
├── components/ # Shared/reusable components
│ ├── ui/ # Primitives (Button, Input, Card)
│ └── layout/ # Layout components (Header, Sidebar)
├── hooks/ # Custom hooks
├── lib/ # Utility functions, API clients
├── types/ # TypeScript type definitions
├── pages/ # Page-level components (if using a router)
├── App.tsx
├── main.tsx
└── index.css
Add a Router (Optional)
For multi-page apps, add React Router:
npm install react-router
// src/App.tsx
import { BrowserRouter, Routes, Route } from "react-router";
import { Home } from "@/pages/Home";
import { About } from "@/pages/About";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Build for Production
npm run build # Output in dist/
npm run preview # Preview production build locally
Vite produces optimized, code-split bundles. The output is static HTML/CSS/JS that can be deployed to any static host (Vercel, Netlify, Cloudflare Pages, S3).
ESLint Setup
Vite’s template includes a basic ESLint config. Upgrade it for better React support:
npm install -D eslint-plugin-react-hooks eslint-plugin-react-refresh
The React hooks plugin catches:
- Hooks called inside conditions or loops
- Missing dependencies in
useEffect - Non-hook functions named with
useprefix
Tip: If you enable React Compiler later, its ESLint plugin replaces the hooks plugin for dependency validation. See React Compiler.
Dev Server Features
Vite’s dev server gives you:
- HMR - component changes reflect instantly, state is preserved
- Fast startup - no bundling on start, uses native ES modules
- TypeScript - type-checked by your editor, transpiled (not checked) by Vite for speed
- Error overlay - compile errors show in the browser
Gotcha: Vite transpiles TypeScript but doesn’t type-check it. Type errors won’t stop the dev server. Run
tsc --noEmitseparately (or rely on your editor) for type checking.
Next: First App to build something real