Fecha publicación: 24 jun 2025

08. Detalle de un curso básico

Ahora que tenemos el listado de cursos, vamos a ver cómo podemos crear una página para el detalle de cada curso, de hecho vamos a generar varias..., por temas de SEO nos interesa tener una página por cada lección de curso.

Así que vamos a crear la siguiente estructura de carpetas:

src
└── pages
    └── training
        └── [trainingSlug]
            └── [lessonSlug].astro

¿Qué es eso entre corchetes? Es una forma de definir rutas dinámicas en Astro, es decir, que el nombre del archivo se convierte en una variable que podemos usar dentro del componente.

Así lo que hacemos es crear todas las lecciones de un curso en una misma carpeta, y cada lección será una página diferente, al estar usando SSG (Static Site Generation) se generarán todas las páginas en el momento de la construcción del sitio.

src/pages/training/[trainingSlug]/[lessonSlug]/index.astro

---
---

Ahora nos hace falta hacer como Dr. Strange en Infinity Wars y sacar todas las combinaciones posibles de lecciones y cursos.

Para hacer esto, Astro nos ofrece la función getStaticPaths, que nos permite generar todas las rutas posibles para una página dinámica.

src/pages/training/[trainingSlug]/[lessonSlug]/index.astro

---
import Layout from "@/layouts/layout.astro";
import { getTrainings } from "@/api";

export async function getStaticPaths() {
  const trainings = await getTrainings();
  return trainings.flatMap((training) =>
    training.lessons.map((lesson) => ({
      params: {
        trainingSlug: training.slug,
        lessonSlug: lesson.slug,
      },
      props: {
        training,
      },
    })),
  );
}
---

¿Qué hacemos aquí?

  • Obtenemos todos los cursos con sus lecciones (ojo lecciones está en un array dentro de cada curso).

  • Usamos flatMap para crear un array de objetos con las rutas posibles, donde cada objeto tiene los parámetros trainingSlug y lessonSlug.

¿Por qué flatMap? Porque queremos aplanar el array de lecciones de cada curso en un único array de rutas.

Y en ese array devolvemos:

  • params: un objeto con los parámetros de la ruta, que serán usados por Astro para generar las rutas dinámicas (sí, esos corchetes que hemos visto antes).

  • props: un objeto con las propiedades que queremos pasar al componente de la página (es decir cuando se vaya a pintar la página en concreto de un curso/lección, le pasamos el curso completo).

Ok, ya tenemos generados todas las rutas posibles, ahora vamos a ir montando cada página, just debajo del getStaticPaths, añadimos este código:

src/pages/training/[trainingSlug]/[lessonSlug]/index.astro

}

+ const { training } = Astro.props;
+ const currentLesson = training.lessons.find(
+  (lesson) => lesson.slug === Astro.params.lessonSlug
+ );
---

¿Qué estamos haciendo aquí?

  • De las propiedades que hemos pasado en props, extraemos el curso (training).

  • Buscamos la lección actual (currentLesson) dentro del array de lecciones del curso, usando el slug de la lección que hemos pasado en los parámetros de la ruta (Astro.params.lessonSlug), un recordatorio: el slug es una forma amigable de identificar un recurso, en este caso una lección, y suele ser una versión simplificada del título, por ejemplo "introduccion-a-astro".

Vamos ahora a mostrar los datos de la lección, de momento sin diseño.

Vamos a añadir este código justo después de las"rejas" (fences: ---)

src/pages/training/[trainingSlug]/[lessonSlug]/index.astro

<Layout title={training.title}>
  <div class="container mx-auto px-4">
    <h1 class="text-2xl font-bold mb-4">{currentLesson?.title}</h1>
    <p>{currentLesson?.content}</p>
  </div>
</Layout>

Y... ya podemos navegar desde un card de un curso al detalle del mismo, eso sí... se veo un poco feo :).

En el proximo video vamos a ver cómo darle un poco de diseño a esta página, para que quede más atractiva y usable.