Vue, JavaScript, Tutorials Your First Vue 3 App: From Zero to Running in Under 10 Minutes
5 min read
Loading...Your First Vue 3 App: From Zero to Running in Under 10 Minutes
Part 2 of the Vue 3 Fundamentals series — scaffolding a real project and understanding your project structure.
The best way to learn a framework isn’t to read about it. It’s to build something with it. In this article, we’re spinning up a real Vue 3 project — not a CDN snippet, not a playground — an actual scaffolded project with a file structure, a dev server, and hot module reloading. By the end of this, you’ll have something running in your browser and a mental model for how Vue 3 projects are organized.
Here we go :
Prerequisites
You’ll need:
- Node.js (v18 or higher recommended) — nodejs.org
- A terminal you’re comfortable opening
- A code editor (VS Code is great, and the Volar extension gives you first-class Vue support)
That’s it. No global installs required ahead of time.
Scaffolding With create-vue
Vue’s official scaffolding tool is called create-vue. It uses Vite under the hood, which means your dev server starts fast and your builds are quick.
Open your terminal and run:
npm create vue@latest
You’ll be walked through a short setup wizard. For a beginner project, here’s what I’d recommend selecting:
✔ Project name: my-first-vue-app
✔ Add TypeScript? No
✔ Add JSX Support? No
✔ Add Vue Router? No
✔ Add Pinia? No
✔ Add Vitest? No
✔ Add an End-to-End Testing Solution? No
✔ Add ESLint? Yes
✔ Add Prettier? Yes
Let’s skip the extras for now. We’ll introduce them when the time is right. Right now, we want a clean, minimal project.
Once it’s done:
cd my-first-vue-app
npm install
npm run dev
Visit http://localhost:5173 and you should see the default Vue 3 welcome page. You have a running app.
What’s In the Box
Let’s open the project and understand what you’re looking at:
my-first-vue-app/
├── public/ → Static files served as-is (favicon, etc.)
├── src/
│ ├── assets/ → Images, fonts, CSS
│ ├── components/ → Your reusable UI building blocks
│ ├── App.vue → The root component of your app
│ └── main.js → The entry point — where Vue mounts to the DOM
├── index.html → The single HTML file that hosts your app
├── package.json → Your project dependencies and scripts
└── vite.config.js → Vite configuration
The most important files for right now are main.js, App.vue, and index.html.
How Vue Boots Up
Open index.html. You’ll see something like this near the bottom:
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
There’s a single empty div with the id app. That’s where Vue lives. Your entire application will render inside it.
Now open src/main.js:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Three things are happening here:
- We import the
createAppfunction from Vue - We import our root component (
App.vue) - We create the Vue application and mount it to the
#appdiv in our HTML
That’s it. Vue takes over that div and everything inside it.
Your First Real Component ~ Voilà
Now open src/App.vue. Delete everything in it and let’s write something from scratch.
<script setup>
import { ref } from 'vue'
const name = ref('developer')
const greeting = ref('Hello')
</script>
<template>
<main>
<h1>{{ greeting }}, {{ name }}!</h1>
<input v-model="name" placeholder="Enter your name" />
<button @click="greeting = 'Hey there'">Switch greeting</button>
</main>
</template>
<style scoped>
main {
max-width: 600px;
margin: 4rem auto;
font-family: sans-serif;
display: flex;
flex-direction: column;
gap: 1rem;
}
h1 {
font-size: 2rem;
}
</style>
Save it. Go back to your browser. You should see a heading, an input field, and a button.
Type into the input. Watch the heading update in real time. Click the button. Watch the greeting change. And you didn’t write a single line of DOM manipulation.
That’s Vue doing its thing.
Breaking Down That Component
A Vue Single-File Component (SFC) has three sections, and you can see all three in what we just wrote:
<script setup> — This is where your component’s logic lives. We imported ref from Vue (more on that in Article 3), created two reactive variables, and because we’re using <script setup>, they’re automatically available in the template.
<template> — This is your HTML. Vue extends it with special syntax: {{ }} for displaying data, v-model for two-way binding (typing in the input updates the variable), and @click for event handling.
<style scoped> — Your CSS. The scoped attribute means these styles only apply to this component, not the whole page. No more accidentally styling something in another component.
This is the structure you’ll use for every Vue component you write.
The Dev Experience
One thing worth mentioning: Vite’s dev server is fast. Changes you save appear in the browser almost instantly through Hot Module Replacement (HMR). The browser doesn’t fully reload — it surgically updates just the component you changed. This makes the feedback loop tight. You write, you see, you iterate. That loop is your best learning tool.
Your Turn
Before moving to Article 3, try this:
- Add a third
refvariable calledcountinitialized to0 - Add a button that increments it:
@click="count++" - Display it in the template:
<p>Count: {{ count }}</p>
If it works — and it should — you just built reactivity by instinct. That’s the goal.
What’s Next
In Article 3, we go deeper into reactivity — the engine that makes everything in Vue feel alive. We’ll cover ref vs reactive, computed properties, and the watch API.
You’re already writing Vue. Now let’s understand why it works.
This is Part 2 of the Vue 3 Fundamentals series. Sources: Vue.js Official Docs, Vue School.