new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Nuxt · Guide · all subjects

general-reference

388 notes in this subject, read out of this brain and free to use. This is page 1 of 7.

Nuxt Guide main topics and sections

The Nuxt Guide covers the following main topics: Key Concepts (auto-import, hybrid rendering, TypeScript support), Best Practices, Working with AI (MCP Server and LLMs.txt integration), Module Author Guide (creating Nuxt modules to integrate, enhance or extend applications), Recipes (solutions to common problems), and Going Further (advanced concepts like experimental features and hooks).

Vue 3 bundle size reduction and tree-shakability

With Vue 3 and Nuxt 3, focus has been put on bundle size reduction. Most of Vue's functionality, including template directives and built-in components, is tree-shakable. Production bundles will not include unused code. A minimal Vue 3 application can be reduced to 12 kb gzipped.

Component auto-imports from app/components directory

Every Vue component created in the app/components/ directory of a Nuxt project will be available in the project without having to import it. If a component is not used anywhere, your production code will not include it.

Single-file components with hot module replacement

Vue's single-file components (SFC or *.vue files) encapsulate markup in <template>, logic in <script>, and styling in <style>. Nuxt provides a zero-config experience for SFCs with Hot Module Replacement that offers a seamless developer experience.

Composition API with setup keyword

The Composition API introduced in Vue 3 is not a replacement of the Options API, but enables better logic reuse throughout an application and is a more natural way to group code by concern in complex components. It is used with the 'setup' keyword in the <script> definition.

Vue Router and file-based routing

Nuxt uses an app/pages/ directory and naming conventions to directly create routes mapped to your files using the official Vue Router library.

Options API example for comparison

Here is an example of the legacy Options API pattern from Vue 2: ```vue <script> export default { data () { return { count: 0, } }, methods: { increment () { this.count++ }, }, } </script> ``` This shows how the Options API uses pre-defined properties like `data` and `methods` to organize component logic.

Composition API example with Counter component

Here is an example of a component using Composition API with auto-imported reactivity in Nuxt 3: ```vue <script setup lang="ts"> const count = ref(0) const increment = () => count.value++ </script> ``` This shows a Counter component that uses the `ref` function (auto-imported) to create reactive state and defines an increment function.

Vue Virtual DOM rewritten for better performance

The Vue Virtual DOM (VDOM) has been rewritten from the ground up and allows for better rendering performance. When working with compiled Single-File Components, the Vue compiler can further optimize them at build time by separating static and dynamic markup. This results in faster first rendering (component creation) and updates, and less memory usage. In Nuxt 3, it enables faster server-side rendering as well.

Nuxt integrates Vue 3

Nuxt uses Vue 3, the new major release of Vue that enables new patterns for Nuxt users.

Auto-imported reactivity functions and composables

Nuxt provides auto-imported Reactivity functions from Vue and Nuxt built-in composables. You can also write your own auto-imported reusable functions in the app/composables/ directory.

Vue app mounting and hydration

The Vue application is mounted by calling app.mount('#__nuxt') to the DOM. If the application uses SSR or SSG mode, Vue performs a hydration step to make the client-side application interactive. During hydration, Vue recreates the application (excluding Server Components), matches each component to its corresponding DOM nodes, and attaches DOM event listeners. To ensure proper hydration, it is important to maintain consistency between the data on the server and the client. For API requests, it is recommended to use useAsyncData, useFetch, or other SSR-friendly composables to ensure that data fetched on the server side is reused during hydration, avoiding repeated requests. Before mounting the Vue application, Nuxt calls the app:beforeMount hook. After mounting the Vue application, Nuxt calls the app:mounted hook.

HTML output generation and hooks

After all required data is fetched and the components are rendered, Nuxt combines the rendered components with settings from unhead to generate a complete HTML document. This HTML, along with the associated data, is then sent back to the client to complete the SSR process. After rendering the Vue application to HTML, Nuxt calls the app:rendered hook. Before finalizing and sending the HTML, Nitro will call the render:html hook, which allows manipulation of the generated HTML, such as injecting additional scripts or modifying meta tags.

