DEV Community

Aleksandr Ryzhikov
Aleksandr Ryzhikov

Posted on

How do I Structure Projects for Scalability

When the project is small, we can easily "dump everything into one folder" and work. But as the application grows, the chaos in the structure begins to slow down development, complicate support, and hinder new team members.

In this article, I'll show you how I structure frontend projects to be scalable, predictable, and convenient for teamwork.


Principles

Before moving on to the structure, I always adhere to three rules::

  1. Explicit is better than implicit — one additional folder is better than magic with obscure imports.
  2. Features are more important than layers — instead of "/components", "/services", I try to highlight functional modules.
  3. Scalability from day one — even if the project is small, the structure should allow for growth without restructuring.

Basic project structure

src/
├── app/                    # Application Level configuration
│   ├── providers/          # Context providers, themes, routers
│   ├── store/              # Global status
│   └── config/             # Constants, settings
├── entities/               # Entities (User, Product, Todo, etc.)
├── features/               # Business features (Login, Search, Cart, etc.)
├── pages/                  # Pages (UI level routing)
├── shared/                 # Reusable utilities, UI components, helpers
└── index.TSX # Entry Point
Enter fullscreen mode Exit fullscreen mode

Example: entities

The entities/ stores models, APIs, and minimal components. For example, entities/todo/:

entities/
└── todo/
    ├── api/
    │ └── todoApi.ts # CRUD operations
    ├── model/
    │   ├── types.ts # Entity Types
    │   └── store.ts # Zustand/Redux status
    └── ui/
        └── TodoItem.tsx # Basic UI Component
Enter fullscreen mode Exit fullscreen mode
// entities/todo/api/todoApi.ts
export const fetchTodos = async () => {
  const res = await fetch("/api/todos");
  return res.json();
};
Enter fullscreen mode Exit fullscreen mode

Example: feature

A feature combines several entities to solve a problem. For example, features/TodoList/:

features/
└── todoList/
    ├── ui/
    │   └── TodoList.tsx
    └── model/
        └── hooks.ts # Local Hooks
Enter fullscreen mode Exit fullscreen mode
// features/todoList/ui/TodoList.tsx
import { useEffect, useState } from "react";
import { fetchTodos } from "@/entities/todo/api/todoApi";
import { TodoItem } from "@/entities/todo/ui/TodoItem";

export function TodoList() {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    fetchTodos().then(setTodos);
  }, []);

  return (
    <div>
      {todos.map((todo) => (
        <TodoItem key={todo.id} {...todo} />
      ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Example: a Page

Pages collect features and entities into a ready-made screen.

pages/
└── home/
    └── HomePage.tsx
Enter fullscreen mode Exit fullscreen mode
// pages/home/HomePage.tsx
import { TodoList } from "@/features/todoList/ui/TodoList";

export function HomePage() {
  return (
    <main>
      <h1>My tasks</h1>
      <TodoList />
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

Shared — always at hand

shared/ contains everything that does not depend on a specific entity or feature:

shared/
├── ui/   # Buttons, inputs, mods
├── lib/  # Utilities, helpers
├── api/  # Basic HTTP client
Enter fullscreen mode Exit fullscreen mode
// shared/api/http.ts
export async function http<T>(url: string, options?: RequestInit): Promise<T> {
  const res = await fetch(url, options);
  if (!res.ok) throw new Error("Network error");
  return res.json();
}
Enter fullscreen mode Exit fullscreen mode

Why it works

  • It's easy for a new developer to navigate: Essentials → Features → Page.
  • The code can be scaled: new features are added without revising the entire architecture.
  • shared/ remains compact and predictable, without leaking business logic.

Conclusion

This structure has grown from real projects, from small pet projects to applications with dozens of developers. It's not the only correct one, but it avoids the "spaghetti code" and makes it easier to maintain.

And how do you structure projects? Share your experience in the comments.👇

Top comments (0)