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

directory-structure

251 notes in this subject, read out of this brain and free to use. This is page 4 of 5.

app/ directory specific files

The app/ directory contains three specific files: app.config.ts (a reactive configuration within the application), app.vue (the root component), and error.vue (the error page).

public/ directory purpose

The public/ directory contains public files that are served at the root and are not modified by the build process. This is suitable for files that must keep their names (such as robots.txt) or are unlikely to change (such as favicon.ico).

server/ directory structure and subdirectories

The server/ directory contains server-side code and includes the following subdirectories: api/ (contains API routes), routes/ (contains server routes such as dynamic /sitemap.xml), middleware/ (code that runs before a server route is processed), plugins/ (plugins used at server creation), and utils/ (reusable functions for server code).

test/ directory purpose

The test/ directory is the recommended place for application tests including unit tests, Nuxt runtime tests, and end-to-end tests.

content/ directory for Nuxt Content module

The content/ directory is enabled by the Nuxt Content module and is used to create a file-based CMS for an application using Markdown files.

modules/ directory for local modules

The modules/ directory contains local modules that are used to extend the functionality of a Nuxt application.

layers/ directory for reusable code organization

The layers/ directory allows organizing and sharing reusable code, components, composables, and configurations. Layers within this directory are automatically registered in the project.

Nuxt configuration files

Nuxt has three main configuration files: nuxt.config.ts (the main configuration file), .nuxtrc (an alternative syntax for configuring the application, useful for global configurations), and .nuxtignore (used to ignore files in the root directory during the build phase).

Directories with auto-import

Nuxt automatically imports from three directories: app/components/ for Vue components, app/composables/ for Vue composables, and app/utils/ for helper functions and utilities. In the server directory, Nuxt auto-imports exported functions and variables from server/utils/.

Module source code and playground directories

In a Nuxt module project, the `src` directory contains the module source code, while the `playground` directory contains a Nuxt application preconfigured to run with and test the module.

Routing defined by pages directory structure

In Nuxt, routing is defined by the structure of files inside the app/pages directory. Nuxt uses vue-router under the hood.

Auto-scanned files in Nuxt layers

