nuxt

Framework

nuxt/nuxt

The full-stack Vue framework for building type-safe, performant web applications.

Overview

Nuxt is an open-source Vue.js framework that provides server-side rendering, static site generation, hybrid rendering, and more. It features automatic routing, data fetching, state management, and zero-config TypeScript. With over 300 modules, it's highly extensible for production-grade full-stack applications.

README Preview

\n\n# Nuxt\n\n\n  \n  \n  \n  \n  \n  \n  \n  \n\n\nNuxt 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.\n\nIt provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including:\n- Server-side rendering, static site generation, hybrid rendering and edge-side rendering\n- Automatic routing with code-splitting and pre-fetching\n- Data fetching and state management\n- Search engine optimization and defining meta tags\n- Auto imports of components, composables and utils\n- TypeScript with zero configuration\n- Go full-stack with our server/ directory\n- Extensible with [300+ modules](https://nuxt.com/modules)\n- Deployment to a variety of [hosting platforms](https://nuxt.com/deploy)\n- ...[and much more](https://nuxt.com) 🚀\n\n### Table of Contents\n\n- 🚀 [Getting Started](#getting-started)\n- 💻 [Vue Development](#vue-development)\n- 📖 [Documentation](#documentation)\n- 🧩 [Modules](#modules)\n- ❤️ [Contribute](#contribute)\n- 🏠 [Local Development](#local-development)\n- 🛟 [Professional Support](#professional-support)\n- 🔗 [Follow Us](#follow-us)\n- ⚖️ [License](#license)\n\n---\n\n## 🚀 Getting Started\n\nUse the following command to create a new starter project. This will create a starter project with all the necessary files and dependencies:\n\n```bash\nnpm create nuxt@latest \n```\n\n> [!TIP]\n> Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds.\n\n## 💻 Vue Development\n\nSimple, 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.\n\nExample of an `app.vue`:\n\n```vue\n\nuseSeoMeta({\n  title: 'Meet Nuxt',\n  description: 'The Intuitive Vue Fra

FAQ (5)

Troubleshooting
How to fix TS2769 when useFetch<T>() receives a runtime string baseURL in Nuxt 4.6?

This is a TypeScript generic-inference regression in Nuxt 4.6.0. When you provide an explicit response type such as useFetch<{ items: number[] }>(), the BaseURL generic defaults to the literal type '', so a runtime string from useRuntimeConfig() is rejected.

Workaround 1 — create a fetch instance with the base URL and pass it via $fetch:

const config = useRuntimeConfig()
const api = $fetch.create({ baseURL: config.public.apiBase })

useFetch<{ items: number[] }>('/x', { $fetch: api })
useLazyFetch<{ items: number[] }>('/x', { $fetch: api })

Workaround 2 — build the full URL and omit baseURL:

const config = useRuntimeConfig()
useFetch<{ items: number[] }>(`${config.public.apiBase}/x`)

The same workaround applies to $fetch imported from #build/fetch. As a temporary measure, you can also downgrade to Nuxt 4.5.2, where the previous behavior worked.

GitHub Issue #36521
Troubleshooting
How to fix Nuxt `Serialize` dropping named properties from objects with string index signatures?

This is a type-level bug in Nuxt 4.6.0's SerializeObject. It uses Omit<T, FilterKeys<T, NonJsonPrimitive>>; when T has an index signature, keyof T becomes string | number, so the named keys are removed during the mapped type. Replace SerializeObject in node_modules/nuxt/dist/app/types/serialize.d.ts with a key-remapping mapped type:

type SerializeObject<T extends object> = {
  [K in keyof T as T[K] extends NonJsonPrimitive ? never : K]: Serialize<T[K]>
}

This preserves both named properties such as docFormat and name, and the index signature. Persist the change with patch-package:

npx patch-package nuxt

Then add patch-package to postinstall:

{ "scripts": { "postinstall": "patch-package" } }

As a temporary workaround without patching Nuxt, cast the response to an explicit corrected type:

