6 min read
On this page

Ecosystem and Modules

Nuxt's module system is what separates it from being "just a Vue framework." A module can hook into the build process, add server routes, register composables, modify the Vite config, and inject runtime plugins — all from a single npm install and a line in nuxt.config.ts. The ecosystem around this is large and, frankly, uneven. Some modules are essential. Some are abandoned. Knowing which ones to reach for and which to avoid saves real time.

How Modules Work

A Nuxt module is a function that runs at build time. It receives the Nuxt instance and can modify the application before it compiles. Adding a module is usually two steps:

npx nuxi module add @nuxt/image

This installs the package and adds it to your nuxt.config.ts:

export default defineNuxtConfig({
  modules: ['@nuxt/image'],
})

Modules execute in order. If module B depends on something module A sets up, list A first. In practice this rarely matters, but it can bite you with modules that modify the same Vite plugins.

Essential Official Modules

Nuxt UI

Nuxt UI is a component library built on top of Tailwind CSS and Radix Vue. It provides production-ready components — buttons, modals, tables, forms, command palettes — with a consistent design system and full keyboard navigation.

npx nuxi module add @nuxt/ui
<script setup lang="ts">
const items = ref([
  { label: 'Profile', icon: 'i-heroicons-user' },
  { label: 'Settings', icon: 'i-heroicons-cog-6-tooth' },
  { label: 'Sign Out', icon: 'i-heroicons-arrow-right-on-rectangle' },
])
</script>

<template>
  <div class="p-4">
    <UDropdown :items="[items]">
      <UButton label="Options" trailing-icon="i-heroicons-chevron-down" />
    </UDropdown>
  </div>
</template>

Nuxt UI is opinionated — it uses Tailwind, it ships with Heroicons, and its styling approach may not fit every project. But if you are building a dashboard, admin panel, or SaaS app and want to move fast, it eliminates days of component development. Companies like Volta and Cal.com have shipped with it.

The alternative is building your own component library on top of Radix Vue or Headless UI, which gives you full design control but takes significantly more time.

Nuxt Content

Nuxt Content turns your Nuxt app into a content management system backed by Markdown, YAML, and JSON files. Write content in Markdown, query it with a MongoDB-like API, and render it with Vue components.

npx nuxi module add @nuxt/content
<!-- content/blog/vue3-migration.md -->
---
title: How We Migrated to Vue 3
description: A practical guide based on our experience migrating 200 components.
date: 2026-03-15
tags: [vue, migration]
---

The migration took three months. Here's what we learned.
<!-- pages/blog/[...slug].vue -->
<script setup lang="ts">
const route = useRoute()
</script>

<template>
  <ContentDoc :path="route.path" />
</template>

Query content programmatically:

<script setup lang="ts">
const { data: posts } = await useAsyncData('blog-posts', () =>
  queryContent('blog')
    .where({ _draft: false })
    .sort({ date: -1 })
    .limit(10)
    .find(),
)
</script>

<template>
  <ul>
    <li v-for="post in posts" :key="post._path">
      <NuxtLink :to="post._path">
        {{ post.title }}
      </NuxtLink>
      <time>{{ post.date }}</time>
    </li>
  </ul>
</template>

Content v3 (the current major version) uses a SQL-based query engine and supports remote content sources, making it suitable for headless CMS-like architectures where content lives in a separate repo or API.

Nuxt Auth Utils

Authentication in Nuxt has historically been a pain point. nuxt-auth-utils (by the Nuxt team) provides OAuth and session management that works with Nuxt's SSR:

npx nuxi module add nuxt-auth-utils
// server/routes/auth/github.get.ts
export default defineOAuthGitHubEventHandler({
  config: {
    emailRequired: true,
  },
  async onSuccess(event, { user, tokens }) {
    await setUserSession(event, {
      user: {
        id: user.id,
        name: user.name,
        email: user.email,
        avatar: user.avatar_url,
      },
    })
    return sendRedirect(event, '/dashboard')
  },
})
<!-- components/AuthButton.vue -->
<script setup lang="ts">
const { loggedIn, user, clear } = useUserSession()
</script>

<template>
  <div v-if="loggedIn">
    <span>{{ user.name }}</span>
    <button @click="clear()">Sign Out</button>
  </div>
  <a v-else href="/auth/github">Sign in with GitHub</a>
</template>

It supports GitHub, Google, Discord, Auth0, and many other OAuth providers. For custom email/password auth, you still need to wire up your own logic, but the session management layer is handled.

VueUse

VueUse is not a Nuxt module — it is a collection of Vue composables that covers almost every common need: browser APIs, sensors, animations, state management utilities, and more. It has over 200 composables, and most Vue projects end up using it.

npm install @vueuse/core @vueuse/nuxt
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@vueuse/nuxt'],
})

Some composables you will reach for constantly:

<script setup lang="ts">
// Debounced ref — perfect for search inputs
const searchQuery = ref('')
const debouncedQuery = refDebounced(searchQuery, 300)

// Dark mode toggle
const isDark = useDark()
const toggleDark = useToggle(isDark)

// Clipboard
const { copy, copied } = useClipboard()

