Skip to the solution
EasyFrontend11 min read

How do you create a new Vue 3 app, and what is in the project structure?

650 views

The problem

Question presented to candidate: "You are starting a brand-new Vue 3 project today. How do you create it, and can you walk me through the files and folders it generates and what each one is for?"

What a strong answer should cover:

  • The official scaffolder is create-vue, run with npm create vue@latest; it creates a Vite-based project. Vue CLI (webpack) is in maintenance mode and not used for new projects.
  • Optional features chosen at creation: TypeScript, JSX, Vue Router, Pinia, Vitest, Cypress or Playwright, ESLint and Prettier.
  • The flow from index.html (the real entry, with <div id="app"> and a module script) to src/main.ts (createApp(App).mount('#app')) to src/App.vue and the component tree.
  • The roles of src/components, src/assets, public/, vite.config.ts (the Vue plugin and the @ alias), package.json scripts, the tsconfig files and env.d.ts.
  • The commands: npm install, npm run dev (dev server with hot module replacement), npm run build (type-check plus production build into dist/) and npm run preview.
  • Where router and store files land when those features are selected (src/router/index.ts, src/stores/, src/views/).

Clarifying questions expected:

  • "Do we need routing, a store or tests from day one, or start minimal?"
  • "TypeScript or plain JavaScript, and is server-side rendering (Nuxt) a requirement?"

Code / implementation expected: Yes. The scaffolding command, the generated main.ts, and a first App.vue.

  • vue
  • setup
  • vite
  • project-structure

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

11 min read Β· 10 sections

Read the code

Scaffold, run and build a Vue 3 project with create-vue
# Interactive: prompts for the project name and each optional feature
npm create vue@latest

# Non-interactive: flags skip the prompts (create-vue 3.24.0)
npm create vue@latest -- --default my-vue-app            # TypeScript, no extras
npm create vue@latest -- --ts --router --pinia --vitest --eslint my-vue-ts
npm create vue@latest -- --bare --router my-bare          # no starter components

cd my-vue-app
npm install        # install dependencies into node_modules
npm run dev        # Vite dev server with hot module replacement
npm run build      # vue-tsc type-check + vite build into dist/
npm run preview    # serve dist/ locally to check the production build
src/main.ts and vite.config.ts as create-vue 3.24.0 generates them (file-name comments added)
// ── src/main.ts ──────────────────────────────────────────
import './assets/main.css'

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

createApp(App).mount('#app')

// ── vite.config.ts ───────────────────────────────────────
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueDevTools(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
})
VueA first replacement for the starter src/App.vue
<!-- src/App.vue: a first replacement for the scaffolded starter page. -->
<!-- main.ts mounts this component with createApp(App).mount("#app"). -->
<script setup>
import { ref, version } from "vue";

const tasks = ref(["Run npm install", "Run npm run dev"]);
const draft = ref("");

function add() {
  if (draft.value.trim()) tasks.value.push(draft.value.trim());
  draft.value = "";
}
</script>

<template>
  <header>
    <h1>My first Vue {{ version }} app</h1>
  </header>
  <main>
    <form @submit.prevent="add">
      <input v-model="draft" placeholder="Next step" />
      <button>Add</button>
    </form>
    <ul>
      <li v-for="task in tasks" :key="task">{{ task }}</li>
    </ul>
  </main>
</template>

<style scoped>
header { border-bottom: 1px solid #ddd; }
</style>

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 12 of 92 in Vue.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Vue.js questions
Up nextEasy

What are scoped styles in Vue?

Continue