Storyblok & Astro
Storyblok es un CMS headless basado en componentes que te permite gestionar tu contenido utilizando componentes reutilizables llamados Bloks.
Integración con Astro
Sección titulada "Integración con Astro"En esta sección, utilizarás la integración de Storyblok para conectar Storyblok con Astro.
Requisitos previos
Sección titulada “Requisitos previos”Para empezar, necesitarás lo siguiente:
-
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.
-
Una cuenta y un espacio de Storyblok - Si aún no tienes una cuenta, regístrate gratis y crea un nuevo espacio.
-
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.
Configuración de credenciales
Sección titulada "Configuración de credenciales"Para agregar tus credenciales de Storyblok a Astro, crea un archivo .env en la raíz de tu proyecto con la siguiente variable:
STORYBLOK_TOKEN=YOUR_PREVIEW_TOKENAhora, 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
Instalación de dependencias
Sección titulada "Instalación de dependencias"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:
npm install @storyblok/astro vitepnpm add @storyblok/astro viteyarn add @storyblok/astro viteConfiguración de Storyblok
Sección titulada "Configuración de Storyblok"Modifica tu archivo de configuración de Astro para incluir la integración de Storyblok:
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:
-
accessToken- Hace referencia al token de la API de Storyblok que agregaste en el paso anterior.Dado que el archivo de configuración de Astro normalmente no admite variables de entorno, utiliza la función
loadEnvde Vite para cargarlas. -
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.Las rutas de los componentes son relativas al directorio
src. Por ejemplo, si tu componente se encuentra ensrc/storyblok/MyComponent.astro, la ruta seríastoryblok/MyComponent(sin la extensión.astro). -
apiOptions- Un objeto que contiene las opciones de la API de Storyblok.Por defecto, la región es
eu. Si tu espacio de Storyblok se creó en la región de EE. UU. (US), deberás establecer la región enus.
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 textodescription- Un campo de textocontent- 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:
---import { storyblokEditable, renderRichText } from '@storyblok/astro'
const { blok } = Astro.propsconst 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.
La key debe coincidir exactamente con el nombre de tu Blok en Storyblok para que sea referenciada correctamente. Si estas no coinciden, o si intentas hacer referencia a un componente que no existe en Storyblok, obtendrás un error.
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', }, }) ],});Obtención de datos
Sección titulada "Obtención de datos"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:
---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.
Requisitos previos
Sección titulada “Requisitos previos”-
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.
-
Un proyecto de Astro integrado con Storyblok - Consulta la integración con Astro para obtener instrucciones sobre cómo configurar la integración.
Creación de una biblioteca de Bloks
Sección titulada "Creación de una biblioteca de Bloks"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:
-
blogPost- Un Blok de tipo de contenido con los siguientes campos:title- Un campo de textodescription- Un campo de textocontent- Un campo de texto enriquecido
-
blogPostList- Un Blok anidable vacío -
page- Un Blok de tipo de contenido con los siguientes campos:body- Un Blok anidable
Creación de contenido
Sección titulada "Creación de contenido"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:
-
home- Una historia de tipo de contenido con el Blokpage. Dentro del campobody, agrega un BlokblogPostList. -
blog/no-javascript- Una historia con el tipo de contenidoblogPostdentro de la carpeta blog.title: No JavaScriptdescription: A sample blog postcontent: Hi there! This blog post doesn't use JavaScript. -
blog/astro-is-amazing- Una historia con el tipo de contenidoblogPostdentro de la carpeta blog.title: Astro is amazingdescription: We love Astrocontent: 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.
Conexión de Bloks con componentes
Sección titulada "Conexión de Bloks con componentes"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.
---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.
---import { storyblokEditable, renderRichText } from '@storyblok/astro'const { blok } = Astro.propsconst 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.
---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.
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', }, }) ],});Generación de páginas
Sección titulada "Generación de páginas"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:
---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.
Generación de sitios estáticos
Sección titulada "Generación de sitios estáticos"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:
---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.
Al agregar carpetas dentro de Storyblok, inclúyelas en el slug al interactuar con la API de Storyblok. Por ejemplo, en la petición GET anterior podemos usar cdn/stories/blog, con una carpeta blog dentro, en lugar de usarlas en la raíz.
Renderizado bajo demanda
Sección titulada "Renderizado bajo demanda"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:
---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:
<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.
Publicando tu sitio
Sección titulada "Publicando tu sitio"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.
Netlify
Sección titulada "Netlify"Para configurar un webhook en Netlify:
-
Ve al panel de control de tu sitio y haz clic en Build & deploy.
-
En la pestaña Continuous Deployment, busca la sección Build hooks y haz clic en Add build hook.
-
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:
-
Ve al panel de control de tu proyecto y haz clic en Settings.
-
En la pestaña Git, busca la sección Deploy Hooks.
-
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.
Agregar un webhook a Storyblok
Sección titulada "Agregar un webhook a Storyblok"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á.
Recursos oficiales
Sección titulada "Recursos oficiales"- Integración de Storyblok con Astro para agregar Storyblok a tu proyecto.
- Guía de Storyblok para Astro
- Referencia del paquete Storyblok para Astro
Recursos de la comunidad
Sección titulada "Recursos de la comunidad"- Cómo hacer que el editor visual funcione para Storyblok + Astro por Sandra Rodgers
- Astro + Storyblok: vista previa de SSR para edición visual instantánea por Jonas Gierer
- Sitio de vistas previas de Astro-Storyblok con la función Branch Deploys de Netlify por Sandra Rodgers
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.