A well-structured React project is as important as well-structured backend code. Files scattered in a flat directory become unmanageable as the application grows. The standard approach organises by feature or type: a components/ folder for reusable UI pieces, a pages/ folder for route-level components, hooks/ for custom hooks, services/ for API calls, and stores/ for state management. With path aliases, absolute imports replace fragile relative paths. With ESLint and Prettier, code quality is enforced automatically. This lesson sets up the complete development environment for the blog application’s frontend.
Recommended Project Structure
blog-frontend/
├── public/
│ └── favicon.svg
│
├── src/
│ ├── main.jsx ← entry point
│ ├── App.jsx ← root component + router setup
│ │
│ ├── components/ ← reusable UI components
│ │ ├── ui/ ← primitive: Button, Input, Badge, Modal
│ │ │ ├── Button.jsx
│ │ │ ├── Badge.jsx
│ │ │ └── Input.jsx
│ │ ├── layout/ ← layout: Header, Sidebar, Footer
│ │ │ ├── Header.jsx
│ │ │ └── Layout.jsx
│ │ └── post/ ← feature: PostCard, PostForm, CommentList
│ │ ├── PostCard.jsx
│ │ ├── PostForm.jsx
│ │ └── CommentList.jsx
│ │
│ ├── pages/ ← route-level components
│ │ ├── HomePage.jsx
│ │ ├── PostDetailPage.jsx
│ │ ├── LoginPage.jsx
│ │ └── DashboardPage.jsx
│ │
│ ├── hooks/ ← custom React hooks
│ │ ├── useAuth.js
│ │ ├── usePosts.js
│ │ └── useInfiniteScroll.js
│ │
│ ├── services/ ← API communication
│ │ ├── api.js ← base axios/fetch instance with auth
│ │ ├── posts.js ← post CRUD API calls
│ │ └── auth.js ← login, register, refresh
│ │
│ ├── stores/ ← global state (Zustand or Context)
│ │ └── authStore.js
│ │
│ └── utils/ ← pure utility functions
│ ├── formatDate.js
│ └── slugify.js
│
├── vite.config.js
├── .eslintrc.cjs
├── tailwind.config.js
└── package.json
src/features/posts/ including its components, hooks, and API calls. Either works; consistency within the project matters more than which convention you choose.`text-${colour}-600`), Tailwind’s JIT compiler cannot detect them and the classes will be missing in production. Always use complete class names in JSX: colour === "blue" ? "text-blue-600" : "text-red-600". Never dynamically construct partial Tailwind class names.Installing Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p # creates tailwind.config.js and postcss.config.js
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}", // scan these files for class names
],
theme: {
extend: {
colors: {
brand: {
50: "#eff6ff",
500: "#3b82f6",
900: "#1e3a8a",
},
},
},
},
plugins: [],
};
/* src/index.css — Tailwind directives */
@tailwind base;
@tailwind components;
@tailwind utilities;
ESLint and Prettier Setup
npm install -D eslint eslint-plugin-react eslint-plugin-react-hooks prettier
// .eslintrc.cjs
module.exports = {
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
],
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
settings: { react: { version: "detect" } },
rules: {
"react/react-in-jsx-scope": "off", // not needed with Vite
"react/prop-types": "warn", // warn on missing prop types
"no-unused-vars": "warn",
},
};
// .prettierrc
// { "semi": true, "singleQuote": false, "tabWidth": 4, "trailingComma": "es5" }
Common Mistakes
Mistake 1 — Dynamic Tailwind class construction
❌ Wrong — class not included in production build:
// Tailwind can't see "text-blue-600" or "text-red-600" — only "text-${variant}-600"
<span className={`text-${variant}-600`}>...</span>
✅ Correct — use complete class names:
const colours = { blue: "text-blue-600", red: "text-red-600" };
<span className={colours[variant]}>...</span> // ✓ full class names
Mistake 2 — Deeply nested relative imports
❌ Wrong — fragile paths break on file moves:
import Button from "../../../components/ui/Button" // what if the file moves?
✅ Correct — use @ alias configured in vite.config.js:
import Button from "@/components/ui/Button" // ✓ always relative to src/
Quick Reference — Dev Workflow
| Task | Command |
|---|---|
| Start dev server | npm run dev |
| Lint code | npm run lint |
| Format code | npx prettier --write src/ |
| Build for production | npm run build |
| Preview production build | npm run preview |
| Install React DevTools | Chrome Web Store → “React Developer Tools” |