type SerializeObjectFixed<T extends object> = {
  [K in keyof T as T[K] extends NonJsonPrimitive ? never : K]: Serialize<T[K]>
}

const wire = JSON.parse(JSON.stringify(doc)) as SerializeObjectFixed<Doc>

The same issue commonly appears with Zod .catchall(), z.looseObject(), and .passthrough() types. Upgrade Nuxt when the linked fix is released, or use the patch until then.

GitHub Issue #36500
Troubleshooting
Why is the global $fetch typed as nitropack's $Fetch instead of NuxtGlobalFetch in Nuxt 4.6.1 (routeTypedFetch not working)?

In Nuxt 4.6.1, @nuxt/kit merges your typescript.appTsConfig (or tsConfig) into the generated tsconfig with defu, which places your custom include entries **before** ./nuxt.d.ts. If any of those included files imports nuxt/app (e.g. test helpers), nitropack's declare global { var $fetch: $Fetch } is loaded first, so the global $fetch is typed as $Fetch<unknown, NitroFetchRequest> again — even with experimental.routeTypedFetch: true. **Workaround:** put ./nuxt.d.ts as the first entry of your include array:

export default defineNuxtConfig({
  experimental: { routeTypedFetch: true },
  typescript: {
    appTsConfig: {
      include: ['./nuxt.d.ts', '../test/**/*.ts'],
    },
  },
})

The duplicate ./nuxt.d.ts entry is deduplicated by Nuxt, and the global $fetch is typed as NuxtGlobalFetch again. Verify with nuxi prepare then tsc -p .nuxt/tsconfig.app.json --noEmit.

GitHub Issue #36621
Troubleshooting
Why are scheduled tasks and Cloudflare cron triggers duplicated when a Nuxt layer is extended by package name?

A layer reached by two paths in the extends graph gets its config merged once per path, doubling every array it declares — e.g. nitro.cloudflare.wrangler.triggers.crons becomes ['0 0 * * *','0 0 * * *'] (Cloudflare deploy fails with duplicate cron found ... [code: 10100]) and nitro.scheduledTasks task lists run twice concurrently. The cause: the seenLayerDirs dedup guard in @nuxt/kit sits behind an existsSync check, and a package specifier like extends: ['@org/layer-a','@org/layer-b'] fails that check before dedup runs (observed on nuxt 4.5.2 / c12 3.3.4). Workaround: spell layers as relative paths instead of package names, e.g. extends: ['./packages/a','./packages/b'] — path spellings pass the existence check and are deduplicated correctly. No upstream fix has shipped yet.

GitHub Issue #36339
Troubleshooting
Why is CSS loaded twice and cascade layer order broken in Nuxt dev mode on Windows (Nuxt 4.6.2)?

This is a Windows-only regression introduced in Nuxt 4.6.2 (works in 4.6.1). In collectDevCss (@nuxt/vite-builder), module-graph URLs now pass through toDevUrl(), which prepends /@id/ to any URL not starting with /. On Windows, absolute paths start with a drive letter (e.g. D:/), so SSR stylesheet links become /_nuxt/@id/D:/…/lib.css. The nuxt:dev-style-ssr plugin only removes link[href="/_nuxt/<id>"] and link[href="/_nuxt/@fs/<id>"], so the /@id/ link is never removed after hydration. Consequences: every global stylesheet (e.g. css: ['primeicons/primeicons.css'] or module-pushed CSS) loads twice in dev, and the stale link stays ahead of Vite-injected <style> tags, so @layer priority no longer follows nuxt.options.css order (a later entry's layer can become lowest priority). Workaround: downgrade/pin to Nuxt 4.6.1 (pnpm add nuxt@4.6.1 or add an override in package.json) until a patch is released. POSIX systems (Linux/macOS) are unaffected because absolute paths start with /. Proper fix for maintainers: add the /@id/ form (joinURL(buildAssetsURL, '@id', moduleId)) to the selectors DevStyleSSRPlugin removes, or have collectDevCss emit the /@fs/ form for absolute paths.

GitHub Issue #36737