Route validation on client

Route validation executes on the client side in the same way as on the server, including the validate method if defined in the definePageMeta function.

Page and components rendering on server

Nuxt renders the page and its components and fetches any required data with useFetch and useAsyncData during server-side rendering. Since there are no dynamic updates and no DOM operations occur on the server, Vue lifecycle hooks such as onBeforeMount, onMounted, and subsequent hooks are NOT executed during SSR. By default, Vue pauses dependency tracking during SSR for better performance. There is no reactivity on the server side because Vue SSR renders the app top-down as static HTML, making it impossible to go back and modify content that has already been rendered.

Route validation in server lifecycle

After initializing plugins and before executing middleware, Nuxt calls the validate method if it is defined in the definePageMeta function. The validate method, which can be synchronous or asynchronous, is often used to validate dynamic route parameters. The validate function should return true if the parameters are valid. If validation fails, it should return false or an object containing a status and/or statusText to terminate the request.

Nitro server engine initialization and plugins

Nuxt is powered by Nitro, a modern server engine. When Nitro starts, it initializes and executes plugins under the /server/plugins/ directory. These plugins can capture and handle application-wide errors, register hooks that execute when Nitro shuts down, and register hooks for request lifecycle events such as modifying responses. Nitro plugins are executed only once when the server starts. In a serverless environment, the server boots on each incoming request, and so do the Nitro plugins, but they are not awaited.

Avoid side effects in script setup root scope during SSR

Code that produces side effects needing cleanup should be avoided in the root scope of <script setup> during SSR. An example of such side effects is setting up timers with setInterval. In client-side only code, a timer can be set up and then torn down in onBeforeUnmount or onUnmounted. However, because the unmount hooks are never called during SSR, the timers will stay around forever. To avoid this, move side-effect code into onMounted instead.

Vue lifecycle on client

Unlike on the server, the browser executes the full Vue lifecycle on the client side.

Standalone server dist in Nitro

Nitro produces a standalone server dist that is independent of node_modules. When running nuxt build, Nuxt generates this dist into a .output directory. The output contains runtime code to run your Nuxt server in any environment and serve static files, making it suitable for JAMstack, serverless, and service worker environments.

Nuxt native storage layer

Nuxt implements a native storage layer that supports multi-source drivers and local assets, enabling a true hybrid framework for the JAMstack.

Nuxt 2 vs Nuxt 3 server differences

The server in Nuxt 2 is not standalone and requires part of Nuxt core to be involved by running nuxt start with nuxt-start or nuxt distributions or custom programmatic usage, which is fragile and prone to breakage. Nuxt 3 uses Nitro to produce a true standalone server independent of node_modules, suitable for serverless and service worker environments.

Typed API routes in Nitro

When using API routes or middleware in Nitro, typings are automatically generated for these routes as long as you are returning a value instead of using res.end() to send a response. These types can be accessed when using $fetch() or useFetch().

$fetch direct API calls

Nitro allows direct calling of routes via the globally-available $fetch helper. When run on the browser, this makes an API call to the server, but when run on the server, it directly calls the relevant function, saving an additional API call. The $fetch API uses ofetch and features automatic parsing of JSON responses and automatic handling of request body and params with correct Content-Type headers.

h3 HTTP handler library

Nitro uses h3 internally for server API endpoints and middleware. h3 allows handlers to directly return objects or arrays for automatically-handled JSON responses, supports returning promises which will be awaited, and provides helper functions for body parsing, cookie handling, redirects, headers and more.

Nitro server engine overview

Nuxt is powered by Nitro, a new server engine that provides cross-platform support for Node.js, browsers, service workers and more. It includes serverless support out-of-the-box, API routes support, automatic code-splitting and async-loaded chunks, hybrid mode for static and serverless sites, and a development server with hot module reloading.

ref and computed unwrapping in templates

Auto-imported ref and computed won't be unwrapped in a component <template> because they are not top-level to the template. This is how Vue works with refs that aren't top-level.

