How should a React project be structured?
Solution and explanation
Feature-based structure (recommended for medium and large apps)
src/
app/ # app shell: providers, router, global styles
App.jsx
routes.jsx
features/
jobs/
api.js # fetch functions / query hooks
components/ # JobCard.jsx, JobFilters.jsx
hooks/ # useJobs.js
pages/ # JobsPage.jsx, JobDetailPage.jsx
jobs.test.jsx
auth/
resume/
components/ # shared UI: Button, Modal, Input, Table
hooks/ # shared hooks: useDebounce, useLocalStorage
lib/ # api client (axios instance), formatters, constants
assets/
Everything for one feature lives together, so a developer working on "jobs" rarely leaves that folder. Shared pieces are promoted to components/ or lib/ only when a second feature needs them.
Small projects
A flat components/, pages/, hooks/, services/ layout is fine; switch to feature folders when it grows.
Conventions that help teams
- One component per file,
PascalCase.jsx; hooksuseCamelCase.js. - An
index.jsper feature exporting its public API only. - A single API client with base URL, auth header and error handling:
export const api = axios.create({ baseURL: import.meta.env.VITE_API_URL, withCredentials: true });
api.interceptors.response.use(r => r, err => {
if (err.response?.status === 401) window.location.assign('/login');
return Promise.reject(err);
});
- Environment variables in
.env(VITE_prefix in Vite); never put secrets in frontend code. - Absolute imports (
@/features/jobs) via path aliases. - ESLint + Prettier + TypeScript for consistency and type safety.
Separation of concerns
- Pages: compose features and read route params.
- Feature components: UI + calls to hooks.
- Hooks: state and data logic.
lib/api: network and pure utilities.
Summary
Organise by feature, keep shared UI and utilities separate, centralise the API client, and enforce conventions with linting and TypeScript.
