Skip to main content

๐Ÿ—‚๏ธ Project Structure and Organization

Organizing code is like organizing a workshop: when every tool has a place, you build faster and break less. This lesson gives you battle-tested folder patterns for frontend and backend projects, the naming and config conventions that professional teams rely on, and a README template that earns its keep.

๐ŸŽฏ Learning Objectives

By the end of this lesson, you will be able to:

  • Lay out a frontend and a backend project using standard, scalable folder patterns
  • Explain separation of concerns and why it makes code easier to change
  • Apply the convention over configuration principle to reduce decisions
  • Choose consistent naming conventions for files, folders, and components
  • Identify the key config files and write a useful README

Estimated Time: 25โ€“35 minutes  โ€ข  Difficulty: Beginner

Hands-on: Design the full folder structure for a blog application, frontend and backend.

In This Lesson

Why Structure Matters

A well-organized project isn't about tidiness for its own sake โ€” it's a productivity multiplier. When code has a predictable home, you spend your energy solving problems instead of hunting for files.

๐Ÿ“– The payoff of good structure

  • Readability โ€” anyone can find things and understand the shape of the app.
  • Collaboration โ€” teammates work in parallel without stepping on each other.
  • Debugging & testing โ€” isolated concerns are easier to test and fix.
  • Scalability โ€” the project grows without turning into a tangle.
๐Ÿ—„๏ธ A useful analogy: Think of your project as a filing cabinet. Each drawer (folder) has one clear purpose, and every document (file) goes in the drawer where you'd instinctively look for it. A stranger โ€” including future-you at 2 a.m. โ€” should be able to find anything without opening every drawer.

Frontend & Backend Patterns

Different parts of an app organize around different jobs. At a high level, most projects share this skeleton:

graph TD A[Project Root] --> B[src/ โ€” source code] A --> C[public/ โ€” static assets] A --> D[tests/ โ€” test files] A --> E[config files] B --> F[components/] B --> G[services/] B --> H[utils/]

Frontend structure

A modern frontend project separates what users see (components, pages) from how it talks to servers (services) and shared helpers (utils):

project-name/
โ”œโ”€โ”€ public/               # Served as-is (not processed by the bundler)
โ”‚   โ”œโ”€โ”€ index.html        # Entry HTML file
โ”‚   โ”œโ”€โ”€ favicon.ico       # Site favicon
โ”‚   โ””โ”€โ”€ images/           # Public images
โ”œโ”€โ”€ src/                  # Source code
โ”‚   โ”œโ”€โ”€ components/       # Reusable UI components
โ”‚   โ”œโ”€โ”€ pages/            # Page-level components / routes
โ”‚   โ”œโ”€โ”€ services/         # API calls and data fetching
โ”‚   โ”œโ”€โ”€ utils/            # Helper functions
โ”‚   โ”œโ”€โ”€ assets/           # Images, fonts imported by code
โ”‚   โ”œโ”€โ”€ styles/           # Global styles
โ”‚   โ”œโ”€โ”€ App.jsx           # Root component
โ”‚   โ””โ”€โ”€ main.jsx          # Application entry point
โ”œโ”€โ”€ tests/                # Test files
โ”œโ”€โ”€ .gitignore            # Files Git should ignore
โ”œโ”€โ”€ package.json          # Dependencies and scripts
โ””โ”€โ”€ README.md             # Project overview

Backend structure

A backend project usually follows the flow of a request: a route points to a controller, which uses a service for business logic, which reads and writes models:

project-name/
โ”œโ”€โ”€ src/                  # Source code
โ”‚   โ”œโ”€โ”€ controllers/      # Request handlers (parse in, shape out)
โ”‚   โ”œโ”€โ”€ models/           # Data models / schemas
โ”‚   โ”œโ”€โ”€ routes/           # URL-to-controller mapping
โ”‚   โ”œโ”€โ”€ middleware/       # Auth, logging, error handling
โ”‚   โ”œโ”€โ”€ services/         # Business logic
โ”‚   โ”œโ”€โ”€ utils/            # Helper functions
โ”‚   โ””โ”€โ”€ app.js            # Application setup
โ”œโ”€โ”€ config/               # Configuration (db, env loading)
โ”œโ”€โ”€ tests/                # Test files
โ”œโ”€โ”€ .env.example          # Documents required env vars (no secrets)
โ”œโ”€โ”€ .gitignore            # Files Git should ignore
โ”œโ”€โ”€ package.json          # Dependencies and scripts
โ””โ”€โ”€ README.md             # Project overview

๐Ÿ’ก The request's journey through the backend

A request to POST /api/orders flows: route (matches the URL) โ†’ middleware (checks the auth token) โ†’ controller (validates the body) โ†’ service (applies business rules) โ†’ model (saves to the database) โ†’ response back out. Each folder owns exactly one step, so a change to one layer rarely disturbs the others.

