Full-project lesson · needs Node.js, npm and real project files, so it does not run in the in-page playground.
By now you have built components, hooks and routes. This lesson zooms out: what a maintainable, professional React project contains beyond the code, and how the pieces fit together.
The root of the project
my-app/
├── index.html the single HTML page; has the root element
├── package.json dependencies and scripts
├── package-lock.json exact versions (commit it)
├── vite.config.ts build and dev-server settings (and test settings)
├── tsconfig.json TypeScript settings (references the two below)
├── tsconfig.app.json settings for code in src
├── tsconfig.node.json settings for config files such as vite.config.ts
├── .oxlintrc.json lint rules (Oxlint in the Vite template)
├── .gitignore node_modules, dist, *.local
├── .env shared public settings (VITE_ variables)
├── .env.example documents which variables exist
├── README.md how to run, test, build and deploy
├── public/ files served as they are (favicon, robots.txt)
└── src/ your code
This is the layout of the react-ts Vite template (create-vite 9, Vite 8, TypeScript 6.0 at the time of writing), plus the .env files and README you add yourself.
Inside src
A structure that scales (Feature-Based Project Structure):
src/
├── main.tsx starts React
├── App.tsx the app shell
├── app/ providers, router, global layout
├── features/ products/, cart/, account/ ... each with components, hooks, api
├── shared/ reusable components, hooks and utilities
├── test/ test setup files
└── index.css global styles and CSS variables
The package.json scripts
Every project should answer the same four questions with a script:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "oxlint",
"preview": "vite preview",
"test": "vitest"
}
}
| Script | Question it answers |
|---|---|
npm run dev | How do I work on it? |
npm run lint | Is the code consistent and free of obvious mistakes? |
npm test | Does it still work? |
npm run build | Does it compile and bundle for production? (In the TypeScript template this also type-checks.) |
npm run preview | What will the production build look like? |
The first four lines come straight from the Vite react-ts template; test is the line you add when you set up testing (Basic Testing Concepts).
Tooling you will meet
- Linter: finds bugs and enforces rules. The template includes Oxlint with React rules, including the Rules of Hooks. Many teams use ESLint with
eslint-plugin-react-hooksinstead; either is fine, but have one. - Formatter: ends style arguments. Prettier is the most common.
- TypeScript: catches mistakes before running (React with TypeScript).
- Test runner: Vitest with Testing Library is the usual match for Vite apps.
- Git hooks (for example Husky or lint-staged): run lint and format on each commit.
- Editor settings: share them with
.editorconfigand.vscoderecommendations.
Environment files
Keep configuration out of the code (Environment Variables). A common convention:
.env shared defaults that are safe to publish
.env.example a copy with fake values, committed, as documentation
.env.local your own overrides and anything private (never committed)
.env.production values used by production builds
Remember that every VITE_ value is public; keep real secrets on a server (Why Secret Keys Must Not Be Exposed).
Continuous integration
A CI service (GitHub Actions, GitLab CI and others) runs your checks on every push, so broken code is found early. The commands are the same ones you run locally:
npm ci # install exactly what package-lock.json says (faster and stricter than npm install)
npm run lint
npm test -- --run
npm run build
npm test -- --run makes Vitest run once and exit instead of staying in watch mode. Add these steps to your CI configuration, and fail the build if any step fails.
Dependencies: keep them few and healthy
- Add a package only when it saves real work. Each one is code you must trust and update.
- Run
npm outdatedandnpm auditregularly. - Commit the lock file, and update packages in small, tested steps.
- Prefer widely used, maintained packages, and check that they support your React version (React 19).
The README
A new teammate (or you in six months) should be able to run the project from the README alone: what it is, how to install, the scripts, the environment variables and how to deploy. Keep it short and correct.
A checklist for a healthy project
- [ ]
npm installthennpm run devworks on a fresh machine - [ ] Lint, tests and build run in CI
- [ ] TypeScript is on (or JSDoc types in plain JavaScript)
- [ ]
.env.exampledocuments every variable; no secrets are committed - [ ] The folder structure is documented and consistent
- [ ] Error handling, loading states and accessibility are part of “done”
Key points
- A modern project is more than components: config, scripts, linting, types, tests and CI.
- Every project should have
dev,lint,test,buildandpreviewscripts. - Keep configuration in
.envfiles, dependencies few, and the README accurate.