JavaScript and React course Β· Module 1: React Basics

React project structure

13 min read
In this lesson8

A well-organized project structure is crucial for code maintainability, easy navigation, and scalability of React applications. In this lesson, we'll look at best practices for structuring React projects and understand how to organize files and components.

Basic React project structure

Whatever the tool, a larger React project (here a Vite one) usually has a similar structure:

1my-react-project/
2β”œβ”€β”€ node_modules/        # Installed dependencies
3β”œβ”€β”€ public/              # Publicly accessible static files
4β”œβ”€β”€ src/                 # Application source code
5β”‚   β”œβ”€β”€ components/      # Reusable components
6β”‚   β”œβ”€β”€ pages/           # Components representing entire pages
7β”‚   β”œβ”€β”€ assets/          # Assets such as images, fonts, etc.
8β”‚   β”œβ”€β”€ utils/           # Utility functions
9β”‚   β”œβ”€β”€ services/        # Code responsible for API communication
10β”‚   β”œβ”€β”€ hooks/           # Custom React hooks
11β”‚   β”œβ”€β”€ context/         # React contexts
12β”‚   β”œβ”€β”€ App.jsx          # Main application component
13β”‚   └── main.jsx         # Application entry point
14β”œβ”€β”€ index.html           # The HTML page the app is loaded into
15β”œβ”€β”€ vite.config.js       # Vite configuration
16β”œβ”€β”€ .gitignore           # Files ignored by Git
17β”œβ”€β”€ package.json         # Project info and dependencies
18└── README.md            # Project documentation

Let's discuss the most important directories and their purposes:

The src/ directory

The src/ directory is the heart of your React application. It contains all the logic, components, and assets. Here's how this directory is typically organized:

components/

Contains reusable components that are used in various parts of the application. There are several approaches to structuring components:

Flat structure

1components/
2β”œβ”€β”€ Button.jsx
3β”œβ”€β”€ Button.css
4β”œβ”€β”€ Header.jsx
5β”œβ”€β”€ Header.css
6β”œβ”€β”€ Footer.jsx
7└── Footer.css

Grouped structure (preferred for larger projects)

1components/
2β”œβ”€β”€ Button/
3β”‚   β”œβ”€β”€ Button.jsx
4β”‚   β”œβ”€β”€ Button.css
5β”‚   └── index.js
6β”œβ”€β”€ Header/
7β”‚   β”œβ”€β”€ Header.jsx
8β”‚   β”œβ”€β”€ Header.css
9β”‚   └── index.js
10└── Footer/
11    β”œβ”€β”€ Footer.jsx
12    β”œβ”€β”€ Footer.css
13    └── index.js

Using index.js files to export components simplifies imports:

1// Instead of:
2import Button from './components/Button/Button';
3
4// You can write:
5import Button from './components/Button';

pages/

Components representing entire pages or views in the application. In projects with routing, each file in this directory typically corresponds to a specific URL path:

1pages/
2β”œβ”€β”€ Home/
3β”‚   β”œβ”€β”€ Home.jsx
4β”‚   └── Home.css
5β”œβ”€β”€ About/
6β”‚   β”œβ”€β”€ About.jsx
7β”‚   └── About.css
8└── Dashboard/
9    β”œβ”€β”€ Dashboard.jsx
10    └── Dashboard.css

assets/

Contains all static assets used in the application:

1assets/
2β”œβ”€β”€ images/
3β”‚   β”œβ”€β”€ logo.png
4β”‚   └── background.jpg
5β”œβ”€β”€ fonts/
6β”‚   β”œβ”€β”€ roboto.ttf
7β”‚   └── open-sans.ttf
8└── styles/
9    β”œβ”€β”€ variables.css
10    └── global.css

utils/

Utility functions and tools used throughout the application:

1utils/
2β”œβ”€β”€ formatDate.js
3β”œβ”€β”€ validation.js
4└── helpers.js

services/

Code responsible for communicating with external APIs or services:

1services/
2β”œβ”€β”€ api.js           # Basic API configuration
3β”œβ”€β”€ userService.js   # User-related queries
4└── productService.js # Product-related queries

hooks/

Custom React hooks that can be used in multiple places in the application:

1hooks/
2β”œβ”€β”€ useLocalStorage.js
3β”œβ”€β”€ useFetch.js
4└── useForm.js

context/

React contexts used for managing global state:

