Next.js -Rutas dinámicas avanzadas [slug], […slug] y [[…slug]]
[slug] Slug simple […slug] Catch-all Slug [[…slug]]Optional Catch-all
Next.js -Rutas dinámicas avanzadas [slug], […slug] y [[…slug]]

Introducción
[slug]Slug simple[...slug]Catch-all Slug[[...slug]]Optional Catch-all
Lee el artículo gratis → friends link o en Github
Todos los ejemplos los podrás encontrar en el repositorio next.js-15.3–1[ref] Acá puedes ver todas las stories de next.js [ref]
Rutas dinámica [slug], […slug] y [[…slug]]
Este tipo de rutas o segmentos dinámicos son útiles cuando no sabes cuántos niveles tendrá la URL o cuando quieres mostrar páginas con URLs amigables y flexibles.
Un slug es una parte de la URL que representa un valor único. Ejemplo: /blog/mi-primer-post, donde mi-primer-post es el slug.
Tipos de slugs
[slug]— Slug simple, donde solo un segmento es obligatorio.[...slug]— Catch-all slug, donde uno o más segmentos son obligatorios.[[...slug]]— Optional Catch-all, donde ninguno o más segmentos son opcionales.
:: [slug] Slug simple
Un slug es un segmento dinámico que permite capturar un valor variable desde la URL. Funciona igual que una ruta dinámica, pero su uso está enfocado en representar nombres legibles, amigables para humanos y óptimos para SEO. Por ejemplo: /blog/react-introduction, /blog/running-shoes , etc.
En todos los casos, react-introduction, running-shoes, son los valores que el segmento [slug] capturará desde la URL.
¿Cómo se crean?
La estructura es muy similar a cualquier ruta dinámica:
- Crear una carpeta con el nombre de la ruta deseada, nombrandola entre corchetes
[slug]. - Dentro de esa carpeta, crea un archivo llamado
page.tsx. - Exporta un componente de React por defecto.
- Accede al parámetro dinámico desde params en el componente de página.
Técnicamente no hay una diferencia funcional entre una ruta dinámica y una ruta slug simple. Más bien la diferencia radica en el propósito o intención del uso:
- Ruta dinámica — Cualquier valor que usa
[]para capturar un valor variable. - Slug simple — Un nombre amigable (legible para humanos y SEO) usado como parámetro dinámico.
Ejemplo
src/app/blog/[slug]/page.tsx → /blog/:slug/
// src/app/blog/[slug]/page.tsx
interface PageParams {
slug: string;
}
// La propiedad params es asincrona, por lo que se debe de tratar como promesa
interface BlogPageProps {
params: Promise<PageParams>;
}
export default async function BlogPostPage({ params }: BlogPageProps) {
// Desestructuramos el `slug` de params, ya que es una promesa
const { slug } = await params;
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Post: {slug}</h1>
</div>
);
}
Al iniciar el servidor (npm run dev), podrás acceder a esta página visitando:
http://localhost:3000/blog/running-shoes

app/blog/[slug]/page.js → /blog/running-shoes → { id: 'running-shoes' }
app/blog/[slug]/page.js → /blog/react-hooks → { id: 'react-hooks' }
app/blog/[slug]/page.js → /blog/js-patterns → { id: 'js-patterns' }
Descarga el proyecto actual [ref] (branch: advanced-dynamic-routes)
¿Cómo funcionan?
Cuando accedes a una ruta como /blog/running-shoes, Next.js:
- Detecta que
[slug]es un segmento dinámico. - Extrae
running-shoescomo parámetroparams.slug. - Ejecuta el componente en
page.tsx. - Renderiza la página con el contenido basado en el slug.
Importante: Solo permite un segmento dinámico. No puedes hacer
*/blog/react/hooks*
Debes tener cuidado cuando uses en la misma ruta el mismo parámetro dinámico en una ruta. Por ejemplo:
/app/product/[slug]/page.tsx
/app/product/[id]/page.tsx
Esto genera el error:

You cannot use different slug names for the same dynamic path ('id' !== 'slug')
Next.js detecta que estás usando el mismo nivel de carpeta o la misma ruta dinámica, pero con nombres distintos, y eso rompe la consistencia del enrutado.
Tip: Usa el mismo nombre de parámetro (
*[slug], `[id]*,[categoryId]`, etc.) en todas las partes de la ruta y no mezcles nombres en la misma rama de rutas.
Recuerda: que si intentas acceder a
/blogsaldrá el mensaje:404 | This page could not be found.
¿Rutas dinámicas o segmento dinámico slug?

