Páginas Dinámicas: [id].astro
Aprende a crear páginas con parámetros dinámicos y getStaticPaths()
¿Qué son las rutas dinámicas?
Las rutas dinámicas te permiten crear páginas con parámetros variables. En vez de crear un archivo por cada producto, post o usuario, creas UN archivo que genera MÚLTIPLES páginas.
Ejemplo: Un archivo [id].astro puede generar /productos/1, /productos/2, /productos/laptop, etc.
1. Rutas dinámicas básicas
Usa [corchetes] en el nombre del archivo para crear parámetros dinámicos.
Ejemplo: src/pages/blog/[id].astro puede generar /blog/1, /blog/2, /blog/post-123, etc.
Ejemplo: Blog con posts dinámicos
[id].astro 📁 Archivo:
src/pages/blog/[id].astro 1---2// src/pages/blog/[id].astro3 4// 1. Define qué valores puede tener [id]5export function getStaticPaths() {6 return [7 { params: { id: '1' } },8 { params: { id: '2' } },9 { params: { id: 'mi-primer-post' } }10 ];11}12 13// 2. Obtén el parámetro de la URL14const { id } = Astro.params;15---16 17<html>18 <body>19 <h1>Post: {id}</h1>20 <p>Estás viendo el post con ID: {id}</p>21 </body>22</html> Importante: getStaticPaths() es OBLIGATORIO en rutas dinámicas. Astro necesita saber qué rutas generar en build time.
Ejemplo avanzado: Con datos reales
1---2// src/pages/blog/[slug].astro3 4export function getStaticPaths() {5 // Aquí normalmente traerías datos de una API o CMS6 const posts = [7 { slug: 'aprendiendo-astro', titulo: 'Aprendiendo Astro', contenido: '...' },8 { slug: 'javascript-moderno', titulo: 'JavaScript Moderno', contenido: '...' },9 { slug: 'css-grid', titulo: 'CSS Grid', contenido: '...' }10 ];11 12 // Genera una ruta por cada post13 return posts.map(post => ({14 params: { slug: post.slug },15 props: { post } // ← Pasa los datos como props16 }));17}18 19// Recibe los datos20const { post } = Astro.props;21---22 23<html>24 <body>25 <h1>{post.titulo}</h1>26 <p>{post.contenido}</p>27 </body>28</html>29 30<!--31 📌 Rutas generadas:32 - /blog/aprendiendo-astro33 - /blog/javascript-moderno34 - /blog/css-grid35-->2. ¿Qué es getStaticPaths()?
getStaticPaths() es una función especial que DEBES exportar en cualquier página con rutas dinámicas ([param]).
Su trabajo es decirle a Astro qué páginas generar en tiempo de build. Sin ella, Astro no sabría qué valores usar para [param].
¿Por qué es necesaria?
❌ Sin getStaticPaths()
Tienes: blog/[id].astro
Pero Astro pregunta:
- • ¿Qué valores tiene [id]?
- • ¿Genero /blog/1, /blog/2, /blog/abc?
- • ¿Cuántas páginas creo?
⚠️ Build falla
✅ Con getStaticPaths()
Le dices a Astro:
return [
{ params: { id: '1' } },
{ params: { id: '2' } }
]
Astro genera:
- • /blog/1
- • /blog/2
✓ Build exitoso
Importante: Astro es un generador de sitios estáticos (SSG). Necesita saber TODAS las páginas a crear en build time. No puede generar páginas "on demand" como frameworks server-side.
Estructura y anatomía
La función debe retornar un array de objetos. Cada objeto representa una página:
1export function getStaticPaths() {2 return [3 {4 params: { id: 'valor-1' }, // ← El valor del parámetro [id]5 props: { /* datos opcionales */ } // ← Datos extra para la página6 },7 {8 params: { id: 'valor-2' },9 props: { /* datos opcionales */ }10 }11 ];12}params (obligatorio)
Define el valor del parámetro dinámico
params: { id: '123' } Para: [id].astro
props (opcional)
Datos adicionales para esa página
props: { titulo: '...' } Accesible vía Astro.props
Ejemplos prácticos
Ejemplo 1: Solo params (IDs simples)
1---2// src/pages/productos/[id].astro3 4export function getStaticPaths() {5 // Lista simple de IDs6 return [7 { params: { id: '1' } },8 { params: { id: '2' } },9 { params: { id: '3' } }10 ];11}12 13const { id } = Astro.params; // Obtener el parámetro14---15 16<h1>Producto #{id}</h1>17 18<!--19 Genera:20 - /productos/121 - /productos/222 - /productos/323-->Ejemplo 2: params + props (con datos completos)
1---2// src/pages/productos/[id].astro3 4export function getStaticPaths() {5 const productos = [6 { id: '1', nombre: 'Laptop', precio: 999 },7 { id: '2', nombre: 'Mouse', precio: 29 },8 { id: '3', nombre: 'Teclado', precio: 79 }9 ];10 11 return productos.map(producto => ({12 params: {'{'} id: producto.id {'}'}, // Para la URL13 props: {'{'} producto {'}'} // Para usar en la página14 }));15}16 17const {'{'} producto {'}'} = Astro.props; // Obtener los datos18---19 20<h1>{'{'}producto.nombre{'}'}</h1>21<p>Precio: {producto.precio{'}'}</p>22 23<!--24 Genera:25 - /productos/1 → Muestra "Laptop - $999"26 - /productos/2 → Muestra "Mouse - $29"27 - /productos/3 → Muestra "Teclado - $79"28-->Ejemplo 3: Datos desde una API
1---2// src/pages/posts/[slug].astro3 4export async function getStaticPaths() {5 // Fetch de una API en build time6 const response = await fetch('https://api.example.com/posts');7 const posts = await response.json();8 9 return posts.map(post => ({10 params: { slug: post.slug },11 props: { post } // Toda la data del post12 }));13}14 15const { post } = Astro.props;16---17 18<article>19 <h1>{post.title}</h1>20 <p>{post.content}</p>21 <small>Por {post.author}</small>22</article>23 24<!--25 ✨ Ventaja: Solo hace el fetch UNA VEZ en build time.26 Las páginas son estáticas y ultra rápidas.27-->Casos especiales y tips
1. Múltiples parámetros
Si tienes [categoria]/[id].astro:
params: { categoria: 'tecnologia', id: '123' } Genera: /tecnologia/123
2. Slugs con formato
Los valores pueden tener guiones, números, letras:
params: { slug: 'mi-primer-post-2025' } Genera: /blog/mi-primer-post-2025
3. Con paginación
Astro tiene una utilidad paginate() para dividir listas:
import { paginate } from 'astro:content';
export function getStaticPaths({ paginate }) {
const posts = [...]; // tus posts
return paginate(posts, { pageSize: 10 });
} 3. Rutas Catch-All (comodín)
Las rutas catch-all capturan CUALQUIER ruta que coincida. Usa [...resto] (con tres puntos).
Ejemplo: src/pages/docs/[...slug].astro captura /docs/intro, /docs/guia/instalacion, /docs/api/fetch/ejemplos, etc.
Ejemplo:
1---2// src/pages/docs/[...slug].astro3 4export function getStaticPaths() {5 return [6 { params: { slug: 'intro' } },7 { params: { slug: 'guia/instalacion' } },8 { params: { slug: 'guia/primeros-pasos' } },9 { params: { slug: 'api/fetch/ejemplos' } }10 ];11}12 13const { slug } = Astro.params;14---15 16<html>17 <body>18 <h1>Documentación</h1>19 <p>Ruta: {slug}</p>20 </body>21</html>22 23<!--24 ✅ Captura:25 /docs/intro → slug = "intro"26 /docs/guia/instalacion → slug = "guia/instalacion"27 /docs/api/fetch/ejemplos → slug = "api/fetch/ejemplos"28-->Uso común: Documentación, blogs con categorías anidadas, o sistemas de archivos virtuales.
4. Ejercicios Prácticos
Pon a prueba lo que has aprendido con estos ejercicios. Intenta resolverlos por tu cuenta antes de ver la solución.
Portfolio con proyectos
Enunciado:
Crea un portfolio personal con las siguientes páginas:
- 1.
index.astro- Página de inicio con tu nombre y descripción - 2.
about.astro- Página "Sobre mí" con tu biografía - 3.
proyectos/[id].astro- Página dinámica para proyectos individuales
Para la página de proyectos:
- • Usa
getStaticPaths()para crear 3 proyectos con IDs:'1','2','3' - • Muestra el ID del proyecto en la página
Objetivo: Practicar rutas estáticas (index.astro, about.astro) y rutas dinámicas ([id].astro con getStaticPaths).
Ver Solución
src/pages/index.astro
1---2// src/pages/index.astro3---4 5<!DOCTYPE html>6<html lang="es">7<head>8 <meta charset="UTF-8">9 <title>Mi Portfolio</title>10</head>11<body>12 <h1>Bienvenido a mi Portfolio</h1>13 <p>Soy [Tu Nombre], desarrollador web.</p>14 15 <nav>16 <a href="/">Inicio</a>17 <a href="/about">Sobre mí</a>18 <a href="/proyectos/1">Ver Proyectos</a>19 </nav>20</body>21</html>src/pages/about.astro
1---2// src/pages/about.astro3---4 5<!DOCTYPE html>6<html lang="es">7<head>8 <meta charset="UTF-8">9 <title>Sobre mí</title>10</head>11<body>12 <h1>Sobre mí</h1>13 <p>Me dedico al desarrollo web hace 2 años.</p>14 <p>Especializado en JavaScript, React y Astro.</p>15 16 <a href="/">Volver al inicio</a>17</body>18</html>src/pages/proyectos/[id].astro
1---2// src/pages/proyectos/[id].astro3 4export function getStaticPaths() {5 return [6 {'{'} params: {'{'} id: '1' {'}'} {'}'},7 {'{'} params: {'{'} id: '2' {'}'} {'}'},8 {'{'} params: {'{'} id: '3' {'}'} {'}'}9 ];10}11 12const {'{'} id {'}'} = Astro.params;13---14 15<!DOCTYPE html>16<html lang="es">17<head>18 <meta charset="UTF-8">19 <title>Proyecto {'{'}id{'}'}</title>20</head>21<body>22 <h1>Proyecto #{'{'}id{'}'}</h1>23 <p>Detalles del proyecto número {'{'}id{'}'}.</p>24 25 <nav>26 <a href="/proyectos/1">Proyecto 1</a>27 <a href="/proyectos/2">Proyecto 2</a>28 <a href="/proyectos/3">Proyecto 3</a>29 </nav>30 31 <a href="/">Volver al inicio</a>32</body>33</html> Rutas generadas: /, /about, /proyectos/1, /proyectos/2, /proyectos/3
Blog con datos completos
Enunciado:
Crea un blog donde cada post tenga datos completos (título, contenido, autor, fecha). Usa getStaticPaths() con params + props.
Requisitos:
- 1. Crea
src/pages/blog/[slug].astro - 2. Define un array con 3 posts, cada uno con:
slug,titulo,contenido,autor,fecha - 3. Usa
getStaticPaths()para generar las rutas - 4. Pasa los datos del post con
props - 5. Muestra todos los datos en la página
Objetivo: Practicar rutas dinámicas con datos completos usando params y props. Entender cómo pasar información a las páginas generadas.
Ver Solución
src/pages/blog/[slug].astro
1---2// src/pages/blog/[slug].astro3 4export function getStaticPaths() {5 const posts = [6 {7 slug: 'aprendiendo-astro',8 titulo: 'Aprendiendo Astro',9 contenido: 'Astro es un framework moderno para crear sitios web ultra rápidos.',10 autor: 'María García',11 fecha: '2025-01-15'12 },13 {14 slug: 'javascript-moderno',15 titulo: 'JavaScript Moderno en 2025',16 contenido: 'Las últimas características de ES2025 que debes conocer.',17 autor: 'Juan Pérez',18 fecha: '2025-01-20'19 },20 {21 slug: 'tailwind-css',22 titulo: 'Tailwind CSS: Guía Rápida',23 contenido: 'Aprende a usar Tailwind CSS para estilizar tus aplicaciones.',24 autor: 'Ana López',25 fecha: '2025-01-25'26 }27 ];28 29 // Generar una ruta por cada post30 return posts.map(post => ({31 params: {'{'} slug: post.slug {'}'}, // Para la URL32 props: {'{'} post {'}'} // Datos del post33 }));34}35 36// Recibir los datos del post37const {'{'} post {'}'} = Astro.props;38---39 40<!DOCTYPE html>41<html lang="es">42<head>43 <meta charset="UTF-8">44 <title>{'{'}post.titulo{'}'}</title>45</head>46<body>47 <article>48 <h1>{'{'}post.titulo{'}'}</h1>49 50 <div>51 <small>Por {'{'}post.autor{'}'} • {'{'}post.fecha{'}'}</small>52 </div>53 54 <p>{'{'}post.contenido{'}'}</p>55 </article>56 57 <nav>58 <h3>Otros posts:</h3>59 <ul>60 <li><a href="/blog/aprendiendo-astro">Aprendiendo Astro</a></li>61 <li><a href="/blog/javascript-moderno">JavaScript Moderno</a></li>62 <li><a href="/blog/tailwind-css">Tailwind CSS</a></li>63 </ul>64 </nav>65</body>66</html>Rutas generadas:
/blog/aprendiendo-astro→ Muestra el post "Aprendiendo Astro"/blog/javascript-moderno→ Muestra el post "JavaScript Moderno"/blog/tailwind-css→ Muestra el post "Tailwind CSS"
Conceptos practicados: getStaticPaths() con array de objetos, uso de .map() para generar rutas, params para la URL, props para pasar datos, Astro.props para recibir datos.