A Senior Developer's Guide to Starting a React Project from Scratch
Posted Date: 2026-03-04
Setting up a React project used to mean running npx create-react-app and calling it a day. Today, the ecosystem has matured. As a senior developer, starting a project isn't just about getting a local server running; it's about establishing a scalable, maintainable, and highly performant foundation. If you start messy, your project will end messy.
In this guide, we will walk through the exact steps and architectural decisions you should make when spinning up a modern React application from absolute zero. No bloated boilerplate, just a clean, professional setup.
Step 1: Ditch CRA and Scaffold with Vite
Create React App (CRA) is officially dead and deprecated. The modern standard for Single Page Applications (SPAs) is Vite. It leverages native ES modules to provide a lightning-fast dev server and uses Rollup for highly optimized production builds.
Open your terminal and run the following command to scaffold a React project with TypeScript (because shipping production code without TypeScript in 2026 is a recipe for disaster):
# Scaffold the project
npm create vite@latest my-awesome-app -- --template react-ts
# Navigate inside and install dependencies
cd my-awesome-app
npm install
# Start the dev server
npm run dev
Step 2: Clean the Boilerplate
Vite gives you a nice counter button and some logos. Delete them. A professional workspace starts with a blank canvas.
- Delete
App.css. - Clear out
index.css(leave it empty for now). - Strip
App.tsxdown to a simple functional component returning a single<div>. - Remove the
assetsfolder contents if you don't need the Vite logo.
Step 3: Define a Scalable Folder Architecture
The biggest mistake junior developers make is dumping all their files directly into the src/ directory. As your application grows, this becomes an unmaintainable nightmare.
Immediately create the following directories inside your src/ folder:
src/
├── assets/ # Images, fonts, and global CSS
├── components/ # Reusable UI components (Buttons, Inputs, Modals)
├── features/ # Feature-based modules (e.g., Auth, Dashboard)
├── hooks/ # Custom React hooks (useAuth, useClickOutside)
├── layouts/ # Wrappers for pages (Navbar + Sidebar + Content)
├── pages/ # Page-level components that correspond to routes
├── services/ # API calls and external integrations
├── store/ # Global state management (Zustand, Redux)
├── types/ # Global TypeScript interfaces and types
└── utils/ # Helper functions (formatDate, currencyFormatter)
Step 4: Set Up Absolute Imports (Path Aliases)
Nobody likes seeing import Button from '../../../components/Button'. We configure absolute imports to make our code cleaner: import Button from '@/components/Button'.
First, update your tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
Then, install npm i -D vite-tsconfig-paths and add it to your vite.config.ts.
Step 5: Enforce Code Quality (ESLint, Prettier, Husky)
If you are working in a team (or even just future-proofing your own code), you need automated quality checks. Vite sets up basic ESLint for you, but you need to combine it with Prettier to ensure uniform code formatting.
- Install Prettier:
npm i -D prettier eslint-config-prettier eslint-plugin-prettier - Create a
.prettierrcfile with your preferred rules (e.g.,"semi": true, "singleQuote": true). - Set up Husky and lint-staged to prevent anyone from committing bad code:
npx husky-init && npm install.
Step 6: Choose Your Stack (Styling, Routing, State)
Now that the foundation is rock solid, you install the core libraries that will power your application. My standard Senior Developer stack usually looks like this:
- Styling: Tailwind CSS. It is the industry standard for rapid, utility-first styling. (Install via
npm i -D tailwindcss postcss autoprefixer). - Routing: React Router v6+. Set up a centralized router configuration using
createBrowserRouter. - Server State (Data Fetching): TanStack Query (React Query). Never use
useEffectto fetch data. React Query handles caching, background updates, and loading states automatically. - Client State: Zustand. If you don't need the immense boilerplate of Redux, Zustand is the lightweight, unopinionated champion of global state management.
Conclusion
Spending 30 minutes configuring your project correctly at the very beginning will save you hundreds of hours of refactoring technical debt later on. You now have a typed, linted, well-architected, and lightning-fast environment. Now, the real work begins. Happy coding!