Skip to content
← Todas las preguntas
🌱 Principiante

¿Cuál es la convención de estructura de directorios en Nuxt?

💚 Nuxt🏗️ Arquitectura⚡ Vite

Nuxt está basado en convenciones. La estructura de directorios es la configuración. El lugar donde colocas un archivo determina su función: un archivo .vue en pages/ se convierte en una ruta, un archivo .ts en server/api/ se convierte en un endpoint de API, un composable en composables/ se importa automáticamente. No hay configuración manual.

Árbol anotado de la estructura de directorios Nuxt con descripciones de roles

Estructura completa del proyecto ​

my-app/
├── app.vue                  ← componente raíz
├── nuxt.config.ts           ← configuración en tiempo de build
├── app.config.ts            ← configuración de app en tiempo de ejecución
├── error.vue                ← página de error personalizada
├── components/              ← componentes Vue con auto-importación
├── composables/             ← composables con auto-importación
├── utils/                   ← funciones de utilidad con auto-importación
├── pages/                   ← enrutamiento basado en archivos
├── layouts/                 ← layouts para envolver páginas
├── middleware/              ← middleware de rutas
├── plugins/                 ← plugins de Vue (auto-registrados)
├── assets/                  ← procesados por el bundler (CSS, imágenes, fuentes)
├── public/                  ← servidos tal cual (favicon, robots.txt)
├── server/                  ← código de servidor Nitro
│   ├── api/                 ← rutas de API (/api/*)
│   ├── routes/              ← rutas de servidor (sin prefijo /api)
│   ├── middleware/          ← middleware de servidor (en cada petición)
│   ├── plugins/             ← plugins de arranque del servidor
│   └── utils/               ← utilidades de servidor con auto-importación
├── layers/                  ← layers locales (auto-detectados)
└── modules/                 ← módulos locales de Nuxt

Qué hace cada directorio ​

components/ ​

Auto-importados por nombre de archivo. Los nombres de carpeta se convierten en prefijos:

components/
├── AppHeader.vue            → <AppHeader />
├── base/
│   └── Button.vue           → <BaseButton />
└── form/
    └── Input.vue            → <FormInput />

composables/ ​

Los archivos de primer nivel se auto-importan:

composables/
├── useAuth.ts               → useAuth() disponible en cualquier lugar
├── useCart.ts               → useCart() disponible en cualquier lugar
└── helpers/
    └── validate.ts          → NO se auto-importa (anidado)

pages/ ​

Cada archivo se convierte en una ruta:

pages/
├── index.vue                → /
├── about.vue                → /about
├── blog/
│   ├── index.vue            → /blog
│   └── [slug].vue           → /blog/:slug
└── [...slug].vue            → ruta comodín

Sin directorio pages/, vue-router no se incluye en absoluto.

layouts/ ​

Wrappers que rodean el contenido de las páginas:

layouts/
├── default.vue              → usado por todas las páginas salvo que se indique otro
└── admin.vue                → las páginas lo activan mediante definePageMeta

middleware/ ​

Guards de navegación de rutas:

middleware/
├── auth.ts                  → aplicado por página mediante definePageMeta
└── analytics.global.ts      → se ejecuta en cada cambio de ruta

plugins/ ​

Ejecutan código al iniciar la app. Auto-registrados, ordenados por nombre de archivo:

plugins/
├── 01.auth.ts               → se ejecuta primero
├── 02.analytics.client.ts   → solo en el cliente
└── 03.logger.server.ts      → solo en el servidor

server/ ​

Todo lo que hay aquí se ejecuta en Nitro, no en Vue:

server/
├── api/users.get.ts         → GET /api/users
├── api/users.post.ts        → POST /api/users
├── api/users/[id].ts        → /api/users/:id
├── middleware/log.ts         → se ejecuta en cada petición al servidor
├── plugins/db.ts            → se ejecuta una vez al arrancar el servidor
└── utils/db.ts              → auto-importado en el código del servidor

public/ vs assets/ ​

Los archivos de public/ se sirven sin cambios en la URL raíz:

public/favicon.ico           → /favicon.ico
public/robots.txt            → /robots.txt

Los archivos de assets/ son procesados por el bundler (con hash, optimizados):

vue
<template>
  <img src="~/assets/images/hero.png" />
</template>

<style>
@import '~/assets/css/main.css';
</style>

Convenciones de nombres de archivo ​

PatrónSignificado
[param].vueParámetro de ruta dinámico
[[param]].vueParámetro de ruta opcional
[...slug].vueRuta comodín
(group)/Grupo de rutas (carpeta no incluida en la URL)
.client.vue / .client.tsSolo en el cliente
.server.vue / .server.tsSolo en el servidor
.global.tsMiddleware global

Archivos especiales ​

ArchivoPropósito
app.vueComponente raíz (opcional si existe pages/)
nuxt.config.tsConfiguración en tiempo de build (módulos, Vite, Nitro)
app.config.tsConfiguración en tiempo de ejecución (tema, feature flags)
error.vuePágina de error personalizada
.envVariables de entorno

Todo es opcional ​

Solo creas los directorios que necesitas. Una app Nuxt mínima puede ser solo app.vue y nuxt.config.ts. Añade pages/ cuando necesites enrutamiento, server/api/ cuando necesites endpoints de API, components/ cuando tengas componentes compartidos.

Ver también: ¿Cómo funciona el routing basado en archivos en Nuxt? · ¿Cómo funcionan los auto-imports en Nuxt? · ¿Qué son las layers de Nuxt?

Referencias ​

Publicado bajo la licencia MIT.