Full-project lesson · needs Node.js, npm and real project files, so it does not run in the in-page playground.
A new project has only a handful of files. Knowing what each one does makes everything else easier. This is the structure created by the Vite React template (create-vite 9):
my-app/
├── index.html
├── package.json
├── package-lock.json
├── vite.config.js
├── .oxlintrc.json
├── .gitignore
├── README.md
├── public/
│ ├── favicon.svg
│ └── icons.svg
└── src/
├── main.jsx
├── App.jsx
├── App.css
├── index.css
└── assets/
├── hero.png
├── react.svg
└── vite.svg
After npm install there is also a node_modules/ folder with all packages. It is large, it is recreated by npm install, and it is never committed to Git.
index.html
This is the only HTML page of your app. Vite uses it as the entry point.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>myapp</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Two lines matter most:
<div id="root"></div>is an empty box. React will draw your whole app inside it.<script type="module" src="/src/main.jsx">loads your JavaScript, starting withsrc/main.jsx.
Change the <title> to your app’s name, and edit the head for fonts or meta tags. This file is also where an SEO title and description go in a client-side app.
src/main.jsx
The entry point of your JavaScript. It starts 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>,
)
It finds the root element, creates a React root and renders <App /> inside it. Rendering React Components explains this file line by line. You rarely edit it, except to add global providers or a router.
src/App.jsx
Your first component and the top of your component tree. The template fills it with a demo page. You will replace its contents with your own.
src/index.css and src/App.css
index.css holds global styles (variables, resets, fonts) and is imported in main.jsx. App.css holds styles for App and is imported in App.jsx. Importing a CSS file from JavaScript is something Vite supports. It is not plain browser behaviour.
src/assets/ and public/
Both hold static files, but they work differently:
| Folder | How you use it | When |
|---|---|---|
src/assets/ | import logo from './assets/react.svg' and use logo as the src | Files you import in code. Vite fingerprints the file name for caching. |
public/ | Refer to it by an absolute path, such as /favicon.svg | Files that must keep their exact name and be served as they are, such as robots.txt or favicons. |
vite.config.js
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})
This turns on the React plugin. You will edit it later to set a base path for deployment or a dev-server proxy.
package.json, .oxlintrc.json, .gitignore
package.jsonlists dependencies and scripts. See Understanding package.json..oxlintrc.jsonconfigures Oxlint, a fast linter. The template turns on a rule that catches mistakes with hooks..gitignoretells Git not to tracknode_modules,dist(the build output) and log files.
Make it your own: clear the demo
The demo page is useful once, then it gets in the way. Replace the contents of src/App.jsx with a minimal component:
function App() {
return (
<main>
<h1>My React App</h1>
<p>This text comes from a component.</p>
</main>
)
}
export default App
Save the file and look at the browser. The page updates without a reload. You can delete src/App.css and the imports of the unused images, or keep them for reference.
Where to put new files
src/components/, one file per component. Larger projects organise by feature; see Feature-Based Project Structure.Key points
index.htmlhas therootelement;src/main.jsxstarts React;src/App.jsxis your top component.src/assetsis for files you import;publicis for files served exactly as they are.vite.config.jsconfigures Vite and the React plugin.