What is Vue?

Vue is a JavaScript framework for building user interfaces. It was created by Evan You - originally a solo project he started in 2014 while at Google - and is now developed at VoidZero, the company he co-founded to keep Vue, Vite, Vitest, Rolldown, and Oxc moving forward as a coherent toolchain. The framework is open-source under the MIT license and ships through the vue npm package.

The defining word is progressive. Vue is designed to scale with the size of the problem - drop it into one page for a sprinkle of interactivity, or use it as the foundation for a full single-page application. Sitting between Angular's everything-included posture and React's minimalist library posture, Vue tends to be the framework people describe as "the one that felt friendly."

An approachable, performant and versatile framework for building web user interfaces.- vuejs.org

The progressive idea

Most JavaScript frameworks ask you to commit. You scaffold a project from a template, you accept a build pipeline, and from then on every page on the site is a framework page. Vue can be used that way - and most teams do - but the framework was designed with a softer entry point.

You can drop Vue into a single HTML file with a script tag, mount it on one element of one page, and leave the rest of the site alone:

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<div id="app">{{ greeting }}</div>

<script>
  Vue.createApp({
    data: () => ({ greeting: "Hello from Vue" })
  }).mount("#app");
</script>

From that floor you can grow into anything: a single component on a marketing page, a richer widget, a multi-page Vue app, or a full Nuxt application with server rendering and filesystem routing. The mental model and the syntax stay the same. The framework grows as your project does, rather than asking for the commitment up front.

Single-file components

The canonical Vue component lives in a .vue file - a Single-File Component, or SFC. The file holds the template, the script, and the styles for one component in one place, cleanly separated:

<!-- Counter.vue -->
<script setup>
import { ref, computed } from "vue";

const count = ref(0);
const doubled = computed(() => count.value * 2);
</script>

<template>
  <button @click="count++">
    Clicked {{ count }} times - that is {{ doubled }} doubled.
  </button>
</template>

<style scoped>
button { padding: 10px 16px; border-radius: 8px; }
</style>

A few details worth catching:

  • The three blocks (<script>, <template>, <style>) are all optional, but <template> is what most components use to describe their markup.
  • <style scoped> automatically scopes the CSS to this component. A button selector here will not leak to other components - Vue rewrites the selector at build time.
  • script setup is the modern, terser form of the Composition API. Everything declared at the top level is available in the template; no return, no export default.
  • The file itself is the component. Importing it gets you a component you can mount, pass props to, or use in a parent's template.

Compiled by the @vitejs/plugin-vue plugin (which ships with the official Vite template), an SFC turns into a regular JavaScript module at build time. The browser never sees the .vue file.

Reactivity and the Composition API

Vue's reactivity system is its calling card. The framework gives you a small set of primitives that mark values as reactive, and from there the framework tracks which parts of the template depend on which values and updates the DOM precisely when those values change.

  • ref(initial) - a single reactive value. Read and write via .value in script; the template unwraps it automatically.
  • reactive(obj) - a reactive proxy of an object. Property access feels like the original object; reads register a dependency, writes trigger updates.
  • computed(fn) - a value derived from other reactive state. Recomputes when its dependencies change; otherwise returns the cached result.
  • watch(source, callback) and watchEffect(fn) - reactive side effects, for the cases that do not fit a template binding.

These primitives make up the Composition API, the modern way to organize a Vue component's logic. The older Options API - data(), methods, computed, lifecycle hooks as named properties - still exists, still works, and is the natural shape for very small components. Most new code uses the Composition API, often through <script setup>.

The Composition API is conceptually similar to React's hooks: a way to bundle related state, derived values, and side effects together and reuse them across components. Vue's version is built on the framework's own reactivity primitives rather than the runtime call-order dance hooks rely on, which makes some patterns simpler - computed values, for example, are first-class instead of a special-cased useMemo.

Templates and directives

Vue uses HTML-based templates rather than JSX. Inside a <template> block you write what looks like ordinary HTML, with two additions:

  • Interpolation with {{ }} for expressions: {{ greeting }}, {{ user.name.toUpperCase() }}.
  • Directives, which are special attributes prefixed with v- that the compiler recognizes and turns into reactive behavior.

The directives you will use most often:

  • v-if / v-else / v-show - conditional rendering and visibility.
  • v-for - list rendering. <li v-for="item in items" :key="item.id">.
  • v-bind (shorthand :) - bind an HTML attribute to a reactive expression. :href="url".
  • v-on (shorthand @) - event listener. @click="handler".
  • v-model - two-way binding for form inputs and custom components. <input v-model="name">.

The template syntax is the part of Vue that designers and HTML-first developers most often single out as the reason they reached for it instead of React. The mental model is "HTML with reactive attributes" rather than "JavaScript that returns markup."

The official ecosystem

One of Vue's quieter strengths is that the official ecosystem is small, coherent, and maintained by the core team. There is one canonical answer for each common need:

  • Vue Router - the official client-side router. Filesystem-free, configured in code, deeply integrated with Vue's reactivity.
  • Pinia - the official state-management library. Lightweight, Composition-API-shaped, the successor to Vuex.
  • Nuxt - the meta-framework. Filesystem routing, server rendering, data fetching, deployment adapters - the Vue equivalent of Next.js, built on Vite.
  • Vitest - the Vite-native test runner. Built by the same broader team; pairs naturally with Vue projects.
  • Vue DevTools - the browser extension and standalone app for inspecting components, reactivity, and routes during development.

Because Vite, Vue, Vitest, Pinia, Nuxt, and Rolldown are all maintained by overlapping people at VoidZero and the broader Vue team, the integration story between them is unusually smooth. Upgrades land in lockstep; the canonical way to do each common task is the documented way.

Where Vue fits

Vue tends to feel like the right call for a few specific shapes of project:

  • Teams adding interactivity to existing content sites. The progressive entry point genuinely matters here - you do not have to rebuild the site to start using Vue.
  • Developers coming from HTML, CSS, or PHP backgrounds. The template-with-directives model maps closely to how those languages already think about markup. The ramp is shorter than JSX.
  • Projects that value a small, coherent official surface. One router, one state library, one meta-framework - and they all work the same way the framework does.
  • Performance-conscious applications. Vue 3 is small, fast, and tree-shakable. The framework's runtime stays out of the way of the parts of your app that need to be fast.

Where Vue fits less well is the inverse: a team with a deep React hiring pool, a project that depends on a React-only third-party library with no Vue equivalent, or a large enterprise that has already standardized on Angular's everything-included posture. The Vue ecosystem is healthy and large, but it is smaller than React's, and "is there a battle-tested library for this exact problem" sometimes answers "yes, but in React first."

For the broader picture - where Vue sits next to Angular, React, and Svelte - read Modern web app frameworks. For the toolchain underneath all of them, read What web developers need to know in 2026.