Saltar al contenido

Kontent.ai y Astro

Kontent.ai es un CMS headless que te permite gestionar el contenido de forma estructurada y modular, con el apoyo de funciones de IA.

En esta sección, utilizarás el SDK de TypeScript de Kontent.ai para conectar tu proyecto de Kontent.ai a tu aplicación de Astro.

Para empezar, necesitarás lo siguiente:

  1. Proyecto de Kontent.ai - Si aún no tienes una cuenta de Kontent.ai, regístrate gratis y crea un nuevo proyecto.

  2. Claves de API de Delivery - Necesitarás el Environment ID para el contenido publicado y la clave de API de Preview para obtener borradores (opcional). Ambas claves se encuentran en la pestaña Environment Settings -> API keys en Kontent.ai.

Para añadir tus credenciales de Kontent.ai a Astro, crea un archivo .env en la raíz de tu proyecto con las siguientes variables:

.env
KONTENT_ENVIRONMENT_ID=YOUR_ENVIRONMENT_ID
KONTENT_PREVIEW_API_KEY=YOUR_PREVIEW_API_KEY

Ahora, estas variables de entorno se pueden usar en tu proyecto de Astro.

Si deseas obtener IntelliSense de TypeScript para estas variables de entorno, puedes crear un nuevo archivo env.d.ts en el directorio src/ y configurar ImportMetaEnv de esta manera:

src/env.d.ts
interface ImportMetaEnv {
readonly KONTENT_ENVIRONMENT_ID: string;
readonly KONTENT_PREVIEW_API_KEY: string;
}

Tu directorio raíz ahora debería incluir estos nuevos archivos:

  • Directoriosrc/
    • env.d.ts
  • .env
  • astro.config.mjs
  • package.json

Para conectar Astro con tu proyecto de Kontent.ai, instala el SDK de TypeScript de Kontent.ai:

Ventana de la terminal
npm install @kontent-ai/delivery-sdk

A continuación, crea un nuevo archivo llamado kontent.ts en el directorio src/lib/ de tu proyecto de Astro.

src/lib/kontent.ts
import { createDeliveryClient } from "@kontent-ai/delivery-sdk";
export const deliveryClient = createDeliveryClient({
environmentId: import.meta.env.KONTENT_ENVIRONMENT_ID,
previewApiKey: import.meta.env.KONTENT_PREVIEW_API_KEY,
});

Esta implementación crea un nuevo objeto DeliveryClient utilizando las credenciales del archivo .env.

Finalmente, el directorio raíz de tu proyecto de Astro ahora debería incluir estos nuevos archivos:

  • Directoriosrc/
    • Directoriolib/
      • kontent.ts
    • env.d.ts
  • .env
  • astro.config.mjs
  • package.json

El DeliveryClient ahora está disponible para todos los componentes. Para obtener contenido, usa el DeliveryClient y el encadenamiento de métodos para definir los elementos que deseas. Este ejemplo muestra una obtención básica de publicaciones de blog y renderiza sus títulos en una lista:

src/pages/index.astro
---
import { deliveryClient } from "../lib/kontent";
const blogPosts = await deliveryClient
.items()
.type("blogPost")
.toPromise()
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<ul>
{blogPosts.data.items.map(blogPost => (
<li>{blogPost.elements.title.value}</li>
))}
</ul>
</body>
</html>

Puedes encontrar más opciones de consulta en la documentación de Kontent.ai.

Con la configuración anterior, ahora puedes crear un blog que use Kontent.ai como fuente de contenido.

  1. Proyecto de Kontent.ai - Para este tutorial, se recomienda utilizar un proyecto en blanco. Si ya tienes algunos tipos de contenido en tu modelo de contenido, puedes usarlos, pero necesitarás modificar los fragmentos de código para que coincidan con tu modelo de contenido.

  2. Proyecto de Astro configurado para la obtención de contenido desde Kontent.ai - ver arriba para obtener más detalles sobre cómo configurar un proyecto de Astro con Kontent.ai