1context/
2β”œβ”€β”€ AuthContext.js
3β”œβ”€β”€ ThemeContext.js
4└── CartContext.js

Organization by feature vs. by type

There are two main approaches to code organization:

Organization by type (shown above)

Files are grouped by their type (components, hooks, services, etc.).

Organization by feature

Files are grouped by feature or part of the application:

1src/
2β”œβ”€β”€ auth/
3β”‚   β”œβ”€β”€ components/
4β”‚   β”œβ”€β”€ hooks/
5β”‚   β”œβ”€β”€ services/
6β”‚   └── context/
7β”œβ”€β”€ products/
8β”‚   β”œβ”€β”€ components/
9β”‚   β”œβ”€β”€ hooks/
10β”‚   β”œβ”€β”€ services/
11β”‚   └── utils/
12└── checkout/
13    β”œβ”€β”€ components/
14    β”œβ”€β”€ hooks/
15    └── services/

This structure is more scalable for large projects, especially when multiple people are working on them.

Naming conventions

Consistent naming is just as important as directory structure:

Components

  • Use PascalCase: Button.jsx, UserProfile.jsx
  • JSX files should have the .jsx extension (not required, but helps with identification)

Hooks

  • Always start with "use": useLocalStorage.js, useWindowSize.js

Contexts

  • Usually end with "Context": AuthContext.js, ThemeContext.js

Services and utilities

  • Use camelCase: apiService.js, formatDate.js

Styles in React

There are several approaches to organizing styles in React:

CSS Modules

1Button/
2β”œβ”€β”€ Button.jsx
3└── Button.module.css

Styled Components

1Button/
2└── Button.jsx  # Contains styled-components definitions

SCSS/SASS

1Button/
2β”œβ”€β”€ Button.jsx
3└── Button.scss

Folder structure best practices

In the React cosmic fleet, a well-organized folder structure is like an efficient logistics system on a spaceship - everything has its place and you can quickly find what you need. Here are proven practices for organizing React projects.

Feature-based vs Type-based organization

Two main approaches to organizing code in React projects:

Type-based organization

Files grouped by their technical role - all components together, all hooks together, etc.

1src/
2β”œβ”€β”€ components/
3β”‚   β”œβ”€β”€ Button/
4β”‚   β”œβ”€β”€ Card/
5β”‚   β”œβ”€β”€ Modal/
6β”‚   β”œβ”€β”€ UserProfile/
7β”‚   β”œβ”€β”€ ProductCard/
8β”‚   └── ShoppingCart/
9β”œβ”€β”€ hooks/
10β”‚   β”œβ”€β”€ useAuth.js
11β”‚   β”œβ”€β”€ useProducts.js
12β”‚   └── useCart.js
13β”œβ”€β”€ services/
14β”‚   β”œβ”€β”€ authService.js
15β”‚   β”œβ”€β”€ productService.js
16β”‚   └── cartService.js
17└── utils/
18    β”œβ”€β”€ validators.js
19    └── formatters.js

Advantages:

  • Simpler for small and medium projects
  • Easy to understand for new developers
  • Good for SPA applications without distinct modules

Disadvantages:

  • In large projects, it's hard to find all files related to a single feature
  • Components from different features are mixed together
  • Harder to scale across teams

Feature-based organization

Files grouped by business feature - all files related to authentication together, all product-related files together, etc.

1src/
2β”œβ”€β”€ features/
3β”‚   β”œβ”€β”€ auth/
4β”‚   β”‚   β”œβ”€β”€ components/
5β”‚   β”‚   β”‚   β”œβ”€β”€ LoginForm/
6β”‚   β”‚   β”‚   β”œβ”€β”€ RegisterForm/
7β”‚   β”‚   β”‚   └── PasswordReset/
8β”‚   β”‚   β”œβ”€β”€ hooks/
9β”‚   β”‚   β”‚   β”œβ”€β”€ useAuth.js
10β”‚   β”‚   β”‚   └── useSession.js
11β”‚   β”‚   β”œβ”€β”€ services/
12β”‚   β”‚   β”‚   └── authService.js
13β”‚   β”‚   β”œβ”€β”€ utils/
14β”‚   β”‚   β”‚   └── validators.js
15β”‚   β”‚   └── index.js
16β”‚   β”‚
17β”‚   β”œβ”€β”€ products/
18β”‚   β”‚   β”œβ”€β”€ components/
19β”‚   β”‚   β”‚   β”œβ”€β”€ ProductList/
20β”‚   β”‚   β”‚   β”œβ”€β”€ ProductCard/
21β”‚   β”‚   β”‚   └── ProductDetails/
22β”‚   β”‚   β”œβ”€β”€ hooks/
23β”‚   β”‚   β”‚   β”œβ”€β”€ useProducts.js
24β”‚   β”‚   β”‚   └── useProductFilters.js
25β”‚   β”‚   β”œβ”€β”€ services/
26β”‚   β”‚   β”‚   └── productService.js
27β”‚   β”‚   └── index.js
28β”‚   β”‚
29β”‚   └── cart/
30β”‚       β”œβ”€β”€ components/
31β”‚       β”‚   β”œβ”€β”€ ShoppingCart/
32β”‚       β”‚   β”œβ”€β”€ CartItem/
33β”‚       β”‚   └── Checkout/
34β”‚       β”œβ”€β”€ hooks/
35β”‚       β”‚   └── useCart.js
36β”‚       β”œβ”€β”€ services/
37β”‚       β”‚   └── cartService.js
38β”‚       └── index.js
39β”‚
40β”œβ”€β”€ shared/
41β”‚   β”œβ”€β”€ components/
42β”‚   β”‚   β”œβ”€β”€ Button/
43β”‚   β”‚   β”œβ”€β”€ Modal/
44β”‚   β”‚   └── Card/
45β”‚   β”œβ”€β”€ hooks/
46β”‚   β”‚   β”œβ”€β”€ useLocalStorage.js
47β”‚   β”‚   └── useDebounce.js
48β”‚   └── utils/
49β”‚       β”œβ”€β”€ formatDate.js
50β”‚       └── formatCurrency.js
51β”‚
52└── App.jsx

Advantages:

  • Easier to scale for large projects
  • All files related to a feature are in one place
  • Easier for team work (different teams can work on different features)
  • Easier to remove entire features
  • Better for code splitting

Disadvantages:

  • More complex for beginners
  • Requires more thought in design
  • Can lead to duplication for very small components

Naming conventions

Consistent naming is a key element of a well-organized project. In React, the following conventions apply:

Components - PascalCase

1// GOOD - PascalCase
2Button.jsx
3UserProfile.jsx
4ShoppingCart.jsx
5ProductCard.jsx
6
7// BAD - other conventions
8button.jsx
9user-profile.jsx
10shopping_cart.jsx

Why PascalCase?

  • Distinguishes React components from regular functions
  • Convention adopted across the entire React ecosystem
  • JSX requires PascalCase for components (custom tags)

Hooks - camelCase with "use" prefix

1// GOOD - camelCase with "use"
2useAuth.js
3useLocalStorage.js
4useWindowSize.js
5useProductFilters.js
6
7// BAD - missing "use" or wrong convention
8Auth.js
9local-storage.js
10WindowSize.js

Why "use" prefix?

  • React requires custom hooks to start with "use"
  • Allows React to validate hook rules
  • Immediately communicates that it's a hook

Contexts - PascalCase with "Context" suffix

1// GOOD - PascalCase with "Context"
2AuthContext.js
3ThemeContext.js
4CartContext.js
5UserPreferencesContext.js
6
7// BAD - missing "Context" or wrong convention
8auth.js
9theme-context.js
10Cart.js

Utils and services - camelCase

1// GOOD - camelCase
2formatDate.js
3validateEmail.js
4apiService.js
5authService.js
6
7// BAD - other conventions
8FormatDate.js
9validate-email.js
10API_Service.js

Where to keep different file types

Planning file locations in a project has enormous significance for its readability and scalability.

Hooks (custom hooks)

Feature-based approach:

1features/
2β”œβ”€β”€ auth/
3β”‚   └── hooks/
4β”‚       β”œβ”€β”€ useAuth.js
5β”‚       └── useSession.js
6└── products/
7    └── hooks/
8        └── useProducts.js
9
10shared/
11└── hooks/
12    β”œβ”€β”€ useLocalStorage.js  # Shared hook
13    β”œβ”€β”€ useDebounce.js      # Shared hook
14    └── useFetch.js         # Shared hook

Type-based approach:

1hooks/
2β”œβ”€β”€ useAuth.js
3β”œβ”€β”€ useSession.js
4β”œβ”€β”€ useProducts.js
5β”œβ”€β”€ useLocalStorage.js
6β”œβ”€β”€ useDebounce.js
7└── useFetch.js

