nuxt
Frameworknuxt/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 FraFAQ (5)
TroubleshootingHow 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.
TroubleshootingHow 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.
TroubleshootingWhy 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.
TroubleshootingWhy 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.
TroubleshootingWhy 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.