// Local storage with reactive sync
const preferences = useLocalStorage('user-prefs', {
  theme: 'light',
  language: 'en',
  sidebar: true,
})

// Intersection observer
const targetEl = ref<HTMLElement>()
const { isIntersecting } = useIntersectionObserver(targetEl, ([entry]) => entry)

// Window scroll position
const { y: scrollY } = useWindowScroll()
</script>

<template>
  <div>
    <input v-model="searchQuery" placeholder="Search..." />
    <button @click="toggleDark()">
      {{ isDark ? 'Light Mode' : 'Dark Mode' }}
    </button>
    <button @click="copy('some text')">
      {{ copied ? 'Copied' : 'Copy' }}
    </button>
  </div>
</template>

VueUse is SSR-safe by default. Composables that use browser APIs return sensible defaults on the server and activate on the client.

Nuxt DevTools

Nuxt DevTools is a browser extension and in-app panel for debugging Nuxt applications. It shows your component tree, routes, active middleware, Pinia stores, API calls, and build info in a single interface.

npx nuxi module add @nuxt/devtools

It is enabled in development by default and stripped from production builds. Press Shift+Alt+D (or the floating button) to open the panel.

What makes it genuinely useful beyond Vue DevTools:

  • Routes tab shows all registered routes, their rendering mode, and middleware
  • Components tab displays the component tree with props and state
  • Imports tab reveals which auto-imports are active and where they come from
  • Server routes tab lists your API endpoints and lets you test them
  • Modules tab shows installed modules and their configuration
  • Build analyzer visualizes your bundle without running a separate command

For teams onboarding new developers, the imports tab alone is valuable — it answers "where does this composable come from?" without grepping the codebase.

Community Modules Worth Knowing

@nuxtjs/i18n — Internationalization. Route-based locale switching, lazy-loaded translations, SEO tags per locale. If your app needs multiple languages, this is the standard.

@nuxtjs/sitemap and @nuxtjs/robots — SEO essentials covered in the SEO topic. Install both on any public-facing site.

@pinia/nuxt — Pinia integration. Auto-imports stores, handles SSR serialization, devtools integration. If you use Pinia (and you should), install this.

@nuxt/fonts — Automatic font optimization. Downloads, subsets, and self-hosts Google Fonts and other web fonts. Set-and-forget.

nuxt-security — Adds security headers (CSP, HSTS, X-Frame-Options), rate limiting, and request validation. Good defaults for production apps.

Upgrading Between Versions

Nuxt follows semver. Minor versions (3.x to 3.y) should not break your app. Major versions (Nuxt 3 to Nuxt 4) require migration effort.

Minor Version Upgrades

npx nuxi upgrade

This updates Nuxt and its direct dependencies to the latest compatible versions. Run your tests after upgrading. Check the release notes for deprecation warnings.

Major Version Migration

Nuxt provides codemods and migration guides for major upgrades. The Nuxt 3 to Nuxt 4 migration (when it lands) will include:

npx nuxi upgrade --force
npx @nuxt/codemod@latest <path-to-project>

Practical advice for major upgrades:

  1. Read the entire migration guide before starting.
  2. Upgrade on a branch. Do not upgrade in main.
  3. Fix compiler errors first, then runtime errors, then test failures.
  4. Upgrade modules one at a time. Some modules lag behind major Nuxt releases by weeks or months.
  5. Pin your Nuxt version in package.json ("nuxt": "3.15.0", not "^3.15.0") to avoid surprise upgrades in CI.
{
  "dependencies": {
    "nuxt": "3.15.0",
    "vue": "3.5.0"
  }
}

Module Compatibility

Before upgrading Nuxt, check that your modules support the new version. The Nuxt Modules website (modules.nuxt.com) shows compatibility badges. If a critical module does not support the new version yet, wait or find an alternative.

Common Pitfalls

Installing too many modules. Each module adds build time and complexity. Before adding a module, ask: can I do this with 20 lines of code instead? A module for adding a single <meta> tag is overkill.

Using abandoned modules. Check the last commit date and open issue count on GitHub before adding a module. A module last updated in 2023 may not work with current Nuxt. The Nuxt team maintains a list of officially recommended modules — prefer those.

Not reading module source code. Modules run at build time with full access to your Nuxt configuration. A malicious or poorly written module can break your build, leak environment variables, or inject unwanted code. For modules from unknown authors, read the source before installing.

Fighting module conventions. Nuxt UI expects Tailwind. Nuxt Content expects a content/ directory. If you fight these conventions — using a different CSS framework with Nuxt UI or restructuring Content's directories — you spend more time configuring than building.

Skipping Nuxt DevTools. Teams debug Nuxt apps by adding console.log everywhere when DevTools would show them the answer in seconds. Install it on every project.

Key Takeaways

  • Nuxt modules hook into the build process and can modify almost anything about your application.
  • Start with the official modules: @nuxt/image, @nuxt/content, @nuxt/ui, @nuxt/fonts, and @nuxt/devtools.
  • VueUse is not optional — its composables are useful in nearly every Vue project.
  • Pin your Nuxt version and upgrade deliberately, not automatically.
  • Check module maintenance status before installing — abandoned modules cause more problems than they solve.