Utils (utility functions)

Feature-based approach:

1features/
2β”œβ”€β”€ products/
3β”‚   └── utils/
4β”‚       β”œβ”€β”€ formatPrice.js
5β”‚       └── filterProducts.js
6└── auth/
7    └── utils/
8        └── validatePassword.js
9
10shared/
11└── utils/
12    β”œβ”€β”€ formatDate.js       # Shared
13    β”œβ”€β”€ debounce.js         # Shared
14    └── cloneDeep.js        # Shared

Type-based approach:

1utils/
2β”œβ”€β”€ formatPrice.js
3β”œβ”€β”€ formatDate.js
4β”œβ”€β”€ validatePassword.js
5β”œβ”€β”€ filterProducts.js
6β”œβ”€β”€ debounce.js
7└── cloneDeep.js

Types (TypeScript)

If you use TypeScript, you have several options for types:

Option 1: Next to the files that use them:

1components/
2└── Button/
3    β”œβ”€β”€ Button.tsx
4    β”œβ”€β”€ Button.types.ts     # Types only for Button
5    β”œβ”€β”€ Button.styles.ts
6    └── index.ts

Option 2: Centralized types:

1types/
2β”œβ”€β”€ user.types.ts
3β”œβ”€β”€ product.types.ts
4β”œβ”€β”€ cart.types.ts
5└── api.types.ts

Option 3: Hybrid (best):

1features/
2└── products/
3    β”œβ”€β”€ components/
4    β”œβ”€β”€ types/              # Feature-specific types
5    β”‚   β”œβ”€β”€ product.types.ts
6    β”‚   └── filter.types.ts
7    └── index.ts
8
9shared/
10└── types/                  # Shared types
11    β”œβ”€β”€ common.types.ts
12    └── api.types.ts

Example project structure - best practices

Combining feature-based for main features and type-based for shared resources:

