Skip to content

How to Structure Vue Projects

Updated: at 

Quick Summary

This post covers specific Vue project structures suited for different project sizes:

Table of Contents

Open Table of Contents

Introduction

When starting a Vue project, one of the most critical decisions you’ll make is how to structure it. The right structure enhances scalability, maintainability, and collaboration within your team. This consideration aligns with Conway’s Law:

“Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.”
— Mel Conway

In essence, your Vue application’s architecture will reflect your organization’s structure, influencing how you should plan your project’s layout.

Diagram of Conway's Law

Whether you’re building a small app or an enterprise-level solution, this guide covers specific project structures suited to different scales and complexities.


1. Flat Structure: Perfect for Small Projects

Are you working on a small-scale Vue project or a proof of concept? A simple, flat folder structure might be the best choice to keep things straightforward and avoid unnecessary complexity.

/src
|-- /components
|   |-- BaseButton.vue
|   |-- BaseCard.vue
|   |-- PokemonList.vue
|   |-- PokemonCard.vue
|-- /composables
|   |-- usePokemon.js
|-- /utils
|   |-- validators.js
|-- /layout
|   |-- DefaultLayout.vue
|   |-- AdminLayout.vue
|-- /plugins
|   |-- translate.js
|-- /views
|   |-- Home.vue
|   |-- PokemonDetail.vue
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /tests
|   |-- ...
|-- App.vue
|-- main.js

Pros and Cons

✅ Pros❌ Cons
Easy to implementNot scalable
Minimal setupBecomes cluttered as the project grows
Ideal for small teams or solo developersLack of clear separation of concerns

2. Atomic Design: Scalable Component Organization

Atomic Design Diagram

For larger Vue applications, Atomic Design provides a clear structure. This approach organizes components into a hierarchy from simplest to most complex.

The Atomic Hierarchy

This method ensures scalability and maintainability, facilitating a smooth transition between simple and complex components.

/src
|-- /components
|   |-- /atoms
|   |   |-- AtomButton.vue
|   |   |-- AtomIcon.vue
|   |-- /molecules
|   |   |-- MoleculeSearchInput.vue
|   |   |-- MoleculePokemonThumbnail.vue
|   |-- /organisms
|   |   |-- OrganismPokemonCard.vue
|   |   |-- OrganismHeader.vue
|   |-- /templates
|   |   |-- TemplatePokemonList.vue
|   |   |-- TemplatePokemonDetail.vue
|-- /pages
|   |-- PageHome.vue
|   |-- PagePokemonDetail.vue
|-- /composables
|   |-- usePokemon.js
|-- /utils
|   |-- validators.js
|-- /layout
|   |-- LayoutDefault.vue
|   |-- LayoutAdmin.vue
|-- /plugins
|   |-- translate.js
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /tests
|   |-- ...
|-- App.vue
|-- main.js

Pros and Cons

✅ Pros❌ Cons
Highly scalableCan introduce overhead in managing layers
Organized component hierarchyInitial complexity in setting up
Reusable componentsMight be overkill for smaller projects
Improves collaboration among teams

3. Modular Approach: Feature-Based Organization

As your project scales, consider a Modular Monolithic Architecture. This structure encapsulates each feature or domain, enhancing maintainability and preparing for potential evolution towards microservices.

/src
|-- /core
|   |-- /components
|   |   |-- BaseButton.vue
|   |   |-- BaseIcon.vue
|   |-- /models
|   |-- /store
|   |-- /services
|   |-- /views
|   |   |-- DefaultLayout.vue
|   |   |-- AdminLayout.vue
|   |-- /utils
|   |   |-- validators.js
|-- /modules
|   |-- /pokemon
|   |   |-- /components
|   |   |   |-- PokemonThumbnail.vue
|   |   |   |-- PokemonCard.vue
|   |   |   |-- PokemonListTemplate.vue
|   |   |   |-- PokemonDetailTemplate.vue
|   |   |-- /models
|   |   |-- /store
|   |   |   |-- pokemonStore.js
|   |   |-- /services
|   |   |-- /views
|   |   |   |-- PokemonDetailPage.vue
|   |   |-- /tests
|   |   |   |-- pokemonTests.spec.js
|-- /search
|   |-- /components
|   |   |-- SearchInput.vue
|   |-- /models
|   |-- /store
|   |   |-- searchStore.js
|   |-- /services
|   |-- /views
|   |-- /tests
|   |   |-- searchTests.spec.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /scss
|-- App.vue
|-- main.ts
|-- router.ts
|-- store.ts
|-- /tests
|   |-- ...
|-- /plugins
|   |-- translate.js

Alternative: Simplified Flat Feature Structure

A common pain point in larger projects is excessive folder nesting, which can make navigation and file discovery more difficult. Here’s a simplified, flat feature structure that prioritizes IDE-friendly navigation and reduces cognitive load:

/features
|-- /project
|   |-- project.composable.ts
|   |-- project.data.ts
|   |-- project.store.ts
|   |-- project.types.ts
|   |-- project.utils.ts
|   |-- project.utils.test.ts
|   |-- ProjectList.vue
|   |-- ProjectItem.vue