Disable auto-imports for custom code only

Set `imports.scan` to `false` in nuxt.config.ts to disable auto-imports for custom code like composables while keeping framework functions like ref, computed, and watch auto-imported. This breaks the layer system's override feature and requires explicit imports of composables from each layer.

Disable all auto-imports configuration

Set `imports.autoImport` to `false` in nuxt.config to disable auto-importing composables and utilities completely. Explicit imports from '#imports' will still work.

Explicit imports via #imports alias

Every auto-import is exposed through the '#imports' alias for explicit imports when needed. For example: `import { computed, ref } from '#imports'`

Auto-import components configuration

Components are auto-imported separately from composables and utilities. Set `components.dirs` to an empty array to disable auto-importing from ~/components directory, though this does not affect components added by modules.

Composable working code example

To use useRuntimeConfig() correctly, call it inside the composable function: `export const useMyComposable = () => { const config = useRuntimeConfig(); ... }`

Composable breaking code example

Accessing runtime config outside a composable function will fail. The code `const config = useRuntimeConfig()` at module level in composables/example.ts will break because it is not called in the right lifecycle context.

Non-SFC components and Nuxt composables

When using a composable that requires Nuxt context inside a non-SFC component, wrap the component with defineNuxtComponent instead of defineComponent.

Auto-import from third-party packages

Configure auto-imports from third-party packages using the imports.presets option in nuxt.config. For example, to auto-import useI18n from vue-i18n: `imports: { presets: [{ from: 'vue-i18n', imports: ['useI18n'] }] }`

Composable context requirements

Most built-in Composition API composables must be called in the right context to avoid the 'Nuxt instance is unavailable' error. They must be called within a Nuxt plugin, route middleware, Vue setup function, <script setup> blocks, defineNuxtComponent, defineNuxtPlugin, or defineNuxtRouteMiddleware. They must be called synchronously, except in these special contexts where transforms keep synchronous context after await.

Built-in auto-imported functions

Nuxt auto-imports functions and composables for data fetching like useFetch(), access to app context via useNuxtApp(), runtime config via useRuntimeConfig(), state management, and component/plugin definition. Vue exposes reactivity APIs like ref and computed, lifecycle hooks, and helpers that are auto-imported by Nuxt.

Auto-import overview and benefits

Nuxt auto-imports components, composables, helper functions and Vue APIs across your application without explicit imports. This preserves typings, IDE completions and hints, and only includes what is used in production code.

Custom folder auto-import configuration

Functions exported from custom folders can be auto-imported by configuring the imports section of your nuxt.config file.

Disabling modules in Nuxt config

Modules can be disabled by setting their config key to `false` in the Nuxt config file. This is particularly useful when disabling modules inherited from layers. For example, to disable the @nuxt/image module, set `image: false` in the config.

buildModules property is deprecated

The `buildModules` property used in Nuxt 2 is deprecated in favor of the `modules` property. Nuxt modules are now build-time-only.

How to add Nuxt modules

Nuxt modules are added to the `nuxt.config.ts` file under the `modules` property. Modules can be specified as package names, local paths, inline options, or inline function definitions. Example syntax: `modules: ['@nuxtjs/example', './modules/example', ['./modules/example', { token: '123' }], async (inlineOptions, nuxt) => { }]`

Why Nuxt modules exist

Nuxt provides a module system to avoid adding every possible feature to the core framework, which would make it very complex and hard to use. Modules allow extending the framework for specific needs while keeping the core lean. Modules can be distributed in npm packages and reused across projects.

What is a Nuxt module

Nuxt modules are async functions that sequentially run when starting Nuxt in development mode using `nuxt dev` or building a project for production with `nuxt build`. They extend the framework core and can override templates, configure webpack loaders, add CSS libraries, and perform many other useful tasks.

ESM compatibility error with .esm.js files

Importing a package with an .esm.js file in a Node.js ESM context fails because Node.js treats .js files as CommonJS by default unless package.json has `"type": "module"`. This causes a SyntaxError: Unexpected token 'export'.