:: […slug] Catch-all Slug (todos los segmentos)
[...slug] permite capturar uno o más segmentos dinámicos en una sola ruta. Ideal cuando no conoces cuántos niveles tendrá una URL. Por ejemplo: /docs/javascript,/docs/javascript/variables, /docs/javascript/variables/const , etc.
¿Cómo se crean?
La estructura es muy similar al segmento dinámico slug:
- Crear una carpeta con el nombre de la ruta deseada, nombrandola entre corchetes con tres puntos
[...slug]. - Dentro de esa carpeta, crea un archivo llamado
page.tsx. - Exporta un componente de React por defecto.
- Accede al parámetro dinámico desde params en el componente de página como un arreglo
string[].
Ejemplo
src/app/docs/[...slug]/page.tsx → /docs/javascript
src/app/docs/[...slug]/page.tsx → /docs/javascript/variables
src/app/docs/[...slug]/page.tsx → /docs/javascript/variables/let
// src/app/blog/[slug]/page.tsx
interface PageParams {
slug: string[];
}
// La propiedad params es asincrona, por lo que se debe de tratar como promesa
interface BlogPageProps {
params: Promise<PageParams>;
}
export default async function DocsPage({ params }: BlogPageProps) {
// Desestructuramos el `slug` de params, ya que es una promesa
const { slug } = await params;
// Unimos los segmentos del slug para mostrarlos como una ruta
const fullPath = slug.join('/');
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Ruta: /docs/{fullPath}</h1>
<p className="text-lg">Params: {JSON.stringify(slug, null, 2)}</p>
</div>
);
}
Al iniciar el servidor (npm run dev), podrás acceder a esta página visitando:
http://localhost:3000/docs/javascript
http://localhost:3000/docs/javascript/variables
http://localhost:3000/docs/javascript/variables/let

app/docs/[...slug]/page.js
→ /docs/react
→ ['react']
app/docs/[...slug]/page.js
→ /docs/react/hooks
→ ['react','hooks']
app/docs/[...slug]/page.js
→ /docs/react/hooks/usestate
→ ['react','hooks','usestate']
Descarga el proyecto actual [ref] (branch: advanced-dynamic-routes)
¿Cómo funcionan?
Cuando accedes a una ruta como /docs/react/hooks, Next.js:
- Detecta que
[[...slug]]es una ruta dinámica con uno o más segmentos dinámicos. - Extrae
[react, hooks]como arreglo deparams.slug. - Ejecuta el componente en
page.tsx. - Renderiza la página con el contenido basado en el slug.
Importante: Debe tener al menos un segmento obligatorio. No puedes enviar rutas vacías (ej.
*/docs) ya que marcará un error. **Utilizalo cuando sepas que siempre habrá al menos un segmento.***
¿Cuándo usar [...slug]?
- Cuándo esperas múltiples niveles en una ruta.
- Cuando tiene la ruta tiene al menos un segmento.
- Cuándo quieres centralizar el manejo de rutas dinámicas anidadas.
- Para páginas de documentación, menús, etc.
:: [[…slug]] — Optional Catch-all
[...slug] permite capturar opcionalmente cero o más segmentos dinámicos en una sola ruta. Ideal cuando puede tener o no parámetros y además no conoces cuántos niveles tendrá una URL. Por ejemplo: /store, /store/mens , /store/mens/shirts, etc.
Cuando no hay segmentos, params.slug será undefined, y puedes utilizar alguna validación para manejarlo como arreglo vacío.
¿Cómo se crean?
La estructura es muy similar al segmento dinámico slug:
- Crear una carpeta con el nombre de la ruta deseada, nombrandola entre corchetes con tres puntos
[[...slug]]. - Dentro de esa carpeta, crea un archivo llamado
page.tsx. - Exporta un componente de React por defecto.
- Accede al parámetro dinámico desde params en el componente de página como un arreglo
string[]
Ejemplo
src/app/store/[[...slug]]/page.tsx → /store
src/app/store/[[...slug]]/page.tsx → /store/mens
src/app/store/[[...slug]]/page.tsx → /store/woman
src/app/store/[[...slug]]/page.tsx → /store/woman/dress
// src/app/store/[[...slug]]/page.tsx
interface PageParams {
slug?: string[];
}
// La propiedad params es asincrónica, por lo que se debe tratar como promesa
interface StorePageProps {
params: Promise<PageParams>;
}
export default async function StorePage({ params }: StorePageProps) {
// Desestructuramos el `slug` de params, ya que es una promesa
const { slug } = await params;
// Validamos si `slug` está definido, de lo contrario mostramos un mensaje predeterminado
const fullPath = slug ? slug.join('/') : 'Inicio';
if (!slug) {
return (
<p className="text-lg">Estás en la página principal de la tienda.</p>
);
}
return (
<div className="p-4">
<h1 className="text-2xl font-bold">Tienda: {fullPath}</h1>
<p className="text-lg">Ruta completa: /store/{fullPath}</p>
</div>
);
}
Al iniciar el servidor (npm run dev), podrás acceder a esta página visitando:
http://localhost:3000/store
http://localhost:3000/store/mens
http://localhost:3000/store/mens/dress

app/store/[...slug]/page.js
→ /store
→ undefined
app/docs/[...slug]/page.js
→ /store/mens
→ ['mens']
app/docs/[...slug]/page.js
→ /store/mens/shoes
→ ['mens','shoes']
Descarga el proyecto actual [ref] (branch: advanced-dynamic-routes)
¿Cómo funcionan?
Cuando accedes a una ruta como /store/mens/shoes, Next.js:
- Detecta que
[[...slug]]es una ruta dinámica con ninguno, uno o más segmentos dinámicos. - Extrae en un arreglo los parámetros que tiene
params.slug. - Ejecuta el componente en
page.tsx. - Renderiza la página con el contenido basado en el slug
Importante: Cuando no se manda algún segmento va a retornar
*undefined*, así que debes validarlo. Utilízalo cuando quieras una máxima flexibilidad y aceptar rutas vacías.
¿Cuándo usar [[...slug]]?
- Cuando la ruta raíz (ej.
/store) debe renderizar algo por defecto. - Cuando quieres que la ruta y cualquier subruta usen el mismo componente (ej.
/storeo/store/a/b/c) - Ideal para mostrar contenido por niveles y una vista inicial vacía o genérica.
Nota: En los ejemplos anteriores (
[slug],[...slug],[[...slug]]) utilizamos*await params, lo cual aplica para componentes que se ejecutan en el servidor (SSR o SSG), para componentes del lado del cliente (CSR), se debe utilizar el hook `useParams`* de Next.js. En la siguiente entrada veremos ejemplos combinando rutas dinámicas avanzadas con CSR, SSR y SSG, utilizando APIs públicas para que comprendas cuándo y cómo usar cada estrategia correctamente.
Resumiendo…

Hasta este punto, has comprendido las rutas avanzadas como [slug], [...slug] y [[...slug]]. También sabes identificar las diferencias entre cada una de ellas y en qué casos utilizar cada tipo según la estructura y necesidades de tu aplicación.
En la siguiente entrada, aprenderás a combinar las rutas dinámicas avanzadas con las estrategias de renderizado híbrido (CSR, SSR y SSG), aplicándolas en ejemplos prácticos utilizando APIs públicas.
Siguiente: Next.js -Renderizado híbrido (CSR, SSR, SSG) con rutas dinámicas avanzadas ([slug], […slug], [[…slug]]) Anterior: Next.js — Renderizado híbrido (CSR, SSR, SSG)
메타데이터
- post_id
- 95f4cd0a982e
- slug
- next-js-rutas-dinámicas-avanzadas-slug-slug-y-slug-95f4cd0a982e
- url
- https://medium.com/@mauriciogc/next-js-rutas-din%C3%A1micas-avanzadas-slug-slug-y-slug-95f4cd0a982e
- canonical_url
- https://medium.com/@mauriciogc/next-js-rutas-din%C3%A1micas-avanzadas-slug-slug-y-slug-95f4cd0a982e
- author_url
- https://medium.com/@mauriciogc
- status
- ok
- fetched_at
- 2026-06-26 03:39:16