Convention Over Configuration

Most modern frameworks favor convention over configuration: rather than making you configure every detail, they assume sensible defaults if you follow established patterns. React doesn't force a folder layout, but the community converged on one โ€” and following it pays dividends.

flowchart TD A[Convention Over Configuration] --> B[Less decision fatigue] A --> C[Standardized codebase] A --> D[Faster onboarding] A --> E[Better tooling support]

It's like a standard kitchen: guests expect plates in the cupboards and forks in the drawers. When your code follows shared conventions, any developer can walk in and immediately know where things live โ€” no map required.

โš ๏ธ Convention has limits

Conventions are a starting point, not a straitjacket. Deviate when your app genuinely needs it โ€” but do it deliberately and document why. Surprising, undocumented structure is where onboarding goes to die.

A Real-World Example

Here's how a production e-commerce app might organize its React frontend. Notice how components are grouped by role โ€” shared, layout, and feature-specific โ€” and how hooks and context get their own homes:

ecommerce-frontend/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”œโ”€โ”€ common/           # Button, Input, Modal โ€” used everywhere
โ”‚   โ”‚   โ”œโ”€โ”€ layout/           # Header, Footer, Sidebar
โ”‚   โ”‚   โ””โ”€โ”€ product/          # ProductCard, ProductList
โ”‚   โ”œโ”€โ”€ pages/                # Home, ProductDetail, Cart
โ”‚   โ”œโ”€โ”€ services/             # api.js, productService.js, authService.js
โ”‚   โ”œโ”€โ”€ hooks/                # useCart, useAuth โ€” reusable stateful logic
โ”‚   โ”œโ”€โ”€ context/              # CartContext, AuthContext โ€” shared state
โ”‚   โ”œโ”€โ”€ utils/                # formatters, validators
โ”‚   โ”œโ”€โ”€ assets/ ยท styles/
โ”‚   โ”œโ”€โ”€ App.jsx
โ”‚   โ””โ”€โ”€ main.jsx
โ””โ”€โ”€ package.json

And the Node.js/Express backend, organized around the request lifecycle:

ecommerce-backend/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ controllers/          # productController, orderController
โ”‚   โ”œโ”€โ”€ models/               # Product, User, Order
โ”‚   โ”œโ”€โ”€ routes/               # productRoutes, orderRoutes
โ”‚   โ”œโ”€โ”€ middleware/           # auth.js, error.js
โ”‚   โ”œโ”€โ”€ services/             # paymentService, productService
โ”‚   โ”œโ”€โ”€ utils/                # logger, validators
โ”‚   โ”œโ”€โ”€ config/               # db.js
โ”‚   โ””โ”€โ”€ app.js
โ”œโ”€โ”€ .env.example
โ”œโ”€โ”€ .gitignore
โ””โ”€โ”€ package.json

This mirrors a well-run store: products (components) grouped by category, checkout logic (services) kept separate from displays, and store policies (config) centralized in one place.

Naming Conventions

Clear, consistent names are the cheapest documentation you'll ever write. Different casings signal different kinds of things:

ConventionLooks likeTypically used for
camelCaseuserService.jsJS modules, variables, functions
PascalCaseUserProfile.jsxReact components, classes
kebab-caseuser-styles.cssCSS files, folders, URLs
snake_caseuser_utils.pyPython files, some databases

The rule that matters most isn't which convention โ€” it's consistency. Pick one per category and never mix.

# Good โ€” clear, descriptive, self-documenting
UserProfile.jsx
ProductCard.jsx
ShoppingCart.jsx

# Bad โ€” vague and inconsistent
Comp1.jsx
MyComp.jsx
X.jsx

Naming is like signage in a library: precise labels let people find a book without pulling every one off the shelf.

Configuration Files

Config files live at the project root and set the rules of the road. The ones you'll meet constantly:

  • package.json โ€” dependencies and scripts
  • .gitignore โ€” files Git should never track
  • .env โ€” secrets and environment values (never committed)
  • .eslintrc / eslint.config.js โ€” linting rules
  • .prettierrc โ€” code formatting
  • tsconfig.json โ€” TypeScript settings
  • vite.config.js โ€” build tool configuration

A typical package.json for a modern React app built with Vite:

{
  "name": "ecommerce-app",
  "version": "1.0.0",
  "description": "E-commerce application",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "test": "vitest",
    "lint": "eslint src",
    "format": "prettier --write \"src/**/*.{js,jsx,css,md}\""
  },
  "dependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "react-router-dom": "^7.1.0"
  },
  "devDependencies": {
    "vite": "^6.0.0",
    "eslint": "^9.17.0",
    "prettier": "^3.4.0",
    "vitest": "^2.1.0"
  }
}

A sensible .gitignore keeps generated files and secrets out of version control:

# Dependencies
/node_modules

