Saltar al contenido

Storyblok & Astro

Storyblok es un CMS headless basado en componentes que te permite gestionar tu contenido utilizando componentes reutilizables llamados Bloks.

En esta sección, utilizarás la integración de Storyblok para conectar Storyblok con Astro.

Para empezar, necesitarás lo siguiente:

  1. Un proyecto de Astro - Si aún no tienes un proyecto de Astro, nuestra guía de instalación te pondrá en marcha en poco tiempo.

  2. Una cuenta y un espacio de Storyblok - Si aún no tienes una cuenta, regístrate gratis y crea un nuevo espacio.

  3. Token de vista previa de Storyblok - Este token se utilizará para recuperar borradores y versiones publicadas de tu contenido. Puedes encontrar y generar tu token de API en la pestaña Access Tokens de la configuración de tu espacio de Storyblok.

Para agregar tus credenciales de Storyblok a Astro, crea un archivo .env en la raíz de tu proyecto con la siguiente variable:

.env
STORYBLOK_TOKEN=YOUR_PREVIEW_TOKEN

Ahora, deberías poder usar estas variables de entorno en tu proyecto.

Tu directorio raíz ahora debería incluir este nuevo archivo:

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

Para conectar Astro con tu espacio de Storyblok, instala la integración oficial de Storyblok usando el comando a continuación para tu gestor de paquetes preferido:

Ventana de la terminal
npm install @storyblok/astro vite

Modifica tu archivo de configuración de Astro para incluir la integración de Storyblok:

astro.config.mjs
import { defineConfig } from 'astro/config';
import { storyblok } from '@storyblok/astro';
import { loadEnv } from 'vite';
const env = loadEnv("", process.cwd(), 'STORYBLOK');
export default defineConfig({
integrations: [
storyblok({
accessToken: env.STORYBLOK_TOKEN,
components: {
// Add your components here
},
apiOptions: {
// Choose your Storyblok space region
region: 'us', // optional, or 'eu' (default)
},
})
],
});

La integración de Storyblok requiere un objeto con las siguientes propiedades:

  1. accessToken - Hace referencia al token de la API de Storyblok que agregaste en el paso anterior.

  2. components - Un objeto que asigna nombres de componentes de Storyblok a rutas de tus componentes locales. Esto es necesario para renderizar tus Bloks de Storyblok en Astro.

  3. apiOptions - Un objeto que contiene las opciones de la API de Storyblok.

Conexión de Bloks con componentes de Astro

Sección titulada "Conexión de Bloks con componentes de Astro"

Para conectar tus Bloks con Astro, crea una nueva carpeta llamada storyblok en el directorio src. Esta carpeta contendrá todos los componentes de Astro que coincidirán con tus Bloks en tu biblioteca de Bloks de Storyblok.

En este ejemplo, tienes un tipo de contenido de Blok blogPost en tu biblioteca de Storyblok con los siguientes campos:

  • title - Un campo de texto
  • description - Un campo de texto
  • content - Un campo de texto enriquecido

Nuestro objetivo es crear el componente de Astro equivalente que utilizará estos campos para renderizar su contenido. Para hacer esto, crea un nuevo archivo llamado BlogPost.astro dentro de src/storyblok con el siguiente contenido:

src/storyblok/BlogPost.astro
---
import { storyblokEditable, renderRichText } from '@storyblok/astro'
const { blok } = Astro.props
const content = renderRichText(blok.content)
---
<article {...storyblokEditable(blok)}>
<h1>{blok.title}</h1>
<p>{blok.description}</p>
<Fragment set:html={content} />
</article>

La propiedad blok contiene los datos que recibirás de Storyblok. También contiene los campos que se definieron en el Blok de tipo de contenido blogPost en Storyblok.

Para renderizar nuestro contenido, la integración proporciona funciones de utilidad como:

  • storyblokEditable - agrega los atributos necesarios a los elementos para que puedas editarlos en Storyblok.
  • renderRichText - transforma el campo de texto enriquecido en HTML.

Tu directorio raíz debería incluir este nuevo archivo:

  • Directoriosrc/
    • Directoriostoryblok/
      • BlogPost.astro
  • .env
  • astro.config.mjs
  • package.json

Finalmente, para conectar el Blok blogPost al componente BlogPost, agrega una nueva propiedad al objeto de componentes en tu archivo de configuración de Astro.

  • La clave es el nombre del Blok en Storyblok. En este caso, es blogPost.
  • El valor es la ruta al componente. En este caso, es storyblok/BlogPost.
astro.config.mjs
import { defineConfig } from 'astro/config';
import { storyblok } from '@storyblok/astro';
import { loadEnv } from 'vite';
const env = loadEnv("", process.cwd(), 'STORYBLOK');
export default defineConfig({
integrations: [
storyblok({
accessToken: env.STORYBLOK_TOKEN,
components: {
blogPost: 'storyblok/BlogPost',
},
apiOptions: {
region: 'us',
},
})
],
});