This structure offers key advantages:


4. Feature-Sliced Design: For Complex Applications

Feature-Sliced Design is ideal for big, long-term projects. This approach breaks the application into different layers, each with a specific role.

Feature-Sliced Design Diagram

Layers of Feature-Sliced Design

/src
|-- /app
|   |-- App.vue
|   |-- main.js
|   |-- app.scss
|-- /processes
|-- /pages
|   |-- Home.vue
|   |-- PokemonDetailPage.vue
|-- /widgets
|   |-- UserProfile.vue
|   |-- PokemonStatsWidget.vue
|-- /features
|   |-- pokemon
|   |   |-- CatchPokemon.vue
|   |   |-- PokemonList.vue
|   |-- user
|   |   |-- Login.vue
|   |   |-- Register.vue
|-- /entities
|   |-- user
|   |   |-- userService.js
|   |   |-- userModel.js
|   |-- pokemon
|   |   |-- pokemonService.js
|   |   |-- pokemonModel.js
|-- /shared
|   |-- ui
|   |   |-- BaseButton.vue
|   |   |-- BaseInput.vue
|   |   |-- Loader.vue
|   |-- lib
|   |   |-- api.js
|   |   |-- helpers.js
|-- /assets
|   |-- /images
|   |-- /styles
|-- /router
|   |-- index.js
|-- /store
|   |-- index.js
|-- /tests
|   |-- featureTests.spec.js

Pros and Cons

✅ Pros❌ Cons
High cohesion and clear separationInitial complexity in understanding the layers
Scalable and maintainableRequires thorough planning
Facilitates team collaborationNeeds consistent enforcement of conventions

5. Micro Frontends: Enterprise-Level Solution

Micro frontends apply the microservices concept to frontend development. Teams can work on distinct sections of a web app independently, enabling flexible development and deployment.

Micro Frontend Diagram

Key Components

Pros and Cons

✅ Pros❌ Cons
Independent deploymentsHigh complexity in orchestration
Scalability across large teamsRequires robust infrastructure
Technology-agnostic approachPotential inconsistencies in user experience

Conclusion

Conclusion

Selecting the right project structure depends on your project’s size, complexity, and team organization. The more complex your team or project is, the more you should aim for a structure that facilitates scalability and maintainability.

Your project’s architecture should grow with your organization, providing a solid foundation for future development.

Comparison Chart

ApproachDescription✅ Pros❌ Cons
Flat StructureSimple structure for small projectsEasy to implementNot scalable, can become cluttered
Atomic DesignHierarchical component-based structureScalable, organized, reusable componentsOverhead in managing layers, initial complexity
Modular ApproachFeature-based modular structureScalable, encapsulated featuresPotential duplication, requires discipline
Feature-Sliced DesignFunctional layers and slices for large projectsHigh cohesion, clear separationInitial complexity, requires thorough planning
Micro FrontendsIndependent deployments of frontend componentsIndependent deployments, scalableHigh complexity, requires coordination between teams

General Rules and Best Practices

Before concluding, let’s highlight some general rules you can apply to every structure. These guidelines are important for maintaining consistency and readability in your codebase.

Base Component Names

Use a prefix for your UI components to distinguish them from other components.

Bad:

components/
|-- MyButton.vue
|-- VueTable.vue
|-- Icon.vue

Good:

components/
|-- BaseButton.vue
|-- BaseTable.vue
|-- BaseIcon.vue

Group related components together by naming them accordingly.

Bad:

components/
|-- TodoList.vue
|-- TodoItem.vue
|-- TodoButton.vue

Good:

components/
|-- TodoList.vue
|-- TodoListItem.vue
|-- TodoListItemButton.vue

Order of Words in Component Names

Component names should start with the highest-level words and end with descriptive modifiers.

Bad:

components/
|-- ClearSearchButton.vue
|-- ExcludeFromSearchInput.vue
|-- LaunchOnStartupCheckbox.vue

Good:

components/
|-- SearchButtonClear.vue
|-- SearchInputExclude.vue
|-- SettingsCheckboxLaunchOnStartup.vue

Organizing Tests

Decide whether to keep your tests in a separate folder or alongside your components. Both approaches are valid, but consistency is key.

Approach 1: Separate Test Folder

/vue-project
|-- src
|   |-- components
|   |   |-- MyComponent.vue
|   |-- views
|   |   |-- HomeView.vue
|-- tests
|   |-- components
|   |   |-- MyComponent.spec.js
|   |-- views
|   |   |-- HomeView.spec.js

Approach 2: Inline Test Files

/vue-project
|-- src
|   |-- components
|   |   |-- MyComponent.vue
|   |   |-- MyComponent.spec.js
|   |-- views
|   |   |-- HomeView.vue
|   |   |-- HomeView.spec.js

Additional Resources


Questions or thoughts?

Follow me on X for more TypeScript, Vue, and web dev insights! Feel free to DM me with:

  • Questions about this article
  • Topic suggestions
  • Feedback or improvements
Connect on X

Related Posts