# Build output
/dist
/build

# Environment variables (secrets!)
.env
.env.local

# Logs
npm-debug.log*

# Editor files
.idea/
.vscode/

โš ๏ธ The number one config mistake

Committing a .env file leaks your API keys and database passwords to anyone who can see the repo. Always list .env in .gitignore, and commit a .env.example with the keys but no values so teammates know what to fill in.

Documentation & the README

The README.md is the front door to your project. A good one lets someone go from "just cloned this" to "running it locally" in minutes. Aim to include:

  • Project name and a one-line description
  • Installation and setup steps
  • How to run it (dev and build)
  • The technology stack
  • Contributing guidelines and license
# E-Commerce Application

A modern e-commerce platform built with React and Node.js.

## Features
- User authentication and profiles
- Product browsing and search
- Shopping cart and checkout

## Installation
1. Clone the repository
   ```bash
   git clone https://github.com/username/ecommerce-app.git
   cd ecommerce-app
   ```
2. Install dependencies
   ```bash
   npm install
   ```
3. Copy `.env.example` to `.env` and fill in the values.
4. Start the dev server
   ```bash
   npm run dev
   ```

## Tech Stack
- Frontend: React, React Router
- Backend: Node.js, Express, PostgreSQL
- Auth: JWT

## License
MIT

โœ… A README worth reading

Write it for a newcomer who has never seen the project. If a fresh developer can clone, install, configure, and run your app using only the README โ€” with no verbal hand-holding โ€” you've done it right.

Hands-on Exercise & Quiz

๐Ÿ‹๏ธ Architect a blog application

Objective: Design the folder structure for a blog app with these features:

  • User authentication
  • Create, edit, and delete blog posts
  • A comment system
  • User profiles
  • Search

Instructions:

  1. Sketch a frontend tree: group components (common / layout / feature), pages, services, hooks, and context.
  2. Sketch a backend tree: routes, controllers, services, models, and middleware.
  3. For each feature above, name at least one file it would add on each side.
  4. Apply consistent naming: PascalCase for components, camelCase for services.
๐Ÿ’ก Hint

Start from the request lifecycle on the backend (route โ†’ controller โ†’ service โ†’ model) and from the UI on the frontend (page โ†’ components โ†’ service call). Each feature usually touches one file in each layer: e.g. "comments" gives you commentRoutes.js, commentController.js, commentService.js, Comment.js, and a CommentList.jsx component.

โœ… Example solution
blog-frontend/src/
โ”œโ”€โ”€ components/
โ”‚   โ”œโ”€โ”€ common/    Button.jsx, SearchBar.jsx
โ”‚   โ”œโ”€โ”€ layout/    Header.jsx, Footer.jsx
โ”‚   โ”œโ”€โ”€ post/      PostCard.jsx, PostEditor.jsx
โ”‚   โ””โ”€โ”€ comment/   CommentList.jsx, CommentForm.jsx
โ”œโ”€โ”€ pages/         Home.jsx, PostDetail.jsx, Profile.jsx, Login.jsx
โ”œโ”€โ”€ services/      authService.js, postService.js, commentService.js
โ”œโ”€โ”€ hooks/         useAuth.js, usePosts.js
โ””โ”€โ”€ context/       AuthContext.jsx

blog-backend/src/
โ”œโ”€โ”€ routes/        authRoutes.js, postRoutes.js, commentRoutes.js
โ”œโ”€โ”€ controllers/   authController.js, postController.js, commentController.js
โ”œโ”€โ”€ services/      postService.js, searchService.js
โ”œโ”€โ”€ models/        User.js, Post.js, Comment.js
โ””โ”€โ”€ middleware/    auth.js, error.js

๐ŸŽฏ Quick Quiz

Question 1: On a backend, which folder's job is to map a URL like /api/posts to the code that handles it?

Question 2: Which file should always be listed in .gitignore to avoid leaking secrets?

Question 3: What does "convention over configuration" primarily give a team?

Summary

๐ŸŽ‰ Key Takeaways

  • Good structure is a productivity multiplier โ€” readability, collaboration, testing, and scale.
  • Frontends organize by UI role (components / pages / services); backends by the request lifecycle (routes โ†’ controllers โ†’ services โ†’ models).
  • Convention over configuration cuts decisions and makes any codebase instantly familiar.
  • Pick consistent naming per category โ€” PascalCase components, camelCase modules.
  • Keep secrets out of Git with .gitignore, and write a README a newcomer can actually follow.

๐Ÿ“š Further Reading

๐Ÿš€ What's Next?

With a clean project skeleton in hand, the next lesson โ€” Agile Development Principles โ€” zooms out to how teams work: planning, iterating, and shipping software in small, valuable increments.

๐ŸŽ‰ Well structured!

A tidy foundation pays off every single day you work in the project. Future-you will thank present-you.