Storyblok y Astro
Storyblok es un headless CMS basado en componentes que te permite gestionar tu contenido utilizando componentes reutilizables llamados Bloks.
Integración con Astro
Sección titulada Integración con AstroEn esta sección, utilizarás la integración de Storyblok para conectar Storyblok con Astro.
Prerrequisitos
Sección titulada PrerrequisitosPara comenzar, necesitarás lo siguiente:
-
Un proyecto de Astro - Si aún no tienes un proyecto de Astro, nuestra guía de instalación te ayudará a poner en marcha en poco tiempo.
-
Una cuenta y 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 obtener 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 credencialesPara agregar las credenciales de tu sitio a Astro, crea un archivo .env
en la raíz de tu proyecto con la siguiente variable:
STORYBLOK_TOKEN=TU_PREVIEW_TOKEN
Ahora, deberías poder usar esta variable de entorno en tu proyecto.
Tu directorio raíz debería incluir este nuevo archivo ahora:
Directorysrc/
- …
- .env
- astro.config.mjs
- package.json
Instalación de dependencias
Sección titulada Instalación de dependenciasPara conectar Astro con tu espacio de Storyblok, instala la integración oficial de Storyblok utilizando el siguiente comando según tu gestor de paquetes preferido:
npm install @storyblok/astro vite
pnpm add @storyblok/astro vite
yarn add @storyblok/astro vite
Configurando Storyblok
Sección titulada Configurando StoryblokModifica tu archivo de configuración de Astro para incluir la integración de Storyblok de la siguiente manera:
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: { // Añade tus componentes aquí }, apiOptions: { // Elige la región de tu espacio de Storyblok. region: 'us', // opcional, o 'eu' (por defecto) }, }) ],});
La integración de Storyblok requiere un objeto con las siguientes propiedades:
-
accessToken
- Esto 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
loadEnv
de Vite para cargarlas. -
components
- Un objeto que mapea los nombres de los componentes de Storyblok a las 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 conteniendo las opciones de la API de Storyblok.Por defecto, la región es
eu
. Si tu espacio de Storyblok fue creado en la región de US, necesitarás establecer la región comous
.
Conectando Bloks a los componentes de Astro
Sección titulada Conectando Bloks a los componentes de AstroPara conectar tus Bloks a Astro, crea una nueva carpeta llamada storyblok
dentro del 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 llamado 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 equivalente del componente de Astro 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:
Directorysrc/
Directorystoryblok/
- BlogPost.astro
- .env
- astro.config.mjs
- package.json
Finalmente, para conectar el Blok blogPost
al componente BlogPost
, agrega una nueva propiedad a tu objeto components
en el 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 del Blok en Storyblok para que se referencie correctamente. Si no coinciden, o estás intentando referenciar 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', }, }) ],});
Obteniendo Datos
Sección titulada Obteniendo DatosPara probar la configuración, en Storyblok crea 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 gancho useStoryblokApi
. Esto inicializará una nueva instancia del cliente utilizando la configuración de integración que has establecido.
Para renderizar tu contenido, pasa la propiedad content
del Story al componente StoryblokComponent
como una prop blok
. Este componente renderizará los Bloks que están definidos dentro de la propiedad content
property. En este caso, renderizará el componente BlogPost
.
Creando un blog con Astro y Storyblok
Sección titulada Creando un blog con Astro y StoryblokCon la configuración de integración establecida, ahora puedes crear un blog con Astro y Storyblok.
Prerrequisitos
Sección titulada Prerrequisitos-
Un espacio de Storyblok - Para este tutorial, recomendamos utilizar un espacio nuevo. Si ya tienes un espacio con bloques (Bloks), siéntete libre de utilizarlos, pero deberás modificar el código para que coincida con los nombres de los bloques y los tipos de contenido.
-
Un proyecto de Astro integrado con Storyblok - Consulta la sección de integración con Astro para obtener instrucciones sobre cómo configurar la integración.
Creando una biblioteca blok
Sección titulada Creando una biblioteca blokPara crear bloques, ve a la aplicación de Storyblok y haz clic en la pestaña de Block Library. Haz clic en el botón + New blok y crea los siguientes bloques:
-
blogPost
- Un tipo de contenido Blok con los siguientes campos:title
- Un campo de textodescription
- Un campo de textocontent
- Un campo de texto enriquecido
-
blogPostList
- Un Blok anidado vacío -
page
- Un tipo de contenido Blok con los siguientes campos:body
- Un Blok anidado
Creando contenido
Sección titulada Creando contenidoPara agregar nuevo contenido, ve a la sección de contenido haciendo clic en la pestaña de Content. Utilizando la biblioteca de Bloks que creaste en el paso anterior, crea las siguientes historias:
-
home
- Un story de tipo de contenido con el Blokpage
. Dentro del campobody
, agrega un BlokblogPostList
. -
blog/no-javascript
- Un story con el tipo de contenidoblogPost
dentro de la carpeta del blog.title: No JavaScriptdescription: A sample blog postcontent: Hi there! This blog post doesn't use JavaScript. -
blog/astro-is-amazing
- Un story con el tipo de contenidoblogPost
dentro de la carpeta del 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.
Conectando Bloks a componentes
Sección titulada Conectando Bloks a componentesPara conectar los Bloks recién creados a los 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 anidado que renderizará de forma recursiva todos los Bloks dentro de la propiedad body
del Blok page
. También agrega los atributos storyblokEditable
al elemento padre, 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 utilizar la función auxiliar 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 anidado que renderizará una lista de vistas previas de publicaciones de blog.
Utiliza el hook useStoryblokApi
para obtener todas los stories con el tipo de contenido blogPost
. Utiliza el parámetro de consulta version
para obtener las versiones en borrador de las historias cuando se encuentra en modo de desarrollo y las versiones publicadas al compilar para producción.
Astro.props
se utiliza para configurar el editor en Storyblok. Aquí también se pueden pasar propiedades adicionales a tu componente, 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', }, }) ],});
Generando páginas
Sección titulada Generando páginasPara crear una ruta para una página
especifica, puedes obtener su contenido directamente desde la API de Storyblok y pasarlo al componente StoryblokComponent
. Asegúrate de haber agregado el componente Page
a tu archivo astro.config.mjs.
Crea un archivo index.astro
dentro de 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>