En Kontent.ai, navega a Content model y crea un nuevo tipo de contenido con los siguientes campos y valores:

  • Nombre: Publicación de blog
  • Elements:
    • Text field
      • Nombre: Título
      • Elemento requerido:
    • Rich text field
      • Nombre: Teaser
      • Elemento requerido:
      • Permitido en este elemento: solo marcar Texto
    • Rich text field
      • Nombre: Contenido
      • Elemento requerido:
    • Date & time field
      • Nombre: Fecha
    • URL slug field
      • Nombre: Slug de URL
      • Elemento requerido:
      • Generación automática desde: selecciona “Título”

Luego, haz clic en Save Changes.

Ahora, navega a la pestaña Content & assets y crea un nuevo elemento de contenido de tipo Blog Post. Rellena los campos usando estos valores:

  • Nombre del elemento de contenido: Astro
  • Título: Astro es increíble
  • Teaser: Astro es un framework todo en uno para construir sitios web rápidos más rápidamente.
  • Contenido: Puedes usar JavaScript para implementar la funcionalidad del sitio web, pero no es necesario ningún bundle del cliente.
  • Fecha y hora: selecciona hoy
  • Slug de URL: astro-is-amazing

Cuando hayas terminado, publica la publicación del blog usando el botón Publish en la parte superior.

Nota: Siéntete libre de crear tantas publicaciones de blog como desees antes de pasar al siguiente paso.

Generación del modelo de contenido en TypeScript

Sección titulada “Generación del modelo de contenido en TypeScript”

A continuación, generarás tipos de TypeScript a partir de tu modelo de contenido.

Primero, instala el generador de modelos JS de Kontent.ai, ts-node y dotenv:

Ventana de la terminal
npm install @kontent-ai/model-generator ts-node dotenv

Luego, añade el siguiente script a package.json:

package.json
{
...
"scripts": {
...
"regenerate:models": "ts-node --esm ./generate-models.ts"
},
}

Debido a que los tipos requieren información estructural sobre tu proyecto que no está disponible en la API pública, también debes agregar una clave de API de Content Management al archivo .env. Puedes generar la clave en Environment settings -> API keys -> Management API.

.env
KONTENT_ENVIRONMENT_ID=YOUR_ENVIRONMENT_ID
KONTENT_PREVIEW_API_KEY=YOUR_PREVIEW_API_KEY
KONTENT_MANAGEMENT_API_KEY=YOUR_MANAGEMENT_API_KEY

Finalmente, añade el script generate-models.ts que configura el generador de modelos para generar los modelos:

generate-models.ts
import { generateModelsAsync, textHelper } from '@kontent-ai/model-generator'
import { rmSync, mkdirSync } from 'fs'
import * as dotenv from 'dotenv'
dotenv.config()
const runAsync = async () => {
rmSync('./src/models', { force: true, recursive: true })
mkdirSync('./src/models')
// change working directory to models
process.chdir('./src/models')
await generateModelsAsync({
sdkType: 'delivery',
apiKey: process.env.KONTENT_MANAGEMENT_API_KEY ?? '',
environmentId: process.env.KONTENT_ENVIRONMENT_ID ?? '',
addTimestamp: false,
isEnterpriseSubscription: false,
})
}
// Self-invocation async function
;(async () => {
await runAsync()
})().catch(err => {
console.error(err)
throw err
})

Ahora, ejecútalo:

Ventana de la terminal
npm run regenerate:models

Ahora estás listo para obtener algo de contenido. Ve a la página de Astro donde deseas mostrar una lista de todas las publicaciones de blog, por ejemplo, la página de inicio index.astro en src/pages.

Obtén todas las publicaciones de blog en el frontmatter de la página de Astro:

src/pages/index.astro
---
import { deliveryClient } from '../lib/kontent';
import type { BlogPost } from '../models';
import { contentTypes } from '../models/project/contentTypes';
const blogPosts = await deliveryClient
.items<BlogPost>
.type(contentTypes.blog_post.codename)
.toPromise()
---

Si te saltaste la generación del modelo, también puedes usar un objeto no tipado y una cadena literal para definir el tipo:

