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 cosas algo más avanzadas.
¿Qué son las rutas dinámicas?
Con las rutas estáticas, cada fichero .astro
equivale a una única ruta concreta. Sin embargo, con las rutas dinámicas podemos crear un fichero .astro
que se encargue de crear múltiples rutas.
Imagina que tenemos una lista de usuarios y queremos hacer una zona de usuarios en nuestra web. Hacer manualmente una página para cada usuario sería muy tedioso. Realmente, la página va a ser la misma, sólo que utilizará los datos de cada usuario en cada página. En ese caso, nos interesa hacer una ruta dinámica: creamos sólo una página y le pasamos la lista de usuarios para que cree una ruta por cada uno.
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
/users/manzdev.html
/users/felixicaza.html
/users/blursoul_.html
/users/pheralb.html
...
¿Y 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 tener también una función exportada llamada getStaticPaths()
, que es la que se utiliza para generar las rutas.
Observa que la función getStaticPaths()
está devolviendo un username
con el nombre de cada usuario:
---
export function getStaticPaths() {
return [
{ params: { username: "manzdev" }},
{ params: { username: "felixicaza" }},
{ params: { username: "blursoul_" }},
{ params: { username: "pheralb" }},
];
}
const { username } = Astro.params;
---
<h1>{username}</h1>
Luego, obtenemos el username
de Astro.params
, que es donde se guardan los parámetros. Astro procesará de forma previa todos estos parámetros y generará una página para cada ruta, pasándole la información en cuestión.
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 modificar. 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 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 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}</h1>
[
{
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.
Múltiples niveles
En el caso que necesitemos múltiples niveles de rutas dinámicas, podemos resolverlo utilizando []
en las carpetas y ficheros necesarios. Por ejemplo, imaginemos que queremos la siguiente estructura:
/post/2025/astro-el-mejor-framework
/post/2025/bienvenidos
/post/2024/se-viene-2025
/post/2024/himno-a-clippy
...
src/pages/post/[year]/[slug].astro
Observa que en esta ocasión vamos a crear múltiples niveles y nos interesa que las rutas estén siempre en una carpeta /post/
, seguidas del año en cuestión y de el título del post, que llamaremos 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 todo desde el fichero
posts.json
. - 2️⃣ Creamos una función
getStaticPaths()
que devuelve unde . - 3️⃣ Mapeamos el
posts
y devolvemosparams
(parte de la URL) yprops
(info) - 4️⃣ Utilizamos las variables en nuestro marcado para crear la página.