Use mlly for safe default export interop

The mlly library provides `interopDefault()` for safe default export handling that preserves named exports. Example: `import { interopDefault } from 'mlly'` then `interopDefault(myModule)` converts `{ default: { foo: 'bar' }, baz: 'qux' }` to `{ foo: 'bar', baz: 'qux' }`.

Node.js module field vs exports field

The `module` field in package.json is a convention used by bundlers like webpack and Rollup but is not recognized by Node.js itself. Node.js only uses the `exports` and `main` fields for module resolution.

Native ESM in Node.js

Modern Node.js LTS releases support native ESM. To enable ESM syntax processing, set `"type": "module"` in package.json with .js extension, or use .mjs file extension (recommended). Nuxt Nitro outputs a `.output/server/index.mjs` file to tell Node.js to treat it as a native ES module.

ESM syntax with import and export

ECMAScript Modules (ESM) use `import a from './a'` to import modules and `export { a }` to export them. ESM became a JavaScript standard after more than 10 years of development.

CommonJS syntax with require and module.exports

CommonJS (CJS) is a module format introduced by Node.js. It uses the syntax `const a = require('./a')` to import modules and `module.exports.a = a` to export them.

Manually interop default export from CJS in ESM

To manually handle default export interop from CJS in ESM: use `import { default as pkg } from 'cjs-pkg'` for static imports, or `import('cjs-pkg').then(m => m.default || m).then(console.log)` for dynamic imports.

Library author: rename ESM files to .mjs

The recommended approach for library authors to fix ESM compatibility is to rename ESM files to end with .mjs and CJS files to end with .cjs for explicitness. This tells Node.js how to treat each file without depending on package.json type field.

Migrate from CJS require to ESM import

When migrating from CommonJS to ESM, replace `module.exports = function () { }` with `export default function () { }` and `exports.hello = 'world'` with `export const hello = 'world'`. Replace `const myLib = require('my-lib')` with `import myLib from 'my-lib'` or `const dynamicMyLib = await import('my-lib').then(lib => lib.default || lib)`.

Node.js import resolution for different file extensions

When importing a module in Node.js: files ending in .mjs are expected to use ESM syntax; files ending in .cjs are expected to use CJS syntax; files ending in .js are expected to use CJS syntax unless their package.json has `"type": "module"`.

Transpile libraries in Nuxt config for ESM issues

To handle libraries with ESM compatibility issues, add them to `build.transpile` in the Nuxt config. Example: `export default defineNuxtConfig({ build: { transpile: ['sample-library'] } })`. You may need to also add other packages imported by these libraries.

Named import error from ESM-syntax build treated as CJS

When Node.js treats an ESM-syntax build as CommonJS, named imports fail with: "SyntaxError: Named export 'named' not found. The requested module is a CommonJS module, which may not support all module.exports as named exports."

Alias libraries to CJS version in Nuxt config

In some cases, manually alias a library to its CJS version in Nuxt config: `export default defineNuxtConfig({ alias: { 'sample-library': 'sample-library/dist/sample-library.cjs.js' } })`.

CommonJS default export interop

A CommonJS module using `module.exports = { test: 123 }` or `exports.test = 123` provides a default export. When required in CJS it works as-is. In ESM contexts with interop support, `import pkg from 'cjs-pkg'` works, but there is always a chance interop fails and returns `{ default: { test: 123 } }`. Dynamic imports always return this shape: `import('cjs-pkg').then(console.log)` returns `[Module: null prototype] { default: { test: '123' } }`.

Library author: make library ESM-only

An alternative approach is to make the entire library ESM-only by setting `"type": "module"` in package.json and ensuring built code uses ESM syntax. However, this means the library can only be consumed in an ESM context and may cause dependency issues.

Replace __dirname and __filename in ESM

In ESM modules, `require`, `require.resolve`, `__filename` and `__dirname` globals are not available. Replace `__dirname` with `fileURLToPath(new URL('.', import.meta.url))` from `node:url` module.

Give your agent this brain