0Pricing
Frontend Academy · Lesson

Feature-Based Folder Structure

Organise code by feature domain rather than by type, colocate tests, styles, and components, and enforce boundaries with eslint-plugin-boundaries.

Feature-Based Folder Structure is a free Frontend Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Two Ways to Organise Code

You can group code by type (components/, hooks/, services/, types/) or by feature (auth/, checkout/, dashboard/ — each containing its own components, hooks, etc.). Feature-based wins for medium-to-large apps.

Type-Based — The Default Trap

The classic React tutorial structure groups everything by type. It scales badly: every file change touches multiple unrelated folders, and 'find all checkout code' means greping across the whole tree.

// Type-based (avoid for large apps):
src/
  components/
    Button.tsx
    LoginForm.tsx
    CartItem.tsx
  hooks/
    useAuth.ts
    useCart.ts
  services/
    auth.ts
    cart.ts
  types/
    User.ts
    CartItem.ts

Feature-Based Structure

Group everything related to a feature in one folder. Easy to find, easy to delete, easy to reason about.

src/
  features/
    auth/
      LoginForm.tsx
      SignupForm.tsx
      useAuth.ts
      auth.service.ts
      auth.types.ts
      auth.test.tsx
    cart/
      CartItem.tsx
      CartSummary.tsx
      useCart.ts
      cart.service.ts
      cart.types.ts
  shared/
    components/
      Button.tsx
    hooks/
      useDebounce.ts

Co-location Inside a Feature

A feature folder contains: components, hooks, services, types, tests — all the code needed for that domain. New developer wants to understand auth? Open auth/. Want to delete auth? Delete the folder.

Shared vs Feature

Code used by 2+ features moves to shared/ (or lib/). Code used by one feature stays inside it. Resist 'might be reusable later' — wait for the second use before extracting.

Feature Boundary Rules

Features should not import from each other directly. If two features need to share code, the shared piece moves to shared/. If they need to coordinate, use events or a shared store at the app level.

Enforcing Boundaries with ESLint

Use eslint-plugin-boundaries or eslint-plugin-import to enforce: features can import from shared but not from each other.

// .eslintrc.json
{
  "plugins": ["boundaries"],
  "settings": {
    "boundaries/elements": [
      { "type": "feature", "pattern": "src/features/*" },
      { "type": "shared",  "pattern": "src/shared/*" }
    ]
  },
  "rules": {
    "boundaries/element-types": ["error", {
      "default": "disallow",
      "rules": [
        { "from": "feature", "allow": ["shared"] },
        { "from": "shared",  "allow": ["shared"] }
      ]
    }]
  }
}

Public API per Feature

Each feature exports a public API via features/auth/index.ts. Other code imports from '@/features/auth', not deep paths. Lets you refactor internals without breaking consumers.

// features/auth/index.ts
export { LoginForm } from './LoginForm';
export { useAuth } from './useAuth';
export type { User, AuthState } from './auth.types';

// Consumers:
import { LoginForm, useAuth } from '@/features/auth';
// NOT: import { LoginForm } from '@/features/auth/LoginForm';

Nesting Subfeatures

Large features can have subfolders: dashboard/widgets/, dashboard/charts/. Avoid nesting deeper than 2-3 levels — search becomes painful.

Where Routes Live

Pages/routes can live in a top-level pages/ or routes/ folder. They're thin — they pull components and hooks from features and compose them.

src/
  pages/
    Dashboard.page.tsx   // composes Dashboard widgets from features/dashboard/
    Cart.page.tsx        // composes from features/cart/
  features/
  shared/

Migrating an Existing App

Start with new features only — put new code in features/. Don't refactor everything at once. As you touch old files, gradually move them. ESLint boundary rules prevent regression in the new structure.

When Type-Based Still Works

For very small apps (under 30 components) or libraries, type-based is fine. Use feature-based as soon as you have distinct business domains (auth, checkout, billing, settings).

Quick Check

What's the main organisational benefit of grouping code by feature instead of by file type?

Recap: Feature-Based Structure

features/ contains domain-specific code; shared/ contains cross-feature utilities. Each feature exports a public index.ts. Features don't import from each other — only from shared. Enforce with eslint-plugin-boundaries. Pages/routes compose features. Migrate incrementally. Type-based is fine for small apps.

Frequently asked questions

Is the “Feature-Based Folder Structure” lesson free?

Yes — the full text of “Feature-Based Folder Structure” is free to read here on the web, and the Frontend Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO.

What will I learn in “Feature-Based Folder Structure”?

Organise code by feature domain rather than by type, colocate tests, styles, and components, and enforce boundaries with eslint-plugin-boundaries. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Frontend Academy?

No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Feature-Based Folder Structure” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Frontend Academy lesson?

Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Atomic Design: Atoms Molecules Organisms
  2. Monorepo Setup with Turborepo
  3. Micro-frontends: Module Federation
  4. Feature-Based Folder Structure
← Back to Frontend Academy