Skip to main content
Vue.js for Beginners to Advanced
CHAPTER 03 Beginner

Vue Project Structure

Updated: May 18, 2026
5 min read

# CHAPTER 3

Vue Project Structure

1. Chapter Introduction

A new Vue 3 project looks overwhelming at first — dozens of files and folders. But each file has a clear purpose. Understanding the project structure is the foundation of productive Vue development. This chapter decodes every file and folder.

2. Learning Objectives

  • Understand the role of every folder in src/.
  • Know what main.js, App.vue, and index.html do.
  • Understand the router, stores, components, and assets folders.
  • Read and understand vite.config.js and package.json.

3. Full Project Structure

text
12345678910111213141516171819202122
my-vue-app/
├── public/              # Static files served as-is (favicon, robots.txt)
│   └── favicon.ico
├── src/                 # ALL your source code lives here
│   ├── assets/          # Images, fonts, global CSS
│   │   └── main.css
│   ├── components/      # Reusable UI components
│   │   └── HelloWorld.vue
│   ├── router/          # Vue Router configuration
│   │   └── index.js
│   ├── stores/          # Pinia state stores
│   │   └── counter.js
│   ├── views/           # Page-level components (one per route)
│   │   ├── HomeView.vue
│   │   └── AboutView.vue
│   ├── App.vue          # Root component (parent of everything)
│   └── main.js          # Application entry point
├── index.html           # HTML template (Vite's entry point)
├── vite.config.js       # Vite bundler configuration
├── package.json         # Dependencies and scripts
├── .eslintrc.cjs        # ESLint configuration
└── .prettierrc.json     # Prettier formatting configuration

4. main.js — Application Entry Point

javascript
1234567891011121314
// src/main.js
import { createApp } from 'vue'       // Vue 3 factory function
import { createPinia } from 'pinia'   // Pinia state manager
import App from './App.vue'           // Root component
import router from './router'         // Vue Router

import './assets/main.css'            // Global styles

const app = createApp(App)            // Create the Vue application instance

app.use(createPinia())                // Register Pinia plugin
app.use(router)                       // Register Vue Router plugin

app.mount(&#039;#app&#039;)                     // Mount to <div id="app"> in index.html

5. App.vue — Root Component

vue
12345678910
<!-- src/App.vue -->
<script setup>
// Global navigation, layout wrappers, etc.
import { RouterView } from &#039;vue-router'
</script>

<template>
  <!-- Router renders the current page&#039;s view component here -->
  <RouterView />
</template>

6. index.html — HTML Shell

html
12345678910111213141516
<!-- index.html (project root) -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Vue App</title>
  </head>
  <body>
    <!-- Vue mounts here -->
    <div id="app"></div>
    <!-- Vite injects the bundled JS -->
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

7. router/index.js — Router Configuration

javascript
12345678910111213141516171819202122
// src/router/index.js
import { createRouter, createWebHistory } from &#039;vue-router&#039;
import HomeView from &#039;../views/HomeView.vue&#039;

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: &#039;/&#039;,
      name: &#039;home&#039;,
      component: HomeView  // Eager loaded
    },
    {
      path: &#039;/about&#039;,
      name: &#039;about&#039;,
      // Lazy loaded — only fetched when user visits /about
      component: () => import(&#039;../views/AboutView.vue&#039;)
    }
  ]
})

export default router

8. stores/counter.js — Pinia Store

javascript
1234567891011121314
// src/stores/counter.js
import { defineStore } from &#039;pinia&#039;
import { ref, computed } from &#039;vue&#039;

export const useCounterStore = defineStore(&#039;counter&#039;, () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)

  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})

9. Component vs View

text
123456789
src/components/  — Reusable pieces used across multiple pages
  Button.vue         ← used on Home, About, Contact pages
  Navbar.vue         ← used on every page in App.vue
  ProductCard.vue    ← used in ProductList view

src/views/       — One per route; each is a "page"
  HomeView.vue       ← rendered at route "/"
  AboutView.vue      ← rendered at route "/about"
  ProductView.vue    ← rendered at route "/products/:id"

10. vite.config.js

vite.config.js
12345678910111213
import { defineConfig } from &#039;vite&#039;
import vue from &#039;@vitejs/plugin-vue&#039;
import { fileURLToPath, URL } from &#039;node:url&#039;

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      // @/ maps to src/ — use @/components/Button.vue instead of ../../components/Button.vue
      &#039;@&#039;: fileURLToPath(new URL(&#039;./src&#039;, import.meta.url))
    }
  }
})

11. Common Mistakes

  • Putting page components in components/ instead of views/: Components should be small and reusable. Pages go in views/ and map 1:1 with routes.
  • Not using @/ path alias: Using ../../components/ relative paths breaks when files move. Always use @/ which maps to src/.

12. MCQs

Question 1

Where does Vue mount to in index.html?

Question 2

What is App.vue?

Question 3

What does @/ path alias resolve to?

Question 4

What folder contains page-level components?

Question 5

What does () => import('../views/About.vue') in router do?

Question 6

What does app.use(router) do?

Question 7

Where do global CSS styles go?

Question 8

<RouterView /> in App.vue renders?

Question 9

What is a Pinia store?

Question 10

vite.config.js is for?

13. Interview Questions

  • Q: Explain the role of main.js in a Vue 3 project.
  • Q: What is the difference between components/ and views/ folders?

14. Summary

A Vue 3 Vite project has a clean, predictable structure: main.js bootstraps the app, App.vue is the root, views/ holds pages, components/ holds reusable pieces, router/ configures navigation, and stores/ manages global state. Understanding this structure means understanding Vue architecture itself.

15. Next Chapter Recommendation

In Chapter 4: Vue Syntax and Templates, we master Vue's template language — interpolation, directives, expressions, and event handling — the HTML-first approach to building UIs.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·