Certain files in a layer directory are auto-scanned and used by Nuxt for the project extending the layer: app/components/*, app/composables/*, app/layouts/*, app/middleware/*, app/pages/*, app/plugins/*, app/utils/*, app/app.config.ts, server/*, and nuxt.config.ts.

Minimal layer directory requirement

A minimal Nuxt layer directory must contain a nuxt.config.ts file to indicate it is a layer.

NuxtIsland component islands directory

By default, component islands are scanned from the ~/components/islands/ directory. The component ~/components/islands/MyIsland.vue can be rendered with <NuxtIsland name="MyIsland" />.

Example setting response status code

```ts export default defineEventHandler((event) => { setResponseStatus(event, 202) }) ``` This example shows how to set a custom HTTP response status code. This file should be placed in server/api/validation/[id].ts and returns a 202 Accepted status.

Example Nitro config in nuxt.config

```ts export default defineNuxtConfig({ // https://nitro.build/config nitro: {}, }) ``` This example shows how to configure Nitro directly from nuxt.config.ts. This is an advanced option that can affect production deployments.

Example using storage in API handler

```ts export default defineEventHandler(async (event) => { // List all keys with const keys = await useStorage('redis').getKeys() // Set a key with await useStorage('redis').setItem('foo', 'bar') // Remove a key with await useStorage('redis').removeItem('foo') return {} }) ``` This example shows how to interact with configured storage in an API handler. This file should be placed in server/api/storage/test.ts.

Example Redis storage configuration

```ts export default defineNuxtConfig({ nitro: { storage: { redis: { driver: 'redis', port: 6379, host: '127.0.0.1', username: '', password: '', db: 0, tls: {}, }, }, }, }) ``` This example shows how to configure Redis storage in nuxt.config.ts.

Example sending redirect from server route

```ts export default defineEventHandler(async (event) => { await sendRedirect(event, '/path/redirect/to', 302) }) ``` This example shows how to send a redirect response from a server route. This file should be placed in server/api/foo.get.ts.

Example sending stream from server route

```ts import fs from 'node:fs' import { sendStream } from 'h3' export default defineEventHandler((event) => { return sendStream(event, fs.createReadStream('/path/to/file')) }) ``` This example shows how to send a file stream from a server route. This file should be placed in server/api/foo.get.ts. This is an experimental feature available in all environments.

Example runtime config for Redis via server plugin

```ts export default defineNuxtConfig({ runtimeConfig: { redis: { host: '', port: 0, }, }, }) ``` This example shows how to define runtime configuration for Redis credentials in nuxt.config.ts when using a server plugin for storage configuration.

Server directory auto-scans files for API and server handlers

Nuxt automatically scans files inside the server/ directory to register API and server handlers with Hot Module Replacement (HMR) support. The server/ directory has three main subdirectories: api/ (for API routes with /api prefix), routes/ (for routes without /api prefix), and middleware/ (for server middleware).

Server route handler must export default function

Each file in the server/ directory should export a default function defined with `defineEventHandler()` or `eventHandler()` (which is an alias). The handler can directly return JSON data, a Promise, or a Response object.

Cannot mix Vue and Nitro code

Do not import Vue app code (components, composables, or other app-only utilities) in your server routes or utilities, and do not import server-only code in your app.

Server API routes automatically prefixed with /api

Files inside the ~~/server/api directory are automatically prefixed with `/api` in their route. For example, a file at server/api/hello.ts creates a route at /api/hello.

Server routes directory creates routes without /api prefix

To add server routes without the `/api` prefix, put them into the ~~/server/routes directory. For example, a file at server/routes/hello.ts creates a route at /hello.

Server routes do not support full dynamic route functionality

Currently server routes do not support the full functionality of dynamic routes as pages do.

Add custom server utilities in server/utils directory

You can add custom helper functions in the ~~/server/utils directory. For example, you can define a custom handler utility that wraps the original handler and performs additional operations before returning the final response.

#server alias for importing from server directory

The `#server` alias can be used to import files from anywhere within the `server/` directory, regardless of the importing file's location. For example: `import { formatUser } from '#server/utils/formatUser'`. This alias ensures consistent imports across server code and is especially useful in deeply nested route handlers. The `#server` alias can only be used within the `server/` directory; importing from `#server` in client code will result in an error.

Dynamic route parameters in server files

Server routes can use dynamic parameters within brackets in the file name like `/api/hello/[name].ts` and be accessed via `event.context.params`. Use `getRouterParam(event, 'name')` to extract the parameter value. Alternatively, use `getValidatedRouterParams` with a schema validator such as Zod or Valibot for runtime and type safety.

HTTP method matching in server route filenames

Handle file names can be suffixed with `.get`, `.post`, `.put`, `.delete`, etc. to match the request's HTTP method. For example, `server/api/test.get.ts` handles GET requests and `server/api/test.post.ts` handles POST requests. Any unmatched HTTP method returns a 405 error. You can also use `index.[method].ts` inside a directory for structuring code differently, which is useful to create API namespaces.

Catch-all routes for fallback handling

Creating a file named `~~/server/api/foo/[...].ts` registers a catch-all route for all requests that do not match any route handler. You can access the route path via `event.context.path` (e.g., '/api/foo/bar/baz') and the route segment via `event.context.params._` (e.g., 'bar/baz'). You can also set a name for the catch-all route using `~~/server/api/foo/[...slug].ts` and access it via `event.context.params.slug`.

Reading request body in server routes

Use `readBody(event)` to read the request body in a server route. Example: `const body = await readBody(event)`. Alternatively, use `readValidatedBody` with a schema validator such as Zod or Valibot for runtime and type safety. When using `readBody` within a GET request, it will throw a `405 Method Not Allowed` HTTP error.

Reading query parameters in server routes

Use `getQuery(event)` to read query parameters from a request. Example: for query `/api/query?foo=bar&baz=qux`, use `const query = getQuery(event)` and access values as `query.foo` and `query.baz`. Alternatively, use `getValidatedQuery` with a schema validator such as Zod or Valibot for runtime and type safety.

Error handling in server routes

If no errors are thrown, a status code of `200 OK` will be returned. Any uncaught errors will return a `500 Internal Server Error` HTTP Error. To return other error codes, throw an exception with `createError()` and specify the status and statusText properties.

Setting response status codes in server routes

Use the `setResponseStatus(event, code)` utility to return a specific HTTP status code. For example, to return `202 Accepted`, use `setResponseStatus(event, 202)`.

Using runtime config in server routes

Use `useRuntimeConfig()` in server routes to access runtime configuration values defined in nuxt.config.ts. Environment variables prefixed with NUXT_ are automatically loaded into runtime config.

Reading request cookies in server routes

Use `parseCookies(event)` to extract cookies from the incoming request in a server route.

Forwarding context and headers in server routes

By default, neither the headers from the incoming request nor the request context are forwarded when making fetch requests in server routes. Use `event.$fetch` to forward the request context and headers when making fetch requests in server routes. Headers that are not meant to be forwarded will not be included in the request, including: transfer-encoding, connection, keep-alive, upgrade, expect, host, accept.

Background tasks with event.waitUntil

Use `event.waitUntil(promise)` to await a promise in the background without delaying the response to the client. This is useful for tasks like caching and logging that shouldn't block the response. The promise will be awaited before the handler terminates, ensuring the task is completed even if the server would otherwise terminate the handler right after the response is sent.

Nitro configuration in nuxt.config

You can use the `nitro` key in `nuxt.config.ts` to directly set Nitro configuration. This is an advanced option and custom config can affect production deployments, as the configuration interface might change over time when Nitro is upgraded in semver-minor versions of Nuxt.

Creating nested routers in server routes

You can create nested routers in server routes using h3's `createRouter()` and `useBase()` functions. Example: create a router with `createRouter()`, define routes using `router.get()`, and export with `export default useBase('/api/hello', router.handler)`.

Sending streams from server routes

Use `sendStream(event, stream)` from h3 to send file streams from server routes. This is an experimental feature available in all environments. Example: `return sendStream(event, fs.createReadStream('/path/to/file'))`.

Sending redirects from server routes

Use `sendRedirect(event, path, statusCode)` to send a redirect response from a server route. Example: `await sendRedirect(event, '/path/redirect/to', 302)`.

Legacy Node.js middleware and handlers

You can wrap legacy Node.js middleware and handlers using `fromNodeMiddleware()` from h3. For handlers, use `export default fromNodeMiddleware((req, res) => {...})`. For middleware, use `export default fromNodeMiddleware((req, res, next) => {...})`. However, legacy support is advised against; modern h3 handlers are preferred. Never combine `next()` callback with a legacy middleware that is `async` or returns a `Promise`.

Example legacy Node.js handler

```ts export default fromNodeMiddleware((req, res) => { res.end('Legacy handler') }) ``` This example shows how to wrap a legacy Node.js handler. This file should be placed in server/api/legacy.ts. Modern h3 handlers are preferred.

Server storage mount points configuration

Nitro provides a cross-platform storage layer. Configure additional storage mount points using `nitro.storage` in nuxt.config.ts or through server plugins. Example configuration for Redis storage: `nitro: { storage: { redis: { driver: 'redis', port: 6379, host: '127.0.0.1', username: '', password: '', db: 0, tls: {} } } }`. In API handlers, use `useStorage('redis').getKeys()`, `useStorage('redis').setItem(key, value)`, and `useStorage('redis').removeItem(key)` to interact with storage.

Example server API route with defineEventHandler

```ts import { defineEventHandler } from 'nitro/h3' export default defineEventHandler((event) => { return { hello: 'world', } }) ``` This example shows a basic API route that returns JSON data. The route is automatically accessible at /api/hello when placed in server/api/hello.ts.

Example calling API from component with useFetch

```vue <script setup lang="ts"> const { data } = await useFetch('/api/hello') </script> <template> <pre>{{ data }}</pre> </template> ``` This example shows how to universally call a server API route from a component using useFetch.

Example custom wrapped response handler utility

```ts export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D> ( handler: EventHandler<T, D>, ): EventHandler<T, D> => defineEventHandler<T>(async (event) => { try { // do something before the route handler const response = await handler(event) // do something after the route handler return { response } } catch (err) { // Error handling return { err } } }) ``` This example shows a custom server utility that wraps an event handler and performs operations before and after the route handler executes. This file should be placed in server/utils/handler.ts.

Example using wrapped response handler

```ts export default defineWrappedResponseHandler(event => 'hello world') ``` This example shows how to use the custom wrapped response handler utility in an API route. This file should be placed in server/api/hello.get.ts.

Example dynamic route parameter with getRouterParam

```ts export default defineEventHandler((event) => { const name = getRouterParam(event, 'name') return `Hello, ${name}!` }) ``` This example shows how to access a dynamic route parameter. This file should be placed in server/api/hello/[name].ts and will create a route accessible at /api/hello/nuxt that returns 'Hello, nuxt!'.

Example GET and POST route handlers

```ts // server/api/test.get.ts export default defineEventHandler(() => 'Test get handler') // server/api/test.post.ts export default defineEventHandler(() => 'Test post handler') ``` These examples show how to create separate handlers for different HTTP methods. GET requests to /test return 'Test get handler', POST requests return 'Test post handler', and any other method returns a 405 error.

Example API namespace with index routes

```ts // server/api/foo/index.get.ts export default defineEventHandler((event) => { // handle GET requests for the `api/foo` endpoint }) // server/api/foo/index.post.ts export default defineEventHandler((event) => { // handle POST requests for the `api/foo` endpoint }) // server/api/foo/bar.get.ts export default defineEventHandler((event) => { // handle GET requests for the `api/foo/bar` endpoint }) ``` These examples show how to use index.[method].ts files inside a directory for structuring API namespaces.

Example catch-all route with named parameter

```ts export default defineEventHandler((event) => { // event.context.params.slug to get the route segment: 'bar/baz' return `Default foo handler` }) ``` This example shows a named catch-all route. This file should be placed in server/api/foo/[...slug].ts and allows accessing the catch-all segment via event.context.params.slug.

Example reading request body with readBody

```ts export default defineEventHandler(async (event) => { const body = await readBody(event) return { body } }) ``` This example shows how to read the request body in a server route. This file should be placed in server/api/submit.post.ts.

Example calling server API with $fetch and POST body

```vue <script setup lang="ts"> async function submit () { const { body } = await $fetch('/api/submit', { method: 'post', body: { test: 123 }, }) } </script> ``` This example shows how to call a server API route with a POST method and request body from a component.

Example reading query parameters

```ts export default defineEventHandler((event) => { const query = getQuery(event) return { a: query.foo, b: query.baz } }) ``` This example shows how to read query parameters from a request. This file should be placed in server/api/query.get.ts and will handle queries like /api/query?foo=bar&baz=qux.

Example error handling in server route

```ts export default defineEventHandler((event) => { const id = Number.parseInt(event.context.params.id) as number if (!Number.isInteger(id)) { throw createError({ status: 400, statusText: 'ID should be an integer', }) } return 'All good' }) ``` This example shows error handling in a server route. This file should be placed in server/api/validation/[id].ts and demonstrates throwing an error with a specific status code.

Example nested router with h3

```ts import { createRouter, defineEventHandler, useBase } from 'h3' const router = createRouter() router.get('/test', defineEventHandler(() => 'Hello World')) export default useBase('/api/hello', router.handler) ``` This example shows how to create a nested router within a server route. This file should be placed in server/api/hello/[...slug].ts.

Give your agent this brain