DEV Community

Cover image for How I Build Vue 3 Applications (Part 2): How I Decide Where Every Component Belongs
Luka Jioshvili
Luka Jioshvili

Posted on

How I Build Vue 3 Applications (Part 2): How I Decide Where Every Component Belongs

One of the hardest decisions in a growing Vue application isn't writing components.

It's deciding who owns them.

Most projects don't struggle with this on day one.

They struggle six months later, when hundreds of components exist and every new file raises the same question:

Where should this component live?

Over the years, I've settled on a simple decision process that helps me answer that question consistently.

In this article, I'll walk through the questions I ask before creating any new component and explain how those answers determine where it belongs.


Why does the components/ folder eventually become a mess?

At the beginning of a project, almost any component organization feels reasonable.

With only a handful of components, it's easy to remember where everything lives because your mental map is still small.

As the application grows, that changes.

New features introduce dialogs, cards, tables, forms, widgets, and other supporting components.

Eventually, the components/ directory becomes a long list of unrelated files.

Nothing is technically wrong.

But every new component becomes a small architectural decision.

Component Folder Overview

The problem isn't the number of components.

It's what happens to your mental model.

Instead of immediately knowing where something belongs, you start relying on search. Related components become scattered, and the business context begins to disappear.

You're no longer thinking:

"I'm working on Billing."

Instead, you're jumping between dialogs, tables, widgets, and cards just to understand a single feature.

As the project grows, understanding the impact of a change becomes harder, making accidental regressions more likely.

For me, this isn't just a folder problem.

It's a cognitive problem.

As I mentioned in Part 1, I want to understand what I'm looking at before opening a file.

The same principle applies to components.

So before I create a new component, I don't ask:

"Which folder should I put this in?"

Instead, I ask:

"Who owns this component?"

Once I can answer that question, choosing where it belongs becomes almost obvious.


What makes a component a UI component?

The first question I ask whenever I create a new component is simple:

Can another feature reuse it?

If the answer is yes, it belongs in components/ui.

UI components are business-agnostic. They shouldn't know anything about billing, users, products, sessions, or any other feature.

Instead, they provide reusable building blocks that every feature can compose.

Common examples include:

  • Buttons
  • Inputs
  • Dialogs
  • Tooltips
  • Avatars
  • Checkboxes
  • Badges

A good rule of thumb is:

If I could copy this component into another project without changing its behavior, it's probably a UI component.

This is the decision tree I mentally follow whenever I create a component.

Decisitons

Once that decision is made, the folder structure becomes almost obvious.

Here's what that looks like:

Structure

Notice that the folders are organized by UI responsibility, not by business domain.

Buttons live together.

Inputs live together.

Dialogs live together.

Icons live together.

Every category answers the same question:

What kind of UI element is this?

The goal isn't to create the perfect hierarchy, it's to make new components obvious to place and existing ones easy to discover.


Feature Components

If the component isn't reusable across the application, I ask another question:

Is it owned by a single business feature?

If the answer is yes, it belongs in components/features.

Feature components represent actual product functionality.

Unlike UI components, they understand the business they're built for.

That means they're free to depend on services, stores, composables, domain models, and business rules, because that feature owns them.

Feature Components

These components aren't designed to be shared across unrelated parts of the application.

They're designed to solve one business problem well.

A good rule I follow is:

If another feature needs this component, I don't immediately move it to ui.

Duplicating a small component is often cheaper than introducing a premature abstraction.

Only after a component proves it's truly shared do I consider promoting it into components/ui.


Layout Components

Not every component belongs to a business feature.

Some components define the application's shell.

Business features live inside them not the other way around.

A simple rule I use is:

If removing every business feature still leaves this component useful, it's probably a layout component.

Here's what that relationship looks like:

Application Shell

Layout components aren't owned by Billing, Products, or Users.

They're owned by the application itself.


Transition Components

Some components exist for one reason only:

Animation.

They shouldn't contain business logic.

They shouldn't know anything about billing, users, products, or sessions.

Their only responsibility is providing reusable animations on top of Vue's <Transition> component.

For example:

  • FadeTransition
  • ExpandYTransition
  • ExpandXTransition

Separating them keeps animations consistent throughout the application while avoiding duplicated transition code.

More importantly, it creates one source of truth for how things move.

I don't want five slightly different fade animations scattered throughout the project.

I want one.

If I decide to tweak the animation timing, easing, or behavior, I change it once and every feature benefits.

Here's what that looks like in practice.

Transition Components

That's why transition components have their own home.

Their responsibility isn't business logic.

It's making the entire application feel consistent.


Conclusion

There is no single "correct" way to organize components.

Every application grows differently, every team develops its own conventions, and every architecture evolves over time.

The approach I've shared isn't about finding the perfect folder structure.

It's about reducing the number of decisions you have to make every day.

For me, that starts with a single question:

Who owns this component?

Once I can answer that, where it belongs is usually obvious.

That simple shift has made my Vue applications easier to navigate, easier to maintain, and easier to scale as they grow.

Like the hybrid folder structure from Part 1, this isn't a universal rule, it's simply the approach I've refined over the years, and it continues to evolve with every project.

Top comments (0)