const blogPosts = await deliveryClient
.items()
.type("blogPost")
.toPromise()

La llamada fetch devolverá un objeto response que contiene una lista de todas las publicaciones de blog en data.items. En la sección HTML de la página de Astro, puedes usar la función map() para listar las publicaciones de blog:

src/pages/index.astro
---
import { deliveryClient } from '../lib/kontent';
import type { BlogPost } from '../models';
import { contentTypes } from '../models/project/contentTypes';
const blogPosts = await deliveryClient
.items<BlogPost>
.type(contentTypes.blogPost.codename)
.toPromise()
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Astro</title>
</head>
<body>
<h1>Blog posts</h1>
<ul>
{blogPosts.data.items.map(blogPost => (
<li>
<a href={`/blog/${blogPost.elements.url_slug.value}/`} title={blogPost.elements.title.value}>
{blogPost.elements.title.value}
</a>
</li>
))}
</ul>
</body>
</html>

Generación de publicaciones de blog individuales

Sección titulada “Generación de publicaciones de blog individuales”

El último paso del tutorial es generar páginas detalladas de publicaciones de blog.

En esta sección, utilizarás el Modo Estático (SSG) con Astro.

Primero, crea un archivo [slug].astro en /src/pages/blog/ que debe exportar una función getStaticPaths que recopile todos los datos del CMS:

