Description: This article will tell you how to set up your Astro-Storyblok projects so that your previews site deploys to a Netlify branch-deploy, while keeping your main production site in SSG mode. Bonus: Github action to keep preview branch in-sync with production.
Introduction
If you are using Storyblok as your headless CMS for a static site such as a blog, you might want to set up a workflow where editors can click 'save' in Storyblok, and then see their changes. This would mean setting up the visual editor to work in Storyblok, which as I explained in a previous article, requires your Astro project to be in SSR mode.
What if you want to take advantage of Astro's static website mode (SSG) for your production site, but you would still like previews to work in Storyblok? How can we do this if previews require the project to be in SSR mode?
If you are using Netlify for deployments, there is a way to create an Astro project that builds the site in SSG mode for production environments and SSR mode for a previews branch , then deploys each version to a different Netlify URL using the Netlify branch-deploy feature.
You can also set up a Github action to keep the preview branch always up-to-date with any changes deployed to your main (production) branch!
Here's a walkthrough for how to set this up.
1. Create a branch-deploy in Netlify so you can have a special branch just for previewing content when clicking the 'save' button in Storyblok
Resource: Netlify Branches and deploys
Create Previews Branch
In your project, create a branch off of main called previews
.
Go into your Netlify dashboard Deploys -> Deploy Settings -> Branches and deploy contexts.
- Click Edit Settings.
- Select 'Let me add individual branches'
- In the Additional branches input, add your branch that you created called
previews
.
Now you have a branch that you will use for your preview environment. You're going to set up your Astro project to build in SSR mode just on this preview branch.
By the way, in Netlify terminology, a branch that you create which corresponds to a deploy that isn't from the main production branch is called a branch-deploy
. There are different Netlify deploy-contexts
, and branch-deploy
is one of them (in addition to production
and deploy-previews
.
Create Environment Variables
You need to make sure that you have an environment variable that tells Netlify that this branch you created is the preview environment. Later, when you go into your Astro project, you'll set up the project to build differently based on these variables.
In Netlify, go to Deploys -> Deploy Settings -> Environment variables.
- Create an environment variable called
VITE_ENVIRONMENT
. - In the Branch deploys, create a variable with the value
preview
. (Of course you can name this variable differently if you prefer.)
Now Netlify can be told based on the VITE_ENVIRONMENT
variable to either build the branch in SSG mode for production, or build it in SSR mode for the previews branch.
2. In the Storyblok Visual Editor settings, add your Netlify preview branch URL to the Preview URLs
Log in to your Storyblok space. In the left side navigation menu, find settings. From there, navigate to Visual Editor.
This is where you will tell Storyblok to connect the Visual Editor to that special branch you created, the previews
branch-deploy.
In the section Preview URLs, there are inputs to add multiple preview domains. Add previews
where it asks for Name and the Netlify url for that deployed previews branch where it asks for Location.
You can look at the Netlify URL to know which deploy-context (i.e. which branch-deploy) the preview site is building from. Since you called your branch-deploy previews
in Netlify, you'll see something like https://previews--NETLIFY_URL
. If you were looking at a Netlify deploy-preview, it would look like https://deploy-preview-32--NETLIFY_URL
(where the number is the number of the deploy-preview).
3. Set up your astro.config.mjs
file so that it uses conditional logic to build your site in static
mode if its in production, server
mode in the preview environment
Now you'll head into your Astro project to add some necessary configuration. This is where the environment variable you set up in Netlify is going to come into play.
Set up .env
In Netlify, you created the environment variable VITE_ENVIRONMENT
with the deploy-context of Branch deploys being given the preview
value.
In your project, you'll need to create a .env
file to supply your project with that variable value so it can work in dev mode. In the .env
file, add VITE_ENVIRONMENT="preview"
.
Add configuration to astro.config.mjs
There are four properties in the config object given to defineConfig
that will need to be written as ternary conditionals. They are output
, accessToken
(in the Storyblok settings object), and bridge
(also in Storyblok settings), and adapter
.
For output
, you'll give a value that is dependent on whether the deploy-context is preview
or not. Here's how it would look:
output: import.meta.env.VITE_ENVIRONMENT === "preview" ? "server" : "static",
This will tell the project to build in server
mode (i.e. SSR) if it's deploying to the preview
branch. If it's not, it will build in static
mode (SSG).
The integrations
array in the configuration object contains a storyblok
method with a settings object passed in. You'll need to add ternaries for the accessToken
and bridge
like so:
storyblok({
accessToken:
import.meta.env.VITE_ENVIRONMENT === "preview"
? "HodE5R9wdAKERDFNiq7LGStl" : "UUtz6RYjUvOC0tMf1MteHQtz",
bridge: import.meta.env.VITE_ENVIRONMENT === "preview" ? true : false,
apiOptions: {
region: "us",
},
components: {
page: "storyblok/Page",
feature: "storyblok/Feature",
grid: "storyblok/Grid",
...
},
}),
This tells the Storyblok integration to use the Preview token if the site is deploying in SSR, and the Public token if the site is deploying in SSG. (These Storyblok access tokens are created in your Storyblok space in Settings > Access Tokens.)
In the article I previously referenced, which is where I show how to set up the Visual Editor, I discuss how to add the Netlify adapter. The Netlify adapter is needed for the SSR deploy-context. You can read that article for more information if you need it on setting up SSR. You will need to set up the Netlify adapter.
You can tell your project to use the Netlify adapter only in SSR mode:
adapter: import.meta.env.VITE_ENVIRONMENT === 'preview' ? netlify() : undefined,
Here's an example of how the astro.config.mjs
file might look. There might be differences depending on your project integrations, but this is a general example:
import { defineConfig } from "astro/config";
import storyblok from "@storyblok/astro";
import netlify from "@astrojs/netlify/functions";
import tailwind from "@astrojs/tailwind";
export default defineConfig({
output: import.meta.env.VITE_ENVIRONMENT === "preview" ? "server" : "static",
adapter: import.meta.env.VITE_ENVIRONMENT === 'preview' ? netlify() : undefined,
integrations: [
tailwind(),
storyblok({
accessToken:
import.meta.env.VITE_ENVIRONMENT === "preview" ? "HodE5R9wdAKERDFNiq7LGStl" : "UUtz6RYjUvOC0tMf1MteHQtz",
bridge: import.meta.env.VITE_ENVIRONMENT === "preview" ? true : false,
apiOptions: {
region: "us",
},
components: {
page: "storyblok/Page",
feature: "storyblok/Feature",
grid: "storyblok/Grid",
},
}),
],
});
4. Get page data from Storyblok using the public token in SSG mode, the preview token in SSR mode.
The Astro pages that pull in content data from Storyblok can pull in either draft
content or published
content. You need to tell your project to build the pages using draft
content when in the preview
deploy-context, and published
content when in production.
For every page in your Astro pages folder, you will do something like this when getting data from the Storyblok API:
const { data } = await sbApi.get("cdn/stories/home", {
version:
import.meta.env.VITE_ENVIRONMENT === "preview" ? "draft" : "published",
});
This will conditionally build the project using either draft
or published
content based on that environment variable value in Netlify.
Here is an example of a home page in an Astro project that does this:
---
import { useStoryblokApi } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";
import Layout from "../layouts/Layout.astro";
const sbApi = useStoryblokApi();
const { data } = await sbApi.get("cdn/stories/home", {
version:
import.meta.env.VITE_ENVIRONMENT === "preview" ? "draft" : "published",
});
const story = data.story;
---
<Layout>
<StoryblokComponent blok={story.content} />
</Layout>
For creating dynamic routes, you can use a conditional setup to tell your project to use Astro's getStaticPaths
method in SSR mode only. Checkout this Discord comment for an example by user Nikitos.
5. Create a Github action that automatically merges any changes made to main to the previews branch too
The last thing you might want to do is to set up a continuous integration so that your preview branch stays in-sync with the main branch. That way, when there is a deploy to production, you don't have to manually update the previews branch - it will happen automatically.
You can use a Github Action to do this. Here's what you need to do.
- Create a
.github
folder in your project at the root. Inside that folder, add aworkflows
folder. - Create a file called
auto-merge.yml
inside theworkflows
folder
- Add the following code to that file:
name: Merge main to previews
on:
pull_request:
branches: [main]
types: [closed]
jobs:
merge-main-to-previews:
if: github.event.pull_request.merged == true
timeout-minutes: 2
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set Git config
run: |
git config --local user.email "actions@github.com"
git config --local user.name "Github Actions"
- name: Merge main to previews
run: |
git fetch --unshallow
git checkout previews
git pull
git merge --no-ff main -m "Auto-merge main to previews"
git push
Now, anytime a pull request is merged to the main (production) branch, it will also merge those changes into the previews branch!
Top comments (1)
Awesome article I canβt wait to try this out!