@astrojs/vue, nuxt, and vitepress are all tools in the Vue.js ecosystem that enable building websites with Vue components, but they serve fundamentally different architectural purposes. @astrojs/vue is an integration plugin that allows using Vue components inside Astro projects, which are primarily content-focused static sites that ship zero JavaScript by default. nuxt is a full-stack Vue framework supporting server-side rendering (SSR), static site generation (SSG), and client-side hydration with a rich plugin system and file-based routing. vitepress is a minimalist documentation site generator built on Vite and Vue, optimized for technical docs with Markdown-driven content and minimal configuration.
All three packages let you use Vue in modern web projects, but they target very different use cases. Let’s compare how they handle core concerns like rendering, data loading, routing, and component architecture — with real code examples.
@astrojs/vue follows Astro’s “islands architecture.” Your page is mostly static HTML; Vue components are hydrated only when needed.
<!-- Astro page (.astro file) -->
---
import MyCounter from '../components/MyCounter.vue';
---
<html>
<body>
<h1>Welcome</h1>
<!-- This Vue component is hydrated on the client -->
<MyCounter client:load />
</body>
</html>
No JavaScript ships for the <h1>. Only MyCounter.vue gets bundled and hydrated.
nuxt fully hydrates your entire app by default (unless you opt into partial hydration). Every page is a reactive Vue application.
<!-- Nuxt page (pages/index.vue) -->
<template>
<div>
<h1>Welcome</h1>
<MyCounter />
</div>
</template>
<script setup>
import MyCounter from '~/components/MyCounter.vue';
</script>
Both <h1> and MyCounter are part of the same reactive component tree. The whole page loads Vue runtime.
vitepress renders Markdown to static HTML with optional Vue components embedded directly in .md files.
<!-- docs/index.md -->
# Welcome
<MyCounter />
<script setup>
import MyCounter from './components/MyCounter.vue'
</script>
Vue components work, but the surrounding content is static. No complex layouts or routing logic beyond docs conventions.
@astrojs/vue relies on Astro’s build-time data fetching. You fetch data in .astro files during SSG — not at runtime.
---
// src/pages/blog.astro
import { getPosts } from '../lib/posts';
const posts = await getPosts(); // Runs at build time
---
<ul>
{posts.map(post => <li>{post.title}</li>)}
</ul>
You cannot fetch user-specific data on page load unless you add client-side JavaScript manually.
nuxt supports multiple data strategies: async data per route (useAsyncData), server routes, and composables.
<!-- pages/posts.vue -->
<script setup>
const { data: posts } = await useAsyncData('posts', () => $fetch('/api/posts'));
</script>
Works in SSR, SSG, or CSR depending on your config. Also supports real-time data via useFetch.
vitepress has no built-in data fetching beyond Markdown frontmatter or static imports.
---
title: Blog
---
<script setup>
import { posts } from './_data.js'; // Must be static
</script>
{{ posts.length }} posts
Dynamic or user-dependent data isn’t supported without custom client-side JS.
@astrojs/vue uses Astro’s file-based router. .astro files define routes; Vue components are just UI pieces.
src/
pages/
index.astro → /
about.astro → /about
blog/
[slug].astro → /blog/:slug
Vue files never define routes.
nuxt uses a file-based router where .vue files in pages/ become routes.
pages/
index.vue → /
about.vue → /about
blog/
[id].vue → /blog/:id
Supports nested routes, middleware, and programmatic navigation.
vitepress uses directory structure in docs/ for routing, but only for Markdown files.
docs/
index.md → /
guide/
intro.md → /guide/intro
No support for dynamic routes beyond what Markdown provides. Not meant for app-like navigation.
@astrojs/vue is configured through astro.config.mjs. You enable Vue via an integration:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue';
export default defineConfig({
integrations: [vue()],
});
Extensibility comes from Astro’s broader ecosystem (e.g., Tailwind, MDX), not Vue-specific plugins.
nuxt uses nuxt.config.ts and a rich module system:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@pinia/nuxt'],
css: ['~/assets/main.css']
});
Supports plugins, composables, middleware, and auto-imports. Built for large-scale apps.
vitepress uses .vitepress/config.js with limited customization:
// .vitepress/config.js
export default {
title: 'My Docs',
themeConfig: {
nav: [{ text: 'Guide', link: '/guide/' }]
}
}
Theming is possible, but deep customization (e.g., custom auth, APIs) isn’t supported.
@astrojs/vue if:nuxt if:vitepress if:vitepress is not a general-purpose framework — don’t try to build an e-commerce site with it.@astrojs/vue does not turn Astro into a Vue app framework. Vue is a component layer only.nuxt is the only one that supports true server-side rendering with dynamic data per request.Think of these tools on a spectrum:
Pick the tool that matches your project’s scope — not just your preferred syntax.
Choose nuxt when you need a full-featured Vue application with complex routing, data fetching, SEO requirements, and support for both SSR and SSG. It’s best for dynamic web apps (e.g., dashboards, e-commerce, admin panels) where you require a complete framework with middleware, plugins, composables, and deployment flexibility across Node.js, serverless, and edge runtimes.
Choose vitepress when you’re building documentation sites or developer-facing content that’s primarily Markdown-based. It offers out-of-the-box theming, search, and responsive layouts with minimal setup. Avoid it for general-purpose applications — it’s purpose-built for docs and lacks features like custom API routes or complex state management.
Choose @astrojs/vue when you're building a content-heavy static site (like a blog or marketing site) with Astro as the primary framework and need to embed interactive Vue components sparingly. It’s ideal when most of your site can be static HTML, and you only hydrate small islands of interactivity — keeping bundle sizes tiny and performance high.
Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.
It provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including:
Use the following command to create a new starter project. This will create a starter project with all the necessary files and dependencies:
npm create nuxt@latest <my-project>
[!TIP] Discover also nuxt.new: Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds.
Simple, intuitive and powerful, Nuxt lets you write Vue components in a way that makes sense. Every repetitive task is automated, so you can focus on writing your full-stack Vue application with confidence.
Example of an app.vue:
<script setup lang="ts">
useSeoMeta({
title: 'Meet Nuxt',
description: 'The Intuitive Vue Framework.',
})
</script>
<template>
<div id="app">
<AppHeader />
<NuxtPage />
<AppFooter />
</div>
</template>
<style scoped>
#app {
background-color: #020420;
color: #00DC82;
}
</style>
We highly recommend you take a look at the Nuxt documentation to level up. It’s a great resource for learning more about the framework. It covers everything from getting started to advanced topics.
Discover our list of modules to supercharge your Nuxt project, created by the Nuxt team and community.
We invite you to contribute and help improve Nuxt 💚
Here are a few ways you can get involved:
Follow the docs to Set Up Your Local Development Environment to contribute to the framework and documentation.