Para probar la configuración, crea en Storyblok una nueva historia con el tipo de contenido blogPost llamada test-post. En Astro, crea una nueva página en el directorio src/pages/ llamada test-post.astro con el siguiente contenido:

src/pages/test-post.astro
---
import { useStoryblokApi } from '@storyblok/astro'
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro'
const storyblokApi = useStoryblokApi()
const { data } = await storyblokApi.get("cdn/stories/test-post", {
version: import.meta.env.DEV ? "draft" : "published",
});
const content = data.story.content;
---
<StoryblokComponent blok={content} />

Para consultar tus datos, utiliza el hook useStoryblokApi. Esto inicializará una nueva instancia de cliente utilizando tu configuración de integración.

Para renderizar tu contenido, pasa la propiedad content de la historia al StoryblokComponent como una prop blok. Este componente renderizará los Bloks que se definen dentro de la propiedad content. En este caso, renderizará el componente BlogPost.

Creación de un blog con Astro y Storyblok

Sección titulada "Creación de un blog con Astro y Storyblok"

Con la integración configurada, ahora puedes crear un blog con Astro y Storyblok.

  1. Un espacio de Storyblok - Para este tutorial, recomendamos utilizar un espacio nuevo. Si ya tienes un espacio con Bloks, no dudes en utilizarlos, pero deberás modificar el código para que coincida con los nombres de los Bloks y los tipos de contenido.

  2. Un proyecto de Astro integrado con Storyblok - Consulta la integración con Astro para obtener instrucciones sobre cómo configurar la integración.

Para crear Bloks, ve a la aplicación de Storyblok y haz clic en la pestaña Block Library. Haz clic en el botón + New blok y crea los siguientes Bloks:

  1. blogPost - Un Blok de tipo de contenido con los siguientes campos:

    • title - Un campo de texto
    • description - Un campo de texto
    • content - Un campo de texto enriquecido
  2. blogPostList - Un Blok anidable vacío

  3. page - Un Blok de tipo de contenido con los siguientes campos:

    • body - Un Blok anidable

Para agregar contenido nuevo, ve a la sección de contenido haciendo clic en la pestaña Content. Utilizando la biblioteca de Bloks que creaste en el paso anterior, crea las siguientes historias:

  1. home - Una historia de tipo de contenido con el Blok page. Dentro del campo body, agrega un Blok blogPostList.

  2. blog/no-javascript - Una historia con el tipo de contenido blogPost dentro de la carpeta blog.

    title: No JavaScript
    description: A sample blog post
    content: Hi there! This blog post doesn't use JavaScript.
  3. blog/astro-is-amazing - Una historia con el tipo de contenido blogPost dentro de la carpeta blog.

    title: Astro is amazing
    description: We love Astro
    content: Hi there! This blog post was build with Astro.

Ahora que tienes tu contenido listo, regresa a tu proyecto de Astro y comienza a construir tu blog.

Para conectar tus Bloks recién creados con componentes de Astro, crea una nueva carpeta llamada storyblok en tu directorio src y agrega los siguientes archivos:

Page.astro es un componente de tipo de contenido de Blok anidable que renderizará recursivamente todos los Bloks dentro de la propiedad body del Blok page. También agrega los atributos storyblokEditable al elemento principal, lo que nos permitirá editar la página en Storyblok.

src/storyblok/Page.astro
---
import { storyblokEditable } from '@storyblok/astro'
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
const { blok } = Astro.props
---
<main {...storyblokEditable(blok)}>
{
blok.body?.map((blok) => {
return <StoryblokComponent blok={blok} />
})
}
</main>

BlogPost.astro renderizará las propiedades title, description y content del Blok blogPost.

Para transformar la propiedad content de un campo de texto enriquecido a HTML, puedes usar la función de utilidad renderRichText.

src/storyblok/BlogPost.astro
---
import { storyblokEditable, renderRichText } from '@storyblok/astro'
const { blok } = Astro.props
const content = renderRichText(blok.content)
---
<article {...storyblokEditable(blok)}>
<h1>{blok.title}</h1>
<p>{blok.description}</p>
<Fragment set:html={content} />
</article>

BlogPostList.astro es un componente de tipo de contenido de Blok anidable que renderizará una lista de vistas previas de publicaciones de blog.

Utiliza el hook useStoryblokApi para recuperar todas las historias con el tipo de contenido de blogPost. Utiliza el parámetro de consulta version para recuperar las versiones en borrador de las historias cuando está en modo de desarrollo y las versiones publicadas cuando se compila para producción.

Astro.props se utiliza para configurar el editor en Storyblok. También se pueden pasar props adicionales a tu componente aquí, si es necesario.

src/storyblok/BlogPostList.astro
---
import { storyblokEditable } from '@storyblok/astro'
import { useStoryblokApi } from '@storyblok/astro'
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get('cdn/stories', {
version: import.meta.env.DEV ? "draft" : "published",
content_type: 'blogPost',
})
const posts = data.stories.map(story => {
return {
title: story.content.title,
date: new Date(story.published_at).toLocaleDateString("en-US", {dateStyle: "full"}),
description: story.content.description,
slug: story.full_slug,
}
})
const { blok } = Astro.props
---
<ul {...storyblokEditable(blok)}>
{posts.map(post => (
<li>
<time>{post.date}</time>
<a href={post.slug}>{post.title}</a>
<p>{post.description}</p>
</li>
))}
</ul>