1my-react-app/
2β”œβ”€β”€ public/
3β”œβ”€β”€ src/
4β”‚   β”œβ”€β”€ features/                    # Main features
5β”‚   β”‚   β”œβ”€β”€ auth/
6β”‚   β”‚   β”‚   β”œβ”€β”€ components/
7β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ LoginForm/
8β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ LoginForm.tsx
9β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ LoginForm.styles.ts
10β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ LoginForm.test.tsx
11β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
12β”‚   β”‚   β”‚   β”‚   └── RegisterForm/
13β”‚   β”‚   β”‚   β”œβ”€β”€ hooks/
14β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ useAuth.ts
15β”‚   β”‚   β”‚   β”‚   └── useSession.ts
16β”‚   β”‚   β”‚   β”œβ”€β”€ services/
17β”‚   β”‚   β”‚   β”‚   └── authService.ts
18β”‚   β”‚   β”‚   β”œβ”€β”€ types/
19β”‚   β”‚   β”‚   β”‚   └── auth.types.ts
20β”‚   β”‚   β”‚   └── index.ts
21β”‚   β”‚   β”‚
22β”‚   β”‚   β”œβ”€β”€ products/
23β”‚   β”‚   β”‚   β”œβ”€β”€ components/
24β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ProductList/
25β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ProductCard/
26β”‚   β”‚   β”‚   β”‚   └── ProductFilters/
27β”‚   β”‚   β”‚   β”œβ”€β”€ hooks/
28β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ useProducts.ts
29β”‚   β”‚   β”‚   β”‚   └── useProductFilters.ts
30β”‚   β”‚   β”‚   β”œβ”€β”€ services/
31β”‚   β”‚   β”‚   β”‚   └── productService.ts
32β”‚   β”‚   β”‚   β”œβ”€β”€ types/
33β”‚   β”‚   β”‚   β”‚   └── product.types.ts
34β”‚   β”‚   β”‚   └── index.ts
35β”‚   β”‚   β”‚
36β”‚   β”‚   └── cart/
37β”‚   β”‚       └── [similar structure]
38β”‚   β”‚
39β”‚   β”œβ”€β”€ shared/                      # Shared resources
40β”‚   β”‚   β”œβ”€β”€ components/
41β”‚   β”‚   β”‚   β”œβ”€β”€ Button/
42β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Button.tsx
43β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Button.styles.ts
44β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Button.test.tsx
45β”‚   β”‚   β”‚   β”‚   └── index.ts
46β”‚   β”‚   β”‚   β”œβ”€β”€ Modal/
47β”‚   β”‚   β”‚   β”œβ”€β”€ Card/
48β”‚   β”‚   β”‚   └── Layout/
49β”‚   β”‚   β”‚
50β”‚   β”‚   β”œβ”€β”€ hooks/
51β”‚   β”‚   β”‚   β”œβ”€β”€ useLocalStorage.ts
52β”‚   β”‚   β”‚   β”œβ”€β”€ useDebounce.ts
53β”‚   β”‚   β”‚   └── useFetch.ts
54β”‚   β”‚   β”‚
55β”‚   β”‚   β”œβ”€β”€ utils/
56β”‚   β”‚   β”‚   β”œβ”€β”€ formatDate.ts
57β”‚   β”‚   β”‚   β”œβ”€β”€ validators.ts
58β”‚   β”‚   β”‚   └── helpers.ts
59β”‚   β”‚   β”‚
60β”‚   β”‚   β”œβ”€β”€ types/
61β”‚   β”‚   β”‚   β”œβ”€β”€ common.types.ts
62β”‚   β”‚   β”‚   └── api.types.ts
63β”‚   β”‚   β”‚
64β”‚   β”‚   └── constants/
65β”‚   β”‚       β”œβ”€β”€ routes.ts
66β”‚   β”‚       └── config.ts
67β”‚   β”‚
68β”‚   β”œβ”€β”€ layouts/                     # Layout components
69β”‚   β”‚   β”œβ”€β”€ MainLayout/
70β”‚   β”‚   β”œβ”€β”€ AuthLayout/
71β”‚   β”‚   └── DashboardLayout/
72β”‚   β”‚
73β”‚   β”œβ”€β”€ pages/                       # Page components (for routing)
74β”‚   β”‚   β”œβ”€β”€ HomePage/
75β”‚   β”‚   β”œβ”€β”€ ProductsPage/
76β”‚   β”‚   β”œβ”€β”€ ProductDetailPage/
77β”‚   β”‚   └── CartPage/
78β”‚   β”‚
79β”‚   β”œβ”€β”€ context/                     # Global contexts
80β”‚   β”‚   β”œβ”€β”€ AuthContext.tsx
81β”‚   β”‚   β”œβ”€β”€ ThemeContext.tsx
82β”‚   β”‚   └── CartContext.tsx
83β”‚   β”‚
84β”‚   β”œβ”€β”€ router/                      # Routing configuration
85β”‚   β”‚   β”œβ”€β”€ routes.tsx
86β”‚   β”‚   └── ProtectedRoute.tsx
87β”‚   β”‚
88β”‚   β”œβ”€β”€ styles/                      # Global styles
89β”‚   β”‚   β”œβ”€β”€ globals.css
90β”‚   β”‚   β”œβ”€β”€ variables.css
91β”‚   β”‚   └── reset.css
92β”‚   β”‚
93β”‚   β”œβ”€β”€ App.tsx
94β”‚   └── index.tsx
95β”‚
96β”œβ”€β”€ .eslintrc.js
97β”œβ”€β”€ .prettierrc
98β”œβ”€β”€ tsconfig.json
99β”œβ”€β”€ package.json
100└── README.md

File organization rules

  1. Maximum 3 levels rule
    • Avoid nesting deeper than 3 levels
    • If you need more, your structure is probably too complex
1// GOOD - 3 levels
2src/features/products/components/
3
4// BAD - too deep
5src/modules/ecommerce/features/products/ui/components/
  1. Export through index.ts
    • Every folder with a component has an index.ts
    • Simplifies imports and hides implementation details
1// components/Button/index.ts
2export { default } from './Button';
3export * from './Button.types';
4
5// Usage
6import Button from './components/Button';  // readable
7// instead of
8import Button from './components/Button/Button';  // verbose
  1. Colocation - keep together what is used together
    • Styles next to the component
    • Tests next to the component
    • Types next to the component
1Button/
2β”œβ”€β”€ Button.tsx          # Component
3β”œβ”€β”€ Button.styles.ts    # Styles
4β”œβ”€β”€ Button.test.tsx     # Tests
5β”œβ”€β”€ Button.types.ts     # Types
6└── index.ts            # Export
  1. Shared vs Feature-specific
    • If something is used in more than 2 places -> shared
    • If something is specific to a feature -> keep it in the feature

