Getting Started with Vue 3 (Composition API Edition): Build Your First App from Scratch
Updated to use the Vue 3 Composition API (with <script setup>
syntax) so your code is modern, concise, and production-ready.
Why This Guide?
If you’re curious about frontend development and want a powerful but beginner-friendly JavaScript framework, Vue.jsis a great place to start. In this guide, you’ll create a working Vue 3 app using Vite and the Composition API. By the end, you’ll understand the moving parts well enough to expand it on your own.
Good to know: The Composition API provides a more flexible way to organize logic in Vue 3 compared to the older Options API. It’s easier to reuse reactive logic across components, works well with TypeScript, and is the recommended approach for most new Vue projects.
What Is Vue, and Why Should You Care?
Vue is a progressive JavaScript framework for building interactive user interfaces. It scales from small interactive widgets to full-featured single-page applications (SPAs).
Why developers love Vue:
Simple to learn: Gentle learning curve—great for beginners.
Reactive: UI updates automatically when state changes.
Component-based: Build UIs from small, reusable blocks.
Composition API power: Co-locate related code, create composable logic functions, and improve maintainability.
With Vue 3 you also get performance improvements, better TypeScript support, and first-class tooling—especially when paired with Vite.
A Quick Word on Single-Page Applications (SPA)
A Single Page Application loads a base HTML page once and updates the visible content dynamically via JavaScript as users navigate or interact. Instead of full page reloads, the app swaps views or components, resulting in a faster, more app-like experience.
Why Use Vite?
Vite (created by Evan You, who also created Vue) is a lightning-fast build tool and dev server.
With Vite, you get:
Instant startup with native ES module–based dev server.
Hot Module Replacement (HMR): See changes in the browser as you save files.
First-class Vue 3 support via official plugins.
In short: Vite + Vue 3 = a smooth developer experience.
Let’s Build Your First Vue App (Composition API)
We’ll scaffold a new project, clean up boilerplate, and build a tiny app with a title and a reusable counter component.
Step 1: Scaffold the Project
Make sure you have Node.js installed (LTS version recommended).
Open your terminal and run:
npm create vite@latest vue-first-app -- --template vue
cd vue-first-app
npm install
npm run dev
You should see the default Vite + Vue starter at:
http://localhost:5173
Step 2: Replace Boilerplate with Your App
We’ll create a simple App.vue
and a Counter.vue
component using the Composition API and <script setup>
—the recommended single-file component syntax in Vue 3.
Your project structure will look something like:
vue-first-app/
├─ index.html
├─ src/
│ ├─ main.js
│ ├─ App.vue
│ └─ components/
│ └─ Counter.vue
├─ package.json
└─ ...
main.js
: Entry Point
This file mounts your root component (App.vue
) into the DOM.
src/main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
This tells Vue: Render the App
component inside the element with the id app
in index.html
.
App.vue
: Your Root Component (Composition API)
We’ll use <script setup>
plus Vue’s ref()
to make reactive state. Unlike data()
in the Options API, ref
and reactive
are imported functions you use directly in your script.
src/App.vue
<template>
<div class="app">
<h1>{{ title }}</h1>
<Counter />
</div>
</template>
<script setup>
import { ref } from 'vue'
import Counter from './components/Counter.vue'
// Reactive state using Composition API
const title = ref('My First Vue App')
</script>
<style scoped>
.app {
font-family: Arial, sans-serif;
padding: 20px;
}
h1 {
color: #42b983;
}
</style>
What’s Happening?
We import
ref
and declare a reactive stringtitle
.Values from
ref
are accessed as.value
in JavaScript but unwrapped automatically in templates, so{{ title }}
works.We import and render the
<Counter />
child component.
Counter.vue
: A Reactive Button (Composition API)
We’ll build a stand-alone component with a local counter that increments when clicked.
src/components/Counter.vue
<template>
<div>
<button @click="increment">
Count is: {{ count }}
</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
// Local reactive state
const count = ref(0)
// Methods are just functions in script scope
function increment() {
count.value++
}
</script>
<style scoped>
button {
padding: 10px 20px;
background-color: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:focus {
outline: 2px solid #2c8c6b;
outline-offset: 2px;
}
</style>
What’s Happening?
count
is aref(0)
, so Vue tracks its changes.The
increment()
function updatescount.value
.The template shows
count
and callsincrement
when clicked.Template ref unwrapping allows
{{ count }}
instead of{{ count.value }}
.
Shortcut: You could do
<button @click="count++">
because Vue unwraps refs in templates, but the explicitincrement()
handler is clearer for beginners and easier to extend.
Run the Dev Server
From your project root:
npm run dev
Visit:
http://localhost:5173
Your app should display the title and the counter button. Click to increase the count—Vue updates instantly thanks to reactivity.
Build for Production
When you’re ready to deploy:
npm run build
This creates an optimized production build (usually in dist/
). You can preview it locally:
npm run preview
Serve the generated files from any static host (Netlify, Vercel, Firebase Hosting, GitHub Pages, etc.).
How the Composition API Differs From the Options API
ConceptOptions APIComposition APIBenefitStatedata()
return objectref()
/ reactive()
Explicit, type-friendly, easy to extractMethodsmethods:
objectplain functionsSimple, tree-shakeableLifecyclemounted()
, etc.onMounted()
, etc.Can group related logic togetherReuseMixins, extendsComposables (functions)Cleaner, no name collisions
What You’ve Learned
By now you’ve:
Scaffolded a Vue 3 + Vite project.
Built components using the Composition API and
<script setup>
.Created reactive state with
ref
.Used event handlers to update state and re-render the UI.
Built & previewed a production bundle.
Example Repo Structure
If you’d like to share code, create a GitHub repo with a structure like this:
vue-first-app/
├─ README.md
├─ package.json
├─ vite.config.js
├─ index.html
└─ src/
├─ main.js
├─ App.vue
└─ components/
└─ Counter.vue
Final Thoughts
Vue makes frontend development fun and approachable. With the Composition API, your code stays organized as your app grows. Combine Vue with Vite for a fast, modern development workflow—even if you’re just starting out.