estructura-app-vue

Structure of a Vue.js Project

  • 7 min

Now that we’ve seen how to create our Vue application, we’ll see that the project we’ve created has a structure with folders and files (in fact, with many).

In reality, not all projects are exactly the same. In the end, the structure depends on your application, the elements you use… on many things.

But, more or less, a “typical” Vue.js project could have a structure similar to this,

📂 mi-app/ ├── 📂 node_modules/ ├── 📂 public/ ├── 📂 src/ │ ├── 📂 assets/ │ ├── 📂 components/ │ ├── 📂 views/ │ ├── 📂 router/ │ ├── 📂 stores/ │ ├── 📂 services/ │ ├── 📂 utils/ │ ├── 📄 App.vue │ └── 📄 main.js ├── 📄 .eslintrc.js ├── 📄 .gitignore ├── 📄 index.html ├── 📄 package.json └── 📄 vite.config.js

As I said, it’s not a single, unchangeable structure. The organization will depend on your project, and even on your preferences. You have room for the structure.

But many of the elements are common and frequent in Vue projects. You need, at least, to know what each thing is.

So let’s review some of them, because at the beginning it can be a bit overwhelming to see so many files and folders.

Files in the Project Root

Index.html

HTML entry point of the application:

File/DirectoryFunction
index.htmlMain HTML template; Vue is mounted inside this file.
<!DOCTYPE html>
<html lang="es">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mi Aplicación Vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>
Copied!

/src Directory

This is the heart of the project where all the source code resides:

FileFunction
src/Contains all the application’s source code.
src/main.js or main.tsMain entry point of the application; mounts the app to the DOM.
src/App.vueRoot component of the application.

Application entry point. Here Vue is mounted and the application is configured.

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

import './assets/main.css'

const app = createApp(App)

app.use(router)

app.mount('#app')
Copied!

The root component of the application:

<script setup>
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <header>
    <img alt="Vue logo" src="./assets/logo.svg" width="125" height="125" />
    <div class="wrapper">
      <HelloWorld msg="¡Bienvenido a tu aplicación Vue 3!" />
      <nav>
        <RouterLink to="/">Inicio</RouterLink>
        <RouterLink to="/about">Acerca de</RouterLink>
      </nav>
    </div>
  </header>

  <RouterView />
</template>

<style scoped>
header {
  line-height: 1.5;
  max-height: 100vh;
}

/* More styles... */
</style>
Copied!

Subdirectories of src

DirectoryFunction
src/assets/Resources like images, styles, and fonts, processed by Vite.
src/components/Reusable UI components.
src/views/Main views associated with routes.
src/router/Routing system configuration with Vue Router.
src/stores/Global state management (Pinia).
src/services/Modules for accessing APIs or external logic.
src/composables/Reusable functions with Composition API.
src/utils/General utility functions, like validations or formatting.

This directory contains static resources like images, fonts, and global styles. Unlike files in public/, files in assets/ are processed by Vue’s build system.

import '@/assets/global.css';
Copied!

This directory stores static resources that will be processed by Vite. For example,

assets/
├── logo.svg
└── main.css
Copied!

This directory stores reusable Vue components. Components in Vue are independent pieces of interface that we can combine to build the application’s structure.

Each Vue component has its own .vue file, which includes the template, script, and styles.

Components should be named using PascalCase (HelloWorld.vue) or kebab-case (hello-world.vue) format to follow Vue conventions. For example,

components/
├── HelloWorld.vue
├── TheHeader.vue
├── TheFooter.vue
└── ui/
    ├── BaseButton.vue
    └── BaseInput.vue
Copied!

Here we store the main views of the application, which are usually associated with specific Vue Router routes. For example,

views/
├── HomeView.vue
└── AboutView.vue
Copied!

Here we configure Vue Router to manage navigation in our application. For example,

router/
└── index.js
Copied!

For state management with Pinia (if we use it, of course). For example,

stores/
└── counter.js
Copied!

For APIs and external services. For example,

services/
├── api.js
└── authService.js
Copied!

Composables are reusable functions that encapsulate shared logic. For example,

utils/
├── useFilterTable.js
└── useValidateNumber.js
Copied!

For utility functions. For example,

utils/
├── formatter.js
└── validation.js
Copied!

Remember that these are examples of folders you will commonly find. It doesn’t mean you have to have all of them by obligation.

Public Folder

The public/ directory contains static files that are served directly without going through Vue’s build process.

Here you can place files like index.html, images, fonts, or any other static resource.

public/
├── favicon.ico
└── robots.txt
Copied!

Example: If we add an image logo.png in public/, we can access it from:

localhost:5173/logo.png

What’s the difference between assets and public?

  • Files in src/assets/ are processed by the bundle (they can be imported via modules and optimized, etc)
  • Files in public/ are copied without modifications to the server root when we build the application