Practical tips for project structure

  1. Start simple - Don't over-engineer a complex structure at the beginning of a project. For a small application, type-based may suffice; only later refactor to feature-based as the project grows.

  2. Refactor when needed - Adapt the structure as the project develops. If a folder has more than 10-15 files, consider splitting it.

  3. Keep components small - Components should be small and focused on a single task. If a component has more than 200-300 lines, consider splitting it.

  4. Group related files - Keep files that are closely related together. If you always edit two files together, they should probably be in the same folder.

  5. Document - Add README.md to main directories to explain their purpose and structure.

  6. Consistency above all - Once you choose a layout (by type, by feature, or the hybrid described above), stick to it throughout the project. The worst thing is mixing styles at random.

Tools that help with code organization

  1. ESLint - Helps maintain consistent code style and catch potential errors
  2. Prettier - Automatically formats code according to established rules
  3. Import sorter - Sorts imports for better readability
  4. Path aliases - Simplifies imports using aliases like @components, @utils
1// tsconfig.json or jsconfig.json
2{
3  "compilerOptions": {
4    "baseUrl": "src",
5    "paths": {
6      "@components/*": ["shared/components/*"],
7      "@features/*": ["features/*"],
8      "@utils/*": ["shared/utils/*"],
9      "@hooks/*": ["shared/hooks/*"]
10    }
11  }
12}
13
14// Usage
15import Button from '@components/Button';
16import { useAuth } from '@features/auth';
17import { formatDate } from '@utils/formatDate';

A well-organized project structure greatly facilitates work, especially in large teams and projects. Remember that there is no single "right" structure - the most important thing is that it is consistent, logical for your team, and scalable as the project grows.

