Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: making livepreview stable and removing useStoryblok function #1050

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
136 changes: 66 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ npm install @storyblok/astro
```

> [!NOTE]
> With pnpm, hoist Storyblok dependencies publicly with `.npmrc`. For more information, check pnpm documentation on [here](https://pnpm.io/npmrc).
> With pnpm, hoist Storyblok dependencies publicly with `.npmrc`. For more information, please refer to the [pnpm documentation](https://pnpm.io/npmrc).

Add the following code to `astro.config.mjs` and replace the `accessToken` with the preview API token of your Storyblok space.

```js
import { defineConfig } from "astro/config";
import storyblok from "@storyblok/astro";
import { storyblok } from "@storyblok/astro";

export default defineConfig({
integrations: [
Expand All @@ -75,6 +75,7 @@ When you initialize the integration, you can pass all [_@storyblok/js_ options](
storyblok({
accessToken: "<your-access-token>",
bridge: true,
livePreview: false,
apiOptions: {}, // storyblok-js-client options
components: {},
componentsDir: "src",
Expand Down Expand Up @@ -109,15 +110,15 @@ storyblok({
```

> [!WARNING]
> For spaces created in the United States or China, the `region` parameter **must** be specified.
> The `region` parameter **must** be specified unless the space was created in the EU.

## Getting started

### 1. Creating and linking your components to the Storyblok Visual Editor

In order to link your Astro components to their equivalents you created in Storyblok:
Link your Astro components to their equivalents created in Storyblok with the following steps.

First, you need to load them globally by specifying their name and their path in `astro.config.mjs`:
First, load the components globally by specifying their name and their path in `astro.config.mjs`:

```js
components: {
Expand Down Expand Up @@ -163,7 +164,7 @@ const { blok } = Astro.props
</div>
```

Finally, you can use the provided `<StoryblokComponent>` for nested components; it will automatically render them (if they have been registered globally beforehand):
Finally, you can use the provided `<StoryblokComponent>` for nested components; it will automatically render them (if they are registered globally):

```jsx
---
Expand All @@ -174,7 +175,7 @@ const { blok } = Astro.props
---

<main {...storyblokEditable(blok)}>
{blok.body?.map(blok => {return <StoryblokComponent blok="{blok}" />})}
{blok.body?.map(blok => {return <StoryblokComponent blok={blok} />})}
</main>
```

Expand Down Expand Up @@ -214,11 +215,11 @@ const { data } = await storyblokApi.get("cdn/stories/home", {
const story = data.story;
---

<StoryblokComponent blok="{story.content}" />
<StoryblokComponent blok={story.content} />
```

> [!NOTE]
> The available methods are described in the [storyblok-js-client] repository(https://github.com/storyblok/storyblok-js-client#method-storyblokget)
> The available methods are described in the [storyblok-js-client](https://github.com/storyblok/storyblok-js-client#method-storyblokget) repository.

#### Dynamic Routing

Expand Down Expand Up @@ -256,16 +257,13 @@ const { data } = await storyblokApi.get(`cdn/stories/${slug}`, {
const story = data.story;
---

<StoryblokComponent blok="{story.content}" />
<StoryblokComponent blok={story.content} />
```

### Using the Storyblok Bridge

The Storyblok Bridge is enabled by default. If you would like to disable it or enable it conditionally (e.g. depending on the environment) you can set the `bridge` parameter to `true` or `false` in `astro.config.mjs`:

> [!NOTE]
> Since Astro is not a reactive JavaScript framework and renders everything as HTML, the Storyblok Bridge will not provide real-time editing as you may know it from other frameworks. However, it automatically refreshes the site for you whenever you save or publish a story.

You can also provide a `StoryblokBridgeConfigV2` configuration object to the `bridge` parameter.

```ts
Expand All @@ -283,13 +281,65 @@ bridge: {
- `resolveLinks` may be needed to resolve link fields.

> [!NOTE]
> `resolveRelations` and `resolveLinks` will not have any effect in Astro, since the Storyblok Bridge is configured to reload the page. Thus, all the requests needed will be performed after the reload.
> `resolveRelations` and `resolveLinks` will only become effective if the live preview feature is used (`getLiveStory()`).

The provided options will be used when initializing the Storyblok Bridge. You can find more information about the Storyblok Bridge and its configuration options on the [In Depth Storyblok Bridge guide](https://www.storyblok.com/docs/guide/in-depth/storyblok-latest-js-v2?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-astro).

If you want to deploy a dedicated preview environment with the Bridge enabled, allowing users of the Storyblok CMS to see their changes being reflected on the frontend directly without having to rebuild the static site, you can enable Server Side Rendering for that particular use case. More information can be found in the [Astro Docs](https://docs.astro.build/en/guides/server-side-rendering/).

### Rendering Rich Text
## Enabling Live Preview for Storyblok's Visual Editor

The Astro SDK provides a live preview feature, designed to offer real-time editing capabilities for an enhanced user experience in Storyblok's Visual Editor.

> [!NOTE]
> To utilize the Astro Storyblok Live feature, Astro must be configured to run in SSR mode.

To activate the live preview feature, follow these steps:

1. Set `livePreview` to `true` in your `astro.config.mjs` file.

```js
//astro.config.mjs
export default defineConfig({
integrations: [
storyblok({
accessToken: "OsvN..",
livePreview: true,
}),
],
output: "server", // Astro must be configured to run in SSR mode
});
```

2. Additionally, use `getLiveStory` on your Astro pages.

```jsx
//pages/[...slug].astro
---
import { getLiveStory, useStoryblokApi } from '@storyblok/astro';
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";

const { slug } = Astro.params;
let story = null;

const liveStory = await getLiveStory(Astro);
if (liveStory) {
story = liveStory;
} else {
const sbApi = useStoryblokApi();
const { data } = await sbApi.get(`cdn/stories/${slug || 'home'}`, {
version: 'draft',
resolve_relations: ['featured-articles.posts'],
});
story = data?.story;
}
// If you are using `resolve_relations` or `resolve_links`, you must also pass them to the Bridge configuration in `astro.config.mjs`.
---

<StoryblokComponent blok={story.content} />
```

## Rendering Rich Text

> [!NOTE]
> While @storyblok/astro provides basic richtext rendering capabilities, for advanced use cases, it is highly recommended to use [storyblok-rich-text-astro-renderer](https://github.com/NordSecurity/storyblok-rich-text-astro-renderer).
Expand All @@ -306,7 +356,7 @@ const { blok } = Astro.props
const renderedRichText = renderRichText(blok.text)
---

<div set:html="{renderedRichText}"></div>
<div set:html={renderedRichText}></div>
```

You can also set a **custom Schema and component resolver** by passing the options as the second parameter of the `renderRichText` function:
Expand Down Expand Up @@ -348,60 +398,6 @@ const renderedRichText = renderRichText(blok.text, {

Returns the instance of the `storyblok-js-client`.

## Enabling Live Preview for Storyblok's Visual Editor

> [!WARNING]
> This feature is currently experimental and optional. You may encounters bugs or performance issues.

The Astro SDK now provides a live preview feature, designed to offer real-time editing capabilities for an enhanced user experience in Storyblok's Visual Editor.

> [!NOTE]
> To utilize the Astro Storyblok Live feature, Astro must be configured to run in SSR mode.

To activate the experimental live preview feature, follow these steps:

1. Set `livePreview` to `true` within your `astro.config.mjs` file.

```js
//astro.config.mjs
export default defineConfig({
integrations: [
storyblok({
accessToken: "OsvN..",
livePreview: true,
}),
],
output: "server", // Astro must be configured to run in SSR mode
});
```

2. Additionally, please use `useStoryblok` on your Astro pages for story fetching. This replaces the previously used `useStoryblokApi` method.

```jsx
//pages/[...slug].astro
---
import { useStoryblok } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";

const { slug } = Astro.params;

const story = await useStoryblok(
// The slug to fetch
`cdn/stories/${slug === undefined ? "home" : slug}`,
// The API options
{
version: "draft",
},
// The Bridge options (optional, if an empty object, null, or false are set, the API options will be considered automatically as far as applicable)
{},
// The Astro object (essential for the live preview functionality)
Astro
);
---

<StoryblokComponent blok={story.content} />
```

## The Storyblok JavaScript SDK Ecosystem

![A visual representation of the Storyblok JavaScript SDK Ecosystem](https://a.storyblok.com/f/88751/2400x1350/be4a4a4180/sdk-ecosystem.png/m/1200x0)
Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@storyblok/astro",
"type": "module",
"version": "1.0.0",
"version": "6.0.0",
"private": false,
"packageManager": "[email protected]",
"description": "Official Astro integration for the Storyblok Headless CMS",
Expand Down Expand Up @@ -71,9 +71,8 @@
"astro": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"dependencies": {
"@storyblok/js": "3.1.9",
"camelcase": "^8.0.0",
"lodash.mergewith": "^4.6.2"
"@storyblok/js": "^3.1.9",
"camelcase": "^8.0.0"
},
"devDependencies": {
"@commitlint/cli": "^19.5.0",
Expand Down
2 changes: 1 addition & 1 deletion playground/ssg/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'astro/config';
import svelte from '@astrojs/svelte';
import vue from '@astrojs/vue';
import react from '@astrojs/react';
import storyblok from '@storyblok/astro';
import { storyblok } from '@storyblok/astro';
import tailwind from '@astrojs/tailwind';
import mkcert from 'vite-plugin-mkcert';

Expand Down
6 changes: 4 additions & 2 deletions playground/ssr/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig } from 'astro/config';
import storyblok from '@storyblok/astro';
import { storyblok } from '@storyblok/astro';
import tailwind from '@astrojs/tailwind';
import mkcert from 'vite-plugin-mkcert';
import vercel from '@astrojs/vercel/serverless';
Expand All @@ -22,7 +22,9 @@ export default defineConfig({
},
},
useCustomApi: false,
bridge: true,
bridge: {
resolveRelations: ['featured-articles.posts'],
},
enableFallbackComponent: true,
livePreview: true,
components: {
Expand Down
31 changes: 19 additions & 12 deletions playground/ssr/src/pages/[...slug].astro
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
---
import { useStoryblok } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
import BaseLayout from "../layouts/BaseLayout.astro";
import {
getLiveStory,
useStoryblokApi,
type ISbStoryData,
} from '@storyblok/astro';
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro';
import BaseLayout from '../layouts/BaseLayout.astro';

const { slug } = Astro.params;
let story: ISbStoryData | null = null;

const story = await useStoryblok(
`cdn/stories/${slug === undefined ? "home" : slug}`,
{
version: "draft",
resolve_relations: ["featured-articles.posts"],
},
{},
Astro
);
const liveStory = await getLiveStory(Astro);
if (liveStory) {
story = liveStory;
} else {
const sbApi = useStoryblokApi();
const { data } = await sbApi.get(`cdn/stories/${slug || 'home'}`, {
version: 'draft',
resolve_relations: ['featured-articles.posts'],
});
story = data?.story;
}
---

<BaseLayout>
Expand Down
2 changes: 1 addition & 1 deletion playground/test/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'astro/config';
import svelte from '@astrojs/svelte';
import vue from '@astrojs/vue';
import react from '@astrojs/react';
import storyblok from '@storyblok/astro';
import { storyblok } from '@storyblok/astro';
import tailwind from '@astrojs/tailwind';

export default defineConfig({
Expand Down
5 changes: 1 addition & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading