Every Vue project starts the same way, and knowing what each generated file does makes the rest of the tooling unsurprising.
Vue is a progressive framework: you can drop it into one page, but most projects are single-page apps built with Vite. Scaffold one with npm create vue@latest; it asks about TypeScript, Vue Router, Pinia and testing, then generates a project you run with npm install and npm run dev.
The building block is the single-file component (SFC), a .vue file with up to three blocks:
<script setup>— the component's logic, written with the Composition API. Every top-level variable, function and import is usable in the template.<template>— HTML-like markup with Vue's bindings and directives.<style scoped>— CSS that applies only to this component's elements.
The entry file main.js creates the application and mounts the root component into an element in index.html:
createApp(App).mount('#app')createApp returns an app instance where you register app-wide things before mounting: plugins (app.use(router)), global components and app.config.errorHandler. Vite compiles each SFC into plain JavaScript: the template becomes an optimised render function, so there is no template parsing in the browser.
Install the official Vue browser devtools early; they show the component tree, state and events, and save hours of console.log debugging.
Example
<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
const name = 'Vue'
const count = ref(0)
</script>
<template>
<h1>Hello {{ name }}!</h1>
<button @click="count++">Clicked {{ count }} times</button>
</template>
<style scoped>
h1 { color: #3b8d63; } /* only affects this component's h1 */
</style>
<!-- src/main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
-->Remember
npm create vue@latestscaffolds a Vite + Vue project- An SFC has
<script setup>,<template>and<style scoped>blocks createApp(App).mount('#app')boots the app; register plugins before mounting
Watch out for
- Calling
app.use(...)aftermount(); plugins must be installed before the app mounts.