Code for this lesson: App.jsx
1import React, { useState } from 'react';
2
3// Demonstration of Vite + React project structure
4function ViteProjectDemo() {
5  const [activeFile, setActiveFile] = useState('App.jsx');
6
7  const fileStructure = [
8    { name: 'node_modules/', type: 'folder', description: 'Installed packages' },
9    { name: 'public/', type: 'folder', description: 'Static files' },
10    { name: '  vite.svg', type: 'file', description: 'Vite logo' },
11    { name: 'src/', type: 'folder', description: 'Source code' },
12    { name: '  assets/', type: 'folder', description: 'Assets (images, fonts)' },
13    { name: '  App.jsx', type: 'file', description: 'Main component', active: true },
14    { name: '  App.css', type: 'file', description: 'Component styles' },
15    { name: '  main.jsx', type: 'file', description: 'Entry point' },
16    { name: '  index.css', type: 'file', description: 'Global styles' },
17    { name: 'index.html', type: 'file', description: 'Main HTML (in the root directory!)' },
18    { name: 'vite.config.js', type: 'file', description: 'Vite configuration' },
19    { name: 'package.json', type: 'file', description: 'Project configuration' },
20  ];
21
22  const fileContents = {
23    'App.jsx': `import { useState } from 'react'
24import './App.css'
25
26function App() {
27  const [count, setCount] = useState(0)
28
29  return (
30    <>
31      <h1>Vite + React</h1>
32      <div className="card">
33        <button onClick={() => setCount(c => c + 1)}>
34          count is {count}
35        </button>
36      </div>
37    </>
38  )
39}
40
41export default App`,
42    'main.jsx': `import React from 'react'
43import ReactDOM from 'react-dom/client'
44import App from './App.jsx'
45import './index.css'
46
47ReactDOM.createRoot(
48  document.getElementById('root')
49).render(
50  <React.StrictMode>
51    <App />
52  </React.StrictMode>,
53)`,
54    'vite.config.js': `import { defineConfig } from 'vite'
55import react from '@vitejs/plugin-react'
56
57export default defineConfig({
58  plugins: [react()],
59})`,
60    'package.json': `{
61  "name": "my-app",
62  "version": "0.0.0",
63  "type": "module",
64  "scripts": {
65    "dev": "vite",
66    "build": "vite build",
67    "preview": "vite preview"
68  },
69  "dependencies": {
70    "react": "^18.2.0",
71    "react-dom": "^18.2.0"
72  },
73  "devDependencies": {
74    "@vitejs/plugin-react": "^4.2.0",
75    "vite": "^5.0.0"
76  }
77}`
78  };
79
80  return (
81    <div style={{
82      fontFamily: 'Arial, sans-serif',
83      maxWidth: '1000px',
84      margin: '0 auto',
85      padding: '20px'
86    }}>
87      <header style={{
88        background: 'linear-gradient(135deg, #61dafb 0%, #21a1f1 100%)',
89        padding: '30px',
90        borderRadius: '12px',
91        color: 'white',
92        textAlign: 'center',
93        marginBottom: '30px'
94      }}>
95        <h1 style={{ margin: 0, fontSize: '2rem' }}>Vite + React</h1>
96        <p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>
97          Project structure and basic files
98        </p>
99      </header>
100
101      <div style={{
102        backgroundColor: '#1e1e1e',
103        borderRadius: '8px',
104        padding: '20px',
105        marginBottom: '30px',
106        fontFamily: 'monospace'
107      }}>
108        <div style={{ color: '#888', marginBottom: '10px' }}>Terminal:</div>
109        <div style={{ color: '#00ff00' }}>$ npm create vite@latest my-app -- --template react</div>
110        <div style={{ color: '#888', marginTop: '5px' }}>Scaffolding project in /my-app...</div>
111        <div style={{ color: '#00ff00', marginTop: '5px' }}>Done. Now run: cd my-app && npm install && npm run dev</div>
112      </div>
113
114      <div style={{ display: 'grid', gridTemplateColumns: '300px 1fr', gap: '20px' }}>
115        <div style={{
116          backgroundColor: '#252526',
117          borderRadius: '8px',
118          padding: '15px'
119        }}>
120          <h3 style={{ color: '#cccccc', margin: '0 0 15px 0', fontSize: '14px' }}>
121            EXPLORER
122          </h3>
123          {fileStructure.map((item, index) => (
124            <div
125              key={index}
126              onClick={() => item.type === 'file' && setActiveFile(item.name.trim())}
127              style={{
128                padding: '8px 10px',
129                color: item.type === 'folder' ? '#dcb67a' : '#9cdcfe',
130                cursor: item.type === 'file' ? 'pointer' : 'default',
131                backgroundColor: activeFile === item.name.trim() ? '#094771' : 'transparent',
132                borderRadius: '4px',
133                fontSize: '14px',
134                fontFamily: 'monospace'
135              }}
136            >
137              {item.type === 'folder' ? 'β–Έ' : 'β€’'} {item.name}
138            </div>
139          ))}
140        </div>
141
142        <div style={{
143          backgroundColor: '#1e1e1e',
144          borderRadius: '8px',
145          padding: '20px'
146        }}>
147          <div style={{
148            color: '#888',
149            fontSize: '12px',
150            marginBottom: '10px',
151            borderBottom: '1px solid #333',
152            paddingBottom: '10px'
153          }}>
154            {activeFile}
155          </div>
156          <pre style={{
157            color: '#d4d4d4',
158            margin: 0,
159            fontSize: '14px',
160            lineHeight: '1.5',
161            overflow: 'auto'
162          }}>
163            {fileContents[activeFile] || '// Select a file from the list'}
164          </pre>
165        </div>
166      </div>
167
168      <div style={{
169        marginTop: '30px',
170        padding: '20px',
171        backgroundColor: '#fff3e0',
172        borderRadius: '8px'
173      }}>
174        <h3 style={{ color: '#e65100', marginTop: 0 }}>Startup commands</h3>
175        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '15px' }}>
176          <div style={{ backgroundColor: 'white', padding: '15px', borderRadius: '8px' }}>
177            <code style={{ color: '#e65100' }}>npm run dev</code>
178            <p style={{ margin: '5px 0 0 0', fontSize: '14px', color: '#666' }}>
179              Starts the development server
180            </p>
181          </div>
182          <div style={{ backgroundColor: 'white', padding: '15px', borderRadius: '8px' }}>
183            <code style={{ color: '#e65100' }}>npm run build</code>
184            <p style={{ margin: '5px 0 0 0', fontSize: '14px', color: '#666' }}>
185              Builds the production version
186            </p>
187          </div>
188        </div>
189      </div>
190    </div>
191  );
192}
193
194export default function App() {
195  return <ViteProjectDemo />;
196}

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What is the main purpose of the src/ folder in a React project?

  2. 2. In which folder are the main React source files located?

  3. 3. Where is the index.html file located in a React project created with Vite?

Hands-on tasks in the game

  • Vertical ordering

    Arrange the file hierarchy of a React application:

  • Click in order

    Arrange the React development workflow:

  • Code editor

    In App.jsx, create the basic structure of a component: a React import, a functional App component that returns JSX, and a default export (export default).

Useful articles