How to Structure Your Vue.js Project Correctly
A house is only as strong as its foundation. The same applies to your Vue.js applications. If you don't organize your files and folders properly from day one, your project will quickly become a mess. Let's look at the best way to structure a modern Vue.js application.
The Ideal Root Structure
When you use create-vue to generate a new project, it gives you a basic
src/ folder. However, for a real-world application, you need to expand it.
Here is the standard folder structure used by professional teams:
src/
├── assets/ # Static files like images, fonts, and global CSS
├── components/ # Reusable Vue components (buttons, modals, cards)
├── composables/ # Reusable Vue 3 Composition API logic
├── layouts/ # Page wrappers (e.g., MainLayout, AuthLayout)
├── router/ # Vue Router configuration
├── services/ # API calls and external services
├── stores/ # Pinia or Vuex state management
├── views/ # Page components (Home.vue, About.vue)
├── App.vue # The main root component
└── main.js # The entry file that mounts the Vue app
1. Components vs. Views
Many beginners confuse components and views. A simple rule is:
-
Views (or Pages): These are directly linked to a URL route. For
example,
HomeView.vueorDashboardView.vue. They usually fetch data and pass it down. -
Components: These are reusable pieces of UI that you use
inside your views. Examples include
Navbar.vue,PrimaryButton.vue, orUserCard.vue.
2. The Power of Composables
In Vue 3, you can write standalone logic functions called "Composables". If you find
yourself writing the same piece of code in multiple components (like checking if the
user is clicking outside a menu, or formatting a date), you should extract it into a
file in the
composables/ folder. By convention, name these files starting with "use",
like useClickOutside.js.
3. Keep API Calls in Services
Do not write fetch() or axios.get() directly inside your Vue
components! This makes testing difficult and your code messy. Create a
services/ folder and put your API logic there. For example, create an
authService.js file that exports a login() function. Then,
import and call that function in your component.
4. Manage Global Data in Stores
If a piece of data needs to be accessed by many different pages (like the current user's
profile, or items in a shopping cart), keep it in the stores/ folder using
Pinia. If the data is only used on one page, keep it as local state inside the component
using ref() or reactive().
Final Thoughts
By following this folder structure, your code will be predictable. When a new developer joins your team, they will immediately know where to look for an API call, where to find a button component, and where the page layouts live. Consistency is the secret to maintainable code.
Jiss Johnson
Senior Vue.js Engineer helping companies build scalable frontend architectures. Open to new opportunities.