Skip to content

How to Structure Vue Projects: From Simple Apps to Enterprise Solutions

Updated: at 

Quick Summary

This post covers various Vue project structures suitable 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 various 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.

Click to view folder structure
/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 methodology can be advantageous. 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.

Click to view folder structure
/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.

Click to view folder structure
/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

Pros and Cons

✅ Pros❌ Cons
Enhances scalabilityPotential code duplication
Encapsulated featuresCan become complex if not managed properly
Easier team collaborationRequires discipline in module boundaries
Prepares for future microservices transition

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

Click to view folder structure
/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. Microfrontends: Enterprise-Level Solution

Microfrontends take the concept of microservices to the frontend. Different teams can work on various sections of a web app independently, allowing for flexible development and deployment.

Microfrontend 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
MicrofrontendsIndependent 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

Tightly Coupled Component Names

Group tightly coupled 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


Related Posts