The Netlify Visual Editor is a user-friendly tool for editing structured visual content. It’s compatible with various frameworks and Headless CMS, enabling real-time editing without requiring extensive technical knowledge. Learn how to use it with the Astro web framework.
#TL;DR
To explore Netlify Visual Editor’s capabilities, we will set up and customize a blog using an Astro template. Enabling visual editing allows content editors to work with structured content in a visual way.
Explore the example site and repo
Preview the deployed site and reference the repository for the code via the following links:
- Preview: https://example-astro-visual-editor.netlify.app/
- Repository: https://github.com/netlify/examples/
Also, you can follow the steps below to create this example from the beginning.
#Prerequisites
To follow along with all of the steps of this guide, you’ll need:
#Tech stack overview
- Astro as the site framework
- File-based content (Git CMS)
- Netlify Visual Editor
Netlify Visual Editor is compatible with various web frameworks, such as Next.js, Nuxt, and 11ty. We’re using Astro as an example.
#Steps required to add Visual Editor
These steps are required for optimal Visual Editor experience.
- Install Visual Editor development dependencies
- Create Visual Editor config (
stackbit.config.ts
) - Create content models to define the structure of the content
- Annotate project components for inline editing
#Getting started with Astro
For this guide, we will be using the Astro Starter Kit: Blog. This template includes several hardcoded pages, such as Home and About, as well as a collection of blog posts. Our goal is to make the blog posts editable using the Visual Editor. To get started with the Astro Starter Kit Blog, run the following command:
TypeScript
Strict
parameters. #Adjust the template
By default, Astro uses port 4321
for its development server, while Visual Editor operates on port 3000
. To change the port for Astro, add the following code to your astro.config.mjs
file:
As we are working with structured content (post collection), the hardcoded pages are unnecessary to include. Please delete the about.astro
and index.astro
in the pages directory. Move index.astro
from the blog directory to the pages directory, and adjust the components paths. This way, our project structure aligns with the example repository, and we only have pages that can be edited in the Visual Editor.
#Install Netlify Visual Editor CLI
Run the following command to install the Netlify Visual Editor CLI globally using npm:
#Installing required dependencies for Visual Editor
Once you have the template in your local environment, let’s install the necessary dependencies for the Netlify Visual Editor. The Astro Starter Kit Blog template uses markdown files to store blog post content (Git CMS). To enable the Visual Editor to work with file-based content, we need to install the following development dependencies:
#Create Visual Editor config
The next step is to add the Netlify Visual Editor config. Create a file at the root of your project named stackbit.config.ts
and add the following code:
#Netlify Visual Editor config explained
Let’s break down each section of the Visual Editor configuration.
#Imports
defineStackbitConfig
: this function is used to define the Netlify Visual Editor configuration. It ensures the configuration follows Visual Editor’s type structure.GitContentSource
: this import from@stackbit/cms-git
enables using a Git-based content source. This way, Netlify Visual Editor can read content directly from files in the project’s repository.
#Configuration details
stackbitVersion
: specifies the Visual Editor version.ssgName
: allows Visual Editor to recognize the web framework used in your project. We set it to “custom” since Astro currently isn’t natively supported as a standard SSG in Visual Editor.nodeVersion
: specifies theNode.js
version.devCommand
: this command (astro dev) runs the development server, which is essential for Visual Editor’s live preview feature.PORT
is dynamically replaced with the correct port Visual Editor uses.
#Experimental section
This section enables Visual Editor’s experimental support for Astro:
name
: specifies Astro as the SSG we are using.logPatterns
: helps Visual Editor to recognize when the server is ready by checking for specific log patterns in the console output, like “is ready” and “astro”.directRoutes
: configures Visual Editor to route socket.io traffic correctly.passthrough
: specifies paths (/vite-hmr/**
) to bypass Visual Editor’s routing and allow direct access, particularly for Hot Module Replacement (HMR) when using Vite.
#Content sources
GitContentSource
: defines a content source.rootPath
: sets the root path of the content to the current directory (__dirname).contentDirs
: specifies where the content is located.models
: the array of the content model definitions. This is currently empty, but we will update it later.assetsConfig
: configures asset handling:referenceType
: set to “static”, meaning images and other assets are stored statically.staticDir
: sets the directory for static content assrc/content
.uploadDir
: specifies _images as the directory where assets are uploaded.publicPath
: the public path to access static content, set to/src/content/
.
#Run Visual Editor locally
To start the Visual Editor locally, run the Astro development server by using the command npm run dev
. In a new terminal window, run the Visual Editor with the command stackbit dev
. This provides you with your own Netlify Visual Editor URL. To be directed to Netlify’s Visual Editor for your new project, open the URL and register or sign in.
#Creating post content model
The next step is to create a content model. The Astro blog kit has a content collection for blog posts, which means we need to create a content model specifically for posts. To ensure a post is editable in the Visual Editor, the post content must be represented as a structured data object sourced from a content source.
We define the post content model within the models
array in the Visual Editor’s configuration. For this, we create an object named post
with the type set to page
and specify the urlPath
and filePath
properties. urlPath
represents the blog post URL path, and filePath
indicates where new posts will be saved.
To ensure that the Visual Editor recognizes which content files correspond to the post model, we add type: post
to the front matter of all existing post files located in src/content/blog
.
Now, if you run the Visual Editor locally, you should see the posts appear in the top navigator and in the sidebar.
#Post fields property
Netlify Visual Editor Reference
In the Visual Editor reference documentation, you can find all properties available within a model definition.
The next step is to make the post front matter editable in the Visual Editor. To achieve this, we need to define the fields
property in our post model. Let’s start by reviewing the blog post collection schema definition:
Ensure that the fields defined in the schema are listed as objects in the fields
property of the post model. Let’s start with the post title.
The post title is a simple text field, so we set its type
to string
. The name
of the field should match the one defined in the collection schema, so we set it to title
. Since the post title is required, we include the required
property and set it to true
. To enhance the user experience, we can also provide an initial value by adding the default
property and setting it to “Post Title”:
Similarly, we define the remaining fields: description
, pubDate
, updatedDate
, and heroImage
:
After these edits, you should see all these fields on post page in the Visual Editor sidebar.
#Annotations
The Visual Editor allows users to make changes directly in the preview by clicking on editable content. To enable inline editing in a post, we need to add annotations to our project components: src/pages/index.astro
, src/pages/blog/[...slug].astro
, and src/layouts/BlogPost.astro
.
Annotations are the data-sb-*
data attributes that inform the Visual Editor how to link the content in the source with its corresponding location in the rendered page structure within the project preview. The two available data attributes are:
data-sb-object-id
: scopes all descendant elements within the context of the given ID value, so that any field path mentioned in HTML descendants is automatically attributed to the document with the specified ID.data-sb-field-path
: provides a path (absolute or relative) from the root of the document, identifying the field to be edited in the content source.
To start, let’s add annotations to the posts on the blog feed page located at src/pages/index.astro
.
#Annotating blog feed posts
We begin by adding the data-sb-object-id
attribute to the post wrapper element, which in this case is the <a>
tag. The value of the data-sb-object-id
attribute corresponds to the path of the post file, relative to the root of the project, and including the file extension. We construct it using the Astro entry id
, as follows: src/content/blog/${post.id}
Next, we add data-sb-field-path
attributes to the elements responsible for rendering the post’s heroImage
, title
, and pubDate
:
Now, let’s add annotations to a single blog post in pages/blog/[...slug].astro
.
#Annotating blog post
The blog post is rendered using the BlogPost
component, which only receives post front matter properties {...post.data}
. To construct the data-sb-object-id
attribute, we also need to pass the Astro entry id
:
Next, let’s modify the BlogPost
component located at src/layouts/BlogPost.astro
. First, we update the TypeScript Props
to include the id
property and extract the id
property from the received props
:
Afterward, we can add the data-sb-object-id
and data-sb-field-path
attributes, following the same approach as we did for the blog feed posts.
After these edits, you should be able to edit inline all annotated fields on post page in the Visual Editor.
#Apply this to your site!
To learn more about the Netlify Visual Editor, explore the documentation or the reference documentation. Try templates with Visual Editor, the Astro Sanity Starter, or the Next.js Content Ops Starter.