src/pages/blog/[slug].astro
---
import { deliveryClient } from '../../lib/kontent';
import type { BlogPost } from '../../models';
import { contentTypes } from '../../models/project/contentTypes';
export async function getStaticPaths() {
const blogPosts = await deliveryClient
.items<BlogPost>()
.type(contentTypes.blog_post.codename)
.toPromise()
---

Hasta ahora, la función obtiene todas las publicaciones de blog de Kontent.ai. El fragmento de código es exactamente el mismo que usaste en la página de inicio.

A continuación, la función debe exportar las rutas y los datos de cada publicación de blog. Nombraste el archivo [slug].astro, por lo que el parámetro que representa el slug de la URL se llama slug:

src/pages/blog/[slug].astro
---
import { deliveryClient } from '../../lib/kontent';
import type { BlogPost } from '../../models';
import { contentTypes } from '../../models/project/contentTypes';
export async function getStaticPaths() {
const blogPosts = await deliveryClient
.items<BlogPost>()
.type(contentTypes.blog_post.codename)
.toPromise()
return blogPosts.data.items.map(blogPost => ({
params: { slug: blogPost.elements.url_slug.value },
props: { blogPost }
}))
}
---

La última parte es proporcionar la plantilla HTML y mostrar cada publicación de blog:

src/pages/blog/[slug].astro
---
import { deliveryClient } from '../../lib/kontent';
import type { BlogPost } from '../../models';
import { contentTypes } from '../../models/project/contentTypes';
export async function getStaticPaths() {
const blogPosts = await deliveryClient
.items<BlogPost>()
.type(contentTypes.blog_post.codename)
.toPromise()
return blogPosts.data.items.map(blogPost => ({
params: { slug: blogPost.elements.url_slug.value },
props: { blogPost }
}))
}
const blogPost: BlogPost = Astro.props.blogPost
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{blogPost.elements.title.value}</title>
</head>
<body>
<article>
<h1>{blogPost.elements.title.value}</h1>
<Fragment set:html={blogPost.elements.teaser.value} />
<Fragment set:html={blogPost.elements.content.value} />
<time>{new Date(blogPost.elements.date.value ?? "")}</time>
</body>
</html>

Navega a tu previsualización de Astro (por defecto, http://localhost:4321/blog/astro-is-amazing/) para ver la publicación de blog renderizada.

Si tus rutas se renderizan bajo demanda, utilizarás rutas dinámicas para obtener los datos de la página desde Kontent.ai.

Crea un nuevo archivo [slug].astro en /src/pages/blog/ y añade el siguiente código. La obtención de datos es muy similar a los casos de uso anteriores, pero añade un equalsFilter que nos permite encontrar la publicación de blog correcta basada en la URL utilizada:

src/pages/blog/[slug].astro
---
import { deliveryClient } from '../../lib/kontent';
import type { BlogPost } from '../../models';
import { contentTypes } from '../../models/project/contentTypes';
const { slug } = Astro.params
let blogPost: BlogPost;
try {
const data = await deliveryClient
.items<BlogPost>()
.equalsFilter(contentTypes.blog_post.elements.url_slug.codename, slug ?? '')
.type(contentTypes.blog_post.codename)
.limitParameter(1)
.toPromise()
blogPost = data.data.items[0]
} catch (error) {
return Astro.redirect('/404')
}
---

Si no estás usando tipos generados, puedes usar cadenas literales en su lugar para definir el tipo de elemento de contenido y el nombre en código del elemento filtrado:

const data = await deliveryClient
.items()
.equalsFilter("url_slug", slug ?? '')
.type("blog_post")
.limitParameter(1)
.toPromise()

Por último, añade el código HTML para renderizar la publicación de blog. Esta parte es la misma que con la generación estática:

src/pages/blog/[slug].astro
---
import { deliveryClient } from '../../lib/kontent';
import type { BlogPost } from '../../models';
import { contentTypes } from '../../models/project/contentTypes';
const { slug } = Astro.params
let blogPost: BlogPost;
try {
const data = await deliveryClient
.items<BlogPost>()
.equalsFilter(contentTypes.blog_post.elements.url_slug.codename, slug ?? '')
.type(contentTypes.blog_post.codename)
.limitParameter(1)
.toPromise()
blogPost = data.data.items[0]
} catch (error) {
return Astro.redirect('/404')
}
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{blogPost.elements.title.value}</title>
</head>
<body>
<article>
<h1>{blogPost.elements.title.value}</h1>
<Fragment set:html={blogPost.elements.teaser.value} />
<Fragment set:html={blogPost.elements.content.value} />
<time>{new Date(blogPost.elements.date.value ?? '')}</time>
</body>
</html>

Para desplegar tu sitio web, visita las guías de despliegue y sigue las instrucciones para tu proveedor de alojamiento preferido.

Si tu proyecto está utilizando el modo estático predeterminado de Astro, necesitarás configurar un webhook para activar una nueva compilación cuando cambie tu contenido. Si estás utilizando Netlify o Vercel como tu proveedor de alojamiento, puedes utilizar su función de webhook para activar una nueva compilación a partir de eventos de Kontent.ai.

Para configurar un webhook en Netlify:

  1. Ve al panel de control de tu sitio y haz clic en Build & deploy.

  2. En la pestaña Continuous Deployment, busca la sección Build hooks y haz clic en Add build hook.

  3. Proporciona un nombre para tu webhook y selecciona la rama en la que deseas activar la compilación. Haz clic en Save y copia la URL generada.

Para configurar un webhook en Vercel:

  1. Ve al panel de control de tu proyecto y haz clic en Settings.

  2. En la pestaña Git, busca la sección Deploy Hooks.

  3. Proporciona un nombre para tu webhook y la rama en la que deseas activar la compilación. Haz clic en Add y copia la URL generada.

En la aplicación de Kontent.ai, ve a Environment settings -> Webhooks. Haz clic en Create new webhook y proporciona un nombre para tu nuevo webhook. Pega la URL que copiaste de Netlify o Vercel y selecciona qué eventos deben activar el webhook. Por defecto, para reconstruir tu sitio cuando cambie el contenido publicado, solo necesitas los eventos Publish y Unpublish bajo Delivery API triggers. Cuando hayas terminado, haz clic en Save.

Ahora, cada vez que publiques una nueva publicación de blog en Kontent.ai, se activará una nueva compilación y tu blog se actualizará.

Más guías de CMS

Socios de CMS destacados

  • CloudCannon

    CMS basado en Git creado para mayor velocidad, seguridad y cero dolores de cabeza.

Todas las guías de CMS

Contribuir Comunidad Patrocinar