Finalmente, agrega tus componentes a la propiedad components del objeto de configuración storyblok en astro.config.mjs. La clave es el nombre del Blok en Storyblok, y el valor es la ruta al componente relativa a src.

astro.config.mjs
import { defineConfig } from 'astro/config';
import { storyblok } from '@storyblok/astro';
import { loadEnv } from 'vite';
const env = loadEnv("", process.cwd(), 'STORYBLOK');
export default defineConfig({
integrations: [
storyblok({
accessToken: env.STORYBLOK_TOKEN,
components: {
blogPost: 'storyblok/BlogPost',
blogPostList: 'storyblok/BlogPostList',
page: 'storyblok/Page',
},
apiOptions: {
region: 'us',
},
})
],
});

Para crear una ruta para una page específica, puedes recuperar su contenido directamente desde la API de Storyblok y pasarlo al componente StoryblokComponent. Recuerda asegurarte de haber agregado el componente Page a tu astro.config.mjs.

Crea un archivo index.astro en src/pages/ para renderizar la página home:

src/pages/index.astro
---
import { useStoryblokApi } from '@storyblok/astro'
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro'
import BaseLayout from '../layouts/BaseLayout.astro'
const storyblokApi = useStoryblokApi();
const { data } = await storyblokApi.get('cdn/stories/home', {
version: import.meta.env.DEV ? "draft" : "published",
});
const content = data.story.content;
---
<html lang="en">
<head>
<title>Storyblok & Astro</title>
</head>
<body>
<StoryblokComponent blok={content} />
</body>
</html>

Para generar páginas para todas tus publicaciones de blog, crea una página .astro que creará rutas dinámicas. Este enfoque varía dependiendo de si tus rutas son prerenderizadas (el valor predeterminado en Astro) o renderizadas bajo demanda.

Si estás utilizando la generación de sitios estáticos predeterminada de Astro, utilizarás rutas dinámicas y la función getStaticPaths para generar las páginas de tu proyecto.

Crea un nuevo directorio src/pages/blog/ y agrega un nuevo archivo llamado [...slug].astro con el siguiente código:

src/pages/blog/[...slug].astro
---
import { useStoryblokApi } from '@storyblok/astro'
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro'
export async function getStaticPaths() {
const sbApi = useStoryblokApi();
const { data } = await sbApi.get("cdn/stories", {
content_type: "blogPost",
version: import.meta.env.DEV ? "draft" : "published",
});
const stories = Object.values(data.stories);
return stories.map((story) => {
return {
params: { slug: story.slug },
};
});
}
const sbApi = useStoryblokApi();
const { slug } = Astro.params;
const { data } = await sbApi.get(`cdn/stories/blog/${slug}`, {
version: import.meta.env.DEV ? "draft" : "published",
});
const story = data.story;
---
<html lang="en">
<head>
<title>Storyblok & Astro</title>
</head>
<body>
<StoryblokComponent blok={story.content} />
</body>
</html>

Este archivo generará una página para cada historia, con el slug y el contenido recuperados desde la API de Storyblok.

Si estás renderizando tus rutas bajo demanda con un adaptador, utilizarás rutas dinámicas para recuperar los datos de la página desde Storyblok.

Crea un nuevo directorio src/pages/blog/ y agrega un nuevo archivo llamado [...slug].astro con el siguiente código:

src/pages/blog/[...slug].astro
---
import { useStoryblokApi } from '@storyblok/astro'
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro'
const storyblokApi = useStoryblokApi()
const slug = Astro.params.slug;
let content;
try {
const { data } = await storyblokApi.get(`cdn/stories/blog/${slug}`, {
version: import.meta.env.DEV ? "draft" : "published",
});
content = data.story.content
} catch (error) {
return Astro.redirect('/404')
}
---
<html lang="en">
<head>
<title>Storyblok & Astro</title>
</head>
<body>
<StoryblokComponent blok={content} />
</body>
</html>

Este archivo recuperará y renderizará los datos de la página desde Storyblok que coincidan con el parámetro dinámico slug.

Dado que estás utilizando una redirección a /404, crea una página 404 en src/pages:

src/pages/404.astro
<html lang="en">
<head>
<title>Not found</title>
</head>
<body>
<p>Sorry, this page does not exist.</p>
</body>
</html>

Si no se encuentra la historia, la solicitud se redirigirá a la página 404.

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

Reconstruir al realizar cambios en Storyblok

Sección titulada "Reconstruir al realizar cambios en Storyblok"

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

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 configuración (Settings) de tu espacio de Storyblok, haz clic en la pestaña Webhooks. Pega la URL del webhook que copiaste en el campo Story published & unpublished y presiona Save para crear un webhook.

Ahora, cada vez que publiques una nueva historia, 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