Volver al inicio
Lección 4: Páginas Dinámicas

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

PASO 1 Crea el archivo con [id].astro

📁 Archivo:

src/pages/blog/[id].astro
1---
2// src/pages/blog/[id].astro
3
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 URL
14const { 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>
PASO 2 Astro genera estas rutas automáticamente:
✓ /blog/1 → muestra "Post: 1"
✓ /blog/2 → muestra "Post: 2"
✓ /blog/mi-primer-post → muestra "Post: mi-primer-post"

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].astro
3
4export function getStaticPaths() {
5 // Aquí normalmente traerías datos de una API o CMS
6 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 post
13 return posts.map(post => ({
14 params: { slug: post.slug },
15 props: { post } // ← Pasa los datos como props
16 }));
17}
18
19// Recibe los datos
20const { 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-astro
33 - /blog/javascript-moderno
34 - /blog/css-grid
35-->

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ágina
6 },
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].astro
3
4export function getStaticPaths() {
5 // Lista simple de IDs
6 return [
7 { params: { id: '1' } },
8 { params: { id: '2' } },
9 { params: { id: '3' } }
10 ];
11}
12
13const { id } = Astro.params; // Obtener el parámetro
14---
15
16<h1>Producto #{id}</h1>
17
18<!--
19 Genera:
20 - /productos/1
21 - /productos/2
22 - /productos/3
23-->

Ejemplo 2: params + props (con datos completos)

1---
2// src/pages/productos/[id].astro
3
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 URL
13 props: {'{'} producto {'}'} // Para usar en la página
14 }));
15}
16
17const {'{'} producto {'}'} = Astro.props; // Obtener los datos
18---
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].astro
3
4export async function getStaticPaths() {
5 // Fetch de una API en build time
6 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 post
12 }));
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].astro
3
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.

EJERCICIO 1

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.astro
3---
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.astro
3---
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].astro
3
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

EJERCICIO 2

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].astro
3
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 post
30 return posts.map(post => ({
31 params: {'{'} slug: post.slug {'}'}, // Para la URL
32 props: {'{'} post {'}'} // Datos del post
33 }));
34}
35
36// Recibir los datos del post
37const {'{'} 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.