Rutas dinámicas

Cómo crear rutas flexibles y variables


Hasta ahora, sólo hemos visto como crear rutas simples con Astro, sin embargo, Astro permite crear rutas dinámicas, un tipo de ruta más potente y flexible para hacer detalles algo más avanzados.

¿Qué son las rutas dinámicas?

Con las rutas estáticas, cada fichero .astro genera una única página para una ruta concreta. Sin embargo, con las rutas dinámicas podemos crear un fichero .astro que se encargará de crear múltiples páginas para varias rutas diferentes.

Imagina que tenemos una lista de usuarios y queremos hacer una página de perfil de usuario para cada uno. Hacer manualmente una página para cada usuario sería muy tedioso, sobre todo en el caso que tengamos muchos usuarios. La página realmente va a ser la misma, sólo que utilizará los datos de cada usuario en cada página concreta. Sería suficiente crear una página «molde» que se usará como base para insertar en ella los datos de cada usuario y generar diferentes páginas.

Archivos de páginas [dinámicas]

En Astro podemos crear una página dinámica estableciendo un nombre de fichero con corchetes, por ejemplo, src/pages/users/[username].astro. En este caso, username será el parámetro que usaremos para identificar el nombre de cada usuario.

Al generar las rutas, [username] se reemplazará por el nombre de cada usuario:

src/pages/users/[username].astro

Esta página generará las siguientes rutas:

/users/manzdev.html
/users/felixicaza.html
/users/blursoul_.html
/users/pheralb.html
...

¿Cómo conseguimos estas rutas en Astro? Vamos a verlo.

La función getStaticPaths()

Como hemos mencionado, el primer paso es nombrar nuestra carpeta o fichero con un nombre entre corchetes. Una vez hecho esto, nuestra página .astro debe exportar una función llamada getStaticPaths(), que es la que se utiliza para generar las rutas.

Recuerda que Astro, por defecto, no trabaja en la web alojada. Trabaja en desarrollo y genera las páginas estáticas que luego son las que subimos a un servidor. La función getStaticPaths() se ejecuta en nuestro equipo cuando hacemos un npm run build, y no en el servidor.

Esta función debe devolver una lista de objetos que contenga los parámetros de la ruta dinámica: en nuestro ejemplo, el username, que es el que forma parte de la URL. Sin esta función getStaticPaths() nuestra ruta dinámica no funcionará y dará error.

Veamos como implementar la función getStaticPaths():

La función getStaticPaths() debe devolver un de que contienen uno o varios parámetros, que forman parte de nuestra URL, y que en nuestro ejemplo hemos dicho que sería /users/[username]:

---
export function getStaticPaths() {
  return [
    { params: { username: "manzdev" }},
    { params: { username: "felixicaza" }},
    { params: { username: "blursoul_" }},
    { params: { username: "pheralb" }},
  ];
}

const { username } = Astro.params;
---
<h1>{username}</h1>

En este caso, lo que estamos indicando es que vamos a generar 4 páginas estáticas. Una por cada objeto del . Astro generará una página por cada uno de esos objetos y modificará el [username] de la URL por el username que le devolvemos en el objeto params.

Por otro lado, en el contenido de la página, podemos obtener los valores desde Astro.params, y así poderlos utilizar en la propia página para mostrar o traernos más contenido relacionado.

Ahora, en lugar de indicar los nombres de usuario manualmente, vamos a automatizarlos y recogerlos de una estructura de datos que sea más fácil de separar (y modificar en el futuro). Observa que ahora partimos de un users con los nombres:

---
const users = ["manzdev", "felixicaza", "blursoul_", "pheralb"];

export function getStaticPaths() {
  return users.map(username => {
    return { params: { username }}
  });
}

const { username } = Astro.params;
---
<h1>{username}</h1>

En el interior de la función getStaticPaths() procesamos ese y devolvemos el que esta función espera, un objeto con params. Aunque no lo hemos hecho aún, junto a los params podríamos añadir props con información adicional para añadir.

Vamos ahora un paso más allá. En el fichero src/data/users.json tenemos un de donde cada objeto tiene información sobre un usuario: rol, imagen, color, etc... Importamos esa información a un objeto en Astro y lo utilizamos en la función getStaticPaths():

---
import users from "../data/users.json";

export async function getStaticPaths() {
  return users.map(({ username, role, image, color }) => {
    return {
      params: { username },
      props: { role, image, color }
    }
  });
}

const { username } = Astro.params;
const { role, image, color } = Astro.props;
---
<h1>{username} ({role}, {color})</h1>
<img src={image} alt={username} />
[
  {
    username: "ManzDev",
    role: "streamer",
    image: "/assets/manzdev.avif",
    color: "indigo",
    ...
  },
  ...
]

Observa que con el .map() recorremos todos los usuarios creamos un objeto con los parámetros que forman parte de la URL (username) y el resto de parámetros que los pasamos como props para que estén disponibles en la parte inferior del frontmatter del componente de .astro.

Esto nos permite crear múltiples páginas que dependan de información externa sin tener que crear las páginas una a una.

Páginas con múltiples niveles

Creando páginas dinámicas, nos puede interesar crear rutas con múltiples niveles. Cuando decimos «múltiples niveles» nos referimos que hay varias secciones entre slash /, como podemos ver en estos ejemplos:

/post/2025/astro-el-mejor-framework
/post/2025/bienvenidos
/post/2024/se-viene-2025
/post/2024/himno-a-clippy

Observa que tenemos un primer nivel post, un segundo nivel que es el año, y un tercer nivel que es el título de la página. En el caso que necesitemos estos múltiples niveles de rutas dinámicas, podemos resolverlo utilizando [] en las carpetas y varias veces, no sólo en el fichero como hicimos más atrás.

Para el ejemplo anterior bastaría con crear una ruta dinámica src/pages/post/[year]/[slug].astro:

  • 1️⃣ Las rutas estarán siempre en una carpeta /post/. Este es fijo.
  • 2️⃣ Luego, una carpeta para el año, que llamaremos [year].
  • 3️⃣ En su interior, tendremos un fichero llamado [slug].astro, para los títulos.

Esto proporciona a Astro la suficiente información para saber que las rutas tendrán dos parámetros: el año con [year] y el título del post con [slug].

Vamos ahora con el contenido de nuestro fichero src/pages/post/[year]/[slug].astro:

---
import posts from "../../../data/posts.json";

export async function getStaticPaths() {
  return posts.map(post => ({
    params: {
      year: post.year,
      slug: post.slug
    },
    props: {
      post
    }
  }));
}

const { post } = Astro.props;
const { year, slug } = Astro.params;
---
<h1>{post.title}</h1>
<p>{post.content}</p>
<small>Publicado en: {year} - URL: /post/{year}/{slug}</small>
  • 1️⃣ Empezamos importando toda la información relevante desde el fichero src/data/posts.json.
  • 2️⃣ Creamos una función getStaticPaths() que devuelve un de .
  • 3️⃣ Mapeamos el array posts y devolvemos params (parte de la URL) y props (info).
  • 4️⃣ Utilizamos las variables en nuestro marcado para crear la página.

Observa la siguiente tabla y ten en cuenta que puedes crear todo tipo de combinaciones alternativas para crear múltiples rutas dinámicas:

Ruta dinámicaRuta generada
src/pages/users/[username].astro/users/manzdev/
src/pages/post/[date]-[slug].astro/post/2025-07-24-mi-primer-post
src/pages/post/[year]/[month]/[slug].astro/post/2025/07/mi-primer-post
src/pages/post/[...path].astro/post/2025/07/mi-primer-post

Parámetros complejos

Si te fijaste en la última fila de la tabla anterior, probablemente te habrá extrañado un poco esta ruta dinámica. En este caso estamos utilizando el operador ... (spread) para obtener múltiples niveles en un sólo parámetro.

En este caso, el parámetro path va a capturar el texto de la ruta completa: 2025/07/mi-primer-post. Luego, nosotros podemos separarlo por / y trabajar con sus partes individuales:

---
export function getStaticPaths() {
  return [
    { params: { path: "2025/06/bienvenidos" }},
    { params: { path: "2025/06/mi-primer-post" }}
  ]
}

const [ year, month, slug ] = Astro.params.path.split("/");
---

<ul>
  <li>Year: {year}</li>
  <li>Month: {month}</li>
  <li>Slug: {slug}</li>
</ul>

Esto podría ser especialmente interesante en algunos casos donde quieres trabajar con el path conjunto para simplificar la obtención de información.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev