Skip to content

Latest commit

 

History

History
2323 lines (1833 loc) · 61.6 KB

jekyll.adoc

File metadata and controls

2323 lines (1833 loc) · 61.6 KB

Jekyll Bookshop Reference Guide

Concepts

🌟
Migrating from Bookshop 2.0 to 3.0? Read the Migration Guide first.

Bookshop defines conventions for writing static components for Jekyll. Using these conventions, Bookshop provides an ergonomic way to build pages out of your components, build and browse these components locally, and generate rich live editing experiences in CloudCannon.

For an example of what this looks like in a real-world example, see our Editing MegaKit with Bookshop video.

Prerequisites

  • Bookshop requires Node >= 16 installed on your machine.

  • This guide expects that you already have Ruby and Jekyll installed on your machine.

Starting Point

💡
Short on time? You can use our Jekyll Bookshop Starter Template and jump straight into editing it in CloudCannon. Come back here when you want to build it out further, or create your own from scratch.

This guide will walk you through getting Bookshop connected to an existing Jekyll site. If you don’t have a site already, running jekyll new mysite is a good start. Alternatively, grab one of CloudCannon’s preconfigured Jekyll templates.

Creating your Bookshop

The first step is to create the directory structure for your Bookshop. To create this structure, you can run the following command in the root of your repository:

npx @bookshop/init --new component-library --framework jekyll

This command should provide you with the following directory structure:

component-library/
├─ bookshop/
│  └─ bookshop.config.cjs
├─ components/
│  └─ sample/
│     ├─ sample.bookshop.yml
│     ├─ sample.scss
│     └─ sample.jekyll.html
└─ shared/
   ├─ jekyll
   │  └─ page.jekyll.html
   └─ styles/
      └─ global.scss

Here’s a quick run-through of what has been generated:

bookshop/bookshop.config.cjs

This houses the configuration for your Bookshop project, in this case instructing Bookshop to use the @bookshop/jekyll-engine package for any live component rendering.

components/

This is where you will write your component files, a sample component has been added for you.

shared/jekyll/

Any non-component files that you want to be able to use when live editing can be placed here. A page helper has been created, which helps render arrays of components.

shared/styles/

Any SCSS files in this directory will be imported alphabetically before component SCSS files. These are used on both the site, and the component browser.


Creating these files yourself?

Bookshop File Reference
component-library/bookshop/bookshop.config.cjs
module.exports = {
    engines: {
        "@bookshop/jekyll-engine": {}
    }
}

We’ll cover creating components and shared files in Authoring New Components.

Connecting Your Bookshop to Jekyll

To use Bookshop with Jekyll, the primary dependency is the jekyll-bookshop gem.

Gemfile
group :jekyll_plugins do
  gem "jekyll-bookshop", "3.12.0"
end

After adding this to your Gemfile and running bundle install, specify the path to your Bookshop project in your Jekyll configuration:

_config.yml
plugins:
  - jekyll-bookshop

bookshop_locations:
  - component-library
💡
Make sure that bookshop_locations points to the component library you just created, relative to your Jekyll source.
💡
If you specify multiple paths, the component libraries will be merged.
💡
Paths that don’t exist will be skipped. If you specify local and production paths, the one that exists will be used.

With that configuration in place, running bundle exec jekyll serve should should succeed. Nothing will appear different yet, but we now have access to use components.

Lastly, we’ll need to install a few npm packages for Bookshop. These aren’t used as part of your production build, but they provide the developer tooling that enables structured data and live editing.

These packages should be installed at the root of the repository that contains your site. If this folder doesn’t have a package.json file yet, run npm init -y to create one.

To get setup, run the following command to install the needed Bookshop packages:

# npm
npm i --save-exact @bookshop/generate @bookshop/browser @bookshop/jekyll-engine

# or yarn
yarn add --exact @bookshop/generate @bookshop/browser @bookshop/jekyll-engine
🌟
Bookshop uses a fixed versioning scheme, where all packages are released for every version. It is recommended that you keep the npm packages and your plugins at the same version. To help with this, you can run npx @bookshop/up@latest from your repository root to update all Bookshop packages in sync.

Using Components in Jekyll

If you ran the @bookshop/init command earlier, you should see that you now have a file at components/sample/sample.jekyll.html. Let’s have a go using that component somewhere on our site.

💡
Bookshop supports multiple SSG targets, which is why we denote this as .jekyll.html.
💡
We’ll cover creating these components soon — if you want to add a new component now, you can run npx @bookshop/init --component <name> in your Bookshop directory to scaffold it out automatically.

Bookshop provides the bookshop tag to include components, which functions the same as using a normal Jekyll include.

To start, add the following snippet to one of your layouts:

index.html
...

{% bookshop sample text="Hello from the sample component" %}

...

If you now load your Jekyll site in a browser, you should see the sample component rendered on the page. There won’t be any styles yet, we’ll cover that soon. First though, there are a few neater ways you can use the bookshop tag:

Alternate syntax

Passing a set of parameters to a component can be cumbersome, and these will often point to front matter objects. Consider the following example:

index.html
---
component:
  hero_text: "Hello World"
  image: /image.png
---
{% bookshop hero hero_text=page.component.hero_text image=page.component.image %}

Having to pass through hero_text and image individually isn’t very maintainable, so instead you can use:

index.html
---
component:
  hero_text: "Hello World"
  image: /image.png
---
{% bookshop hero bind=page.component %}

The bind parameter is provided by Bookshop. This works like the spread operator in Javascript, by passing all the keys of the object to the component as props.

💡
If you’re used to a framework like Svelte, this is the equivalent of <Component {…​props} />

Bookshop tags also support interpolating liquid, so if you have your component name in a variable you can use:

index.html
---
component:
  _bookshop_name: hero
  hero_text: "Hello World"
  image: /image.png
---
{% bookshop {{page.component._bookshop_name}} bind=page.component %}
💡
The Bookshop name of a component is the path to its directory.
So the name for components/sample/sample.jekyll.html is sample,
and the name for components/generic/button/button.jekyll.html would be generic/button.
💡
The structures generated by Bookshop for CloudCannon include a _bookshop_name field for you, which can be used to render components dynamically. We’ll cover this a bit later on in Connecting Bookshop to CloudCannon.

Using Shared Bookshop Helpers in Jekyll

Shared Bookshop helpers can be placed in the shared/jekyll directory. i.e:

component-library/
├─ components/
└─ shared/
  └─ jekyll/
    └─ helper.jekyll.html

This can then be included using the bookshop_include tag:

{% bookshop_include helper lorem="ipsum" %}

The format is the same as the bookshop tag. This is otherwise a standard Jekyll include, with the extra feature that it can be used anywhere within your Jekyll site or your components.

ℹ️
While developing locally, components will have access to the rest of your site. This isn’t true when live editing, which is why these helper files exist.

You will notice that @bookshop/init created a page.jekyll.html file for you. Given the following front matter:

content_blocks:
  - _bookshop_name: hero
    hero_text: Hello World
    image: /image.png
  - _bookshop_name: cta
    heading: Join our newsletter
    location: /signup

You can render the array of components using the page helper like so:

{% bookshop_include page content_blocks=page.content_blocks %}

This will loop through the given array, and render each component according to its _bookshop_name key.

Give this a try now — replace the sample component you added with the page helper, and add the following to your front matter:

content_blocks:
  - _bookshop_name: sample
    text: A sample example
  - _bookshop_name: sample
    text: A second sample example
🌟
It is essential to render arrays of components using the page helper. Live editing only works within Bookshop components and helpers, so using this method means that rearranging and adding new components will work in the Visual Editor.

Importing Bookshop Styles

Bookshop provides some helpers for including the component and global styles that you defined in your component library.

ℹ️
Locating styles inside your Bookshop is optional — you can always define them with the rest of your site — but authoring your styles in your component library will provide a better experience when we cover using the local component browser.

@bookshop/init created a sample.scss file for you at components/sample/sample.scss. This file will currently be empty, but you should add a style here to test that the Bookshop SCSS integration is working for you. Something like:

.c-sample {
  background-color: blanchedalmond;
}

To import styles in Jekyll, Bookshop provides the tag {% bookshop_scss %} to be used in your main SCSS file. For example:

assets/main.scss
---
# Front matter dashes for Jekyll to process the file
---

{% bookshop_scss %} // Import all bookshop styles

This bundles all Bookshop SCSS files into the Jekyll Sass pipeline.

🌟
Bookshop SCSS files are loaded in order of all shared files, followed by all component files, alphabetically.

Authoring New Components

💡
To create new components, you can simply run npx @bookshop/init --component <name> in an existing Bookshop

Components live within the components/ directory, each inside a folder bearing their name. A component is defined with a <name>.bookshop.<format> file. This file serves as the schema for the component, defining which properties it may be supplied.

Components may also be nested within folders, which are then referenced as part of the component name. For example, the following structure would define the components hero, button/large and button/small:

components/
├─ hero/
|  |  hero.bookshop.yml
|  └─ hero.jekyll.html
└─ button/
   ├─ large/
   |  |  large.bookshop.yml
   │  └─ large.jekyll.html
   └─ small/
      |  small.bookshop.yml
      └─ small.jekyll.html

Authoring Component Template Files

Beyond the naming convention, Bookshop template files are what you would expect when working with Jekyll. A basic button component might look like the following:

components/button/button.jekyll.html
<a class="c-button" href="{{ include.link_url }}">{{ include.link_text }}</a>

Components can, of course, reference other components:

components/hero/hero.jekyll.html
<h1>{{ include.hero_text }}</h1>
{% bookshop button link_url=include.link_url link_text="Click me" %}

Authoring Component Styles

A <component>.scss file can be written alongside your other component files. Beyond the location and the automatic import, there is nothing special about the contents of this file.

Authoring Component Bookshop Files

The Bookshop file for each component is the most important piece of the Bookshop ecosystem. This file drives the Structured Data in CloudCannon, the local component browser, and Bookshop’s live editing.
The sample.bookshop.yml file that our init command generated contains the following:

sample.bookshop.yml
# Metadata about this component, to be used in the CMS
spec:
  structures:
    - content_blocks
  label: Sample
  description:
  icon:
  tags:

# Defines the structure of this component, as well as the default values
blueprint:
  text: "Hello World!"

# Overrides any fields in the blueprint when viewing this component in the component browser
preview:

# Any extra CloudCannon inputs configuration to apply to the blueprint
_inputs: {}

Let’s walk through an example file section by section to understand what’s going on.

Component Spec

spec:
  structures:
    - content_blocks
  label: Example
  description: An example Bookshop component
  icon: book
  tags:
    - example

This section is used when creating the Structure for your component. The structures array defines which structure keys to register this component with. In other words, with the above snippet, this component will be one of the options within an array named content_blocks, or another input configured to use _structures.content_blocks.

The other keys are used when the component is displayed in CloudCannon or in the Bookshop Component Browser. icon should be the name of a suitable material icon to use as the thumbnail for your component.

Component Blueprint

blueprint:
  text: Hello World!

The blueprint is the primary section defining your component. This will be used as the intitial state for your component when it is added to a page, and should thus include all properties used in your template.

Component Preview

preview:
  text: Vestibulum id ligula porta felis euismod semper.

Your blueprint represents the initial state of your component, but in the component browser you might want to see a preview of your component filled out with example data.

The preview object will be merged with your blueprint before a component is rendered in the component browser. This is a deep merge, so given the following specification:

blueprint:
  hero_text: "Hello World"
  cta:
    button_text: ""
    button_url: "#"

preview:
  cta:
    button_text: "Click me"

Your component preview data will be:

hero_text: "Hello World"
cta:
  button_text: "Click me"
  button_url: "#"
ℹ️
In a future Bookshop release, component thumbnails will be automatically generated. This will also use the preview object.

Inputs Configuration

_inputs:
  text:
    type: "html"
    comment: "This comment will appear in the CMS"

The _inputs section of your Bookshop file can be used to configure the keys in your blueprint. This object is passed through unaltered to CloudCannon, so see the CloudCannon Inputs Documentation to read more.

This configuration is scoped to the individual component, so you can configure the same key differently across components — even if the components are nested within one another.

Blueprint Arrays

Arrays of objects in your blueprint will be transformed into CloudCannon Structures automatically, and initialized as empty arrays. Using the following Blueprint:

blueprint:
  text: Sample Text
  items:
    - item_content: Hello World

A new component added to the page will take the form:

text: Sample Text
items: []

Editors will then be able to add and remove objects to the items array.

Nesting Components

Your blueprint can reference other components and structures to create rich page builder experiences:

blueprint:
  hero_text: Hello World
  button: bookshop:button

In this example, the button key will become an Object Structure containing the values specified in your button component blueprint. If you desired an array of buttons, you could use the following:

blueprint:
  hero_text: Hello World
  buttons: [bookshop:button]  # equivalent
  buttons:
    - bookshop:button         # equivalent

If you’re creating a layout component, you likely want to support a set of components. For this, you can reference the keys we defined in spec.structures as such:

blueprint:
  section_label: My Section

  # Make header a single component that can be selected from the content_blocks set
  header: bookshop:structure:content_blocks

  # Make inner_components an array that can contain components marked content_blocks
  inner_components: [bookshop:structure:content_blocks]

To give a concrete example, say we have the following hero.bookshop.yml file:

spec:
  structures: [content_blocks]

blueprint:
  hero_text: Hello World
  cta_button: bookshop:button
  column_components: [bookshop:structure:content_blocks]

Then our hero.jekyll.html file to render this might look like the following:

<div class="hero">
  <h1>{{ include.hero_text }}</h1>
  {% if include.cta_button %}
    {% bookshop button bind=include.cta_button %}
  {% endif %}
  {% for component in include.column_components %}
    {% bookshop {{ component._bookshop_name }} bind=component %}
  {% endfor %}
</div>
🌟
Object Structures in CloudCannon may be empty, so testing for the existence of this component in your template is recommended.

Initializing Nested Components

By default, nested components using the bookshop: shorthand will be initialized empty. For example, the blueprint:

blueprint:
  hero_text: Hello World
  button: bookshop:button

Will be initialized in CloudCannon as:

hero_text: Hello World
button:

Where button will provide an editor with the option to add a button component. To instead have the button component exist on creation, you can use the syntax bookshop:button!:

blueprint:
  hero_text: Hello World
  button: bookshop:button!

The same setting can be applied to a structure shorthand by specifying the component that should be initialized. Taking the following example:

blueprint:
  hero_text: Hello World
  column_components:
    - bookshop:structure:content_blocks!(hero)
    - bookshop:structure:content_blocks!(button)

This will be initialized in CloudCannon as:

hero_text: Hello World
column_components:
  - _bookshop_name: hero
    # hero fields
  - _bookshop_name: button
    # button fields

Where column_components can be then further added to/removed from by an editor, as per the tagged structure.

Supported File Formats

💡
When you run npx @bookshop/init --component <name> you will be prompted to pick which configuration format you want to create the component with.

In the examples above, we have been writing the Bookshop configuration files using YAML. This is the recommended format, but you can also choose another if you prefer. Here is a real-world example of a component written in each supported format:

hero.bookshop.yml
# Metadata about this component, to be used in the CMS
spec:
  structures:
    - content_blocks
    - page_sections
  label: Hero
  description: A large hero component suitable for opening a landing page
  icon: crop_landscape
  tags:
    - Above the Fold
    - Multimedia

# Defines the structure of this component, as well as the default values
blueprint:
  hero_text: ""
  hero_level: h1
  hero_image: ""
  hero_image_alt: ""
  subcomponents: [bookshop:structure:content_blocks]

# Overrides any fields in the blueprint when viewing this component in the component browser
preview:
  hero_text: Bookshop Makes Component Driven Development Easy
  hero_image: https://placekitten.com/600/400

# Any extra CloudCannon inputs configuration to apply to the blueprint
_inputs:
  hero_level:
    type: select
    options:
      values:
        - h1
        - h2
        - h3
        - h4
hero.bookshop.toml
# Metadata about this component, to be used in the CMS
[spec]
structures = [ "content_blocks", "page_sections" ]
label = "Hero"
description = "A large hero component suitable for opening a landing page"
icon = "crop_landscape"
tags = [ "Above the Fold", "Multimedia" ]

# Defines the structure of this component, as well as the default values
[blueprint]
hero_text = ""
hero_level = "h1"
hero_image = ""
hero_image_alt = ""
subcomponents = [ "bookshop:structure:content_blocks" ]

# Overrides any fields in the blueprint when viewing this component in the component browser
[preview]
hero_text = "Bookshop Makes Component Driven Development Easy"
hero_image = "https://placekitten.com/600/400"

# Any extra CloudCannon inputs configuration to apply to the blueprint
[_inputs]
hero_level.type = "select"
hero_level.options.values = [ "h1", "h2", "h3", "h4" ]
hero.bookshop.js
module.exports = () => {
  const spec = {
    structures: [
      "content_blocks",
      "page_sections",
    ],
    label: "Hero",
    description: "A large hero component suitable for opening a landing page",
    icon: "crop_landscape",
    tags: [
      "Above the Fold",
      "Multimedia",
    ]
  };

  const blueprint = {
    hero_text: "",
    hero_level: "h1",
    hero_image: "",
    hero_image_alt: "",
    subcomponents: [ "bookshop:structure:content_blocks" ],
  };

  const preview = {
    hero_text: "Bookshop Makes Component Driven Development Easy",
    hero_image: "https://placekitten.com/600/400",
  };

  const _inputs = {
    hero_level: {
      type: "select",
      options: {
        values: [
          "h1",
          "h2",
          "h3",
          "h4",
        ]
      }
    }
  };

  return {
    spec,
    blueprint,
    preview,
    _inputs,
  }
}
hero.bookshop.json
{
  "spec": {
    "structures": [
      "content_blocks",
      "page_sections"
    ],
    "label": "Hero",
    "description": "A large hero component suitable for opening a landing page",
    "icon": "crop_landscape",
    "tags": [
      "Above the Fold",
      "Multimedia"
    ]
  },
  "blueprint": {
    "hero_text": "",
    "hero_level": "h1",
    "hero_image": "",
    "hero_image_alt": "",
    "subcomponents": [ "bookshop:structure:content_blocks" ]
  },
  "preview": {
    "hero_text": "Bookshop Makes Component Driven Development Easy",
    "hero_image": "https://placekitten.com/600/400"
  },
  "_inputs": {
    "hero_level": {
      "type": "select",
      "options": {
        "values": [
          "h1",
          "h2",
          "h3",
          "h4"
        ]
      }
    }
  }
}
💡
Can’t decide? You can always run npx @bookshop/up --format <format> to automatically convert all of your files if you change your mind.

Providing Custom Component Thumbnails

When an editor is selecting a component in CloudCannon, the icon from the component spec will be used as the thumbnail. You can provide a custom image to use instead by placing a <component>.preview.<format> in your component directory. To provide a custom icon, which will be shown when viewing an array of components, you can also provide a <component>.icon.<format> file.

components/
└─ hero/
   |  hero.bookshop.yml
   ├─ hero.preview.png
   ├─ hero.icon.svg
   └─ hero.jekyll.html

See the CloudCannon Structures Reference for extra keys that you can set in your component spec to control the display of these images.

Using the Bookshop Component Browser

The Bookshop component browser allows you to browse and experiment with your components. When running in development the component browser also provides hot reloading of component templating and styles. An example browser showing the components in our Eleventy starter template can be seen here: https://winged-cat.cloudvent.net/components/

In your local development environment, run:
npx @bookshop/browser

By default, this will discover any Bookshop directories in or under the current working directory, and will host a component library on port 30775.

After running this command, a component browser will be viewable on http://localhost:30775

💡
Run npx @bookshop/browser --help to see the available options.

Integrating the Component Browser With Your Site

Coming Soon — Bookshop Jekyll provides a helper for embedding the Bookshop browser in your website. This references the component browser started in the previous command, and embeds a live copy into your website.

This allows you to:

  • Rely on your site layouts and styles in your component

  • Host a component browser on a page of your built site

To install the component browser on a page of your site, use the bookshop_component_browser tag in that page’s layout.

components.html
{% bookshop_component_browser %}

If you’re running Jekyll locally, open another terminal and run npx @bookshop/browser in your Bookshop, or a parent directory. You should now be able to visit the page that you installed the component browser on, and see your components in a playground environment.

💡
If you’re running the browser command on a custom port, you can pass that port as an argument with {% bookshop_component_browser 1234 %}

Hosting a Component Library

Any page that contains the bookshop_component_browser snippet will get picked up by npx @bookshop/generate (See Connecting Bookshop to CloudCannon) and turned into a hosted component browser, no extra configuration is needed.

Connecting Bookshop to CloudCannon

ℹ️
This guide assumes that your site is already set up with CloudCannon. If this isn’t the case, hop over to the CloudCannon Documentation and get setup with a successful build first.

Now that you understand how everything works locally, we can integrate Bookshop with CloudCannon. Bookshop does most of the heavy lifting for you, so we’ll get to see the benefits pretty quickly.
The main thing you need to do is create a postbuild script that runs Bookshop’s generate script. This should be placed inside a folder named .cloudcannon at the root of your repository.

.cloudcannon/postbuild
npm i
npx @bookshop/generate

This command will automatically discover your component library as well as the output site from your build, and will then generate CloudCannon Structures for your components. This step will also connect live editing to any pages on your site that contain Bookshop components.

With that in place, live editing should work in CloudCannon. If you have the following front matter on a page:

---
content_blocks:
---

And the page helper listed above in your layout, then in the CloudCannon sidebar you should be able to add our sample component and see it render live on the page.

💡
If something isn’t working, browse through our Jekyll Bookshop Starter Template to see how everything is configured.

Data Bindings

Once you have components rendered on the page, Bookshop will create Visual Data Bindings automatically.

If a component is passed data from the page front matter, you will be able to interact with that component directly on the page.

By default, Bookshop will add bindings for any components on the page, but will not add bindings for shared helper files. This prevents Bookshop rendering data bindings around our shared page helper, so that the components within are immediately accessible.

This behavior can be customised by including a flag in the component’s data. Bookshop will look for any of the following keys:

  • data_binding

  • dataBinding

  • _data_binding

  • _dataBinding

For example:

<!-- This component will **not** get a binding -->
{% bookshop item data_binding=false props=props %}

<!-- This include **will** get a binding -->
{% bookshop_include page data_binding=true props=props %}
ℹ️
This flag only applies to the component directly and doesn’t cascade down. Any subcomponents will follow the standard rules, or can also specify their own Data Binding flag.

Live Editing Site Data and Collections

The npx @bookshop/generate command connects Bookshop to a subset of your site’s data when live editing.

Accessing site.data should then work as expected inside a component in the visual editor.

Accessing site.<collection> should also work out of the box. All front matter from a collection should be accessible, but some collection fields such as page.content and page.excerpt will not be available when live editing.

🌟
For data to be accessible, you will need to set data_config: true in your CloudCannon Global Configuration file.
ℹ️
Support is only provided for data files in your source. Any data provided by a plugin will not be available.

Passing Data to Bookshop Components

In order to live edit Bookshop components, Bookshop needs a clear path between a component and the data it draws from. In general, you should avoid adding logic around your Bookshop components in your site layouts, and instead move that logic into a Bookshop component or helper.

An example:

index.html
---
hero_text: "Hello World"
---
<!--
  This component can make the connection between "text" and the front matter,
  and will work as expected in the visual editor.
-->
{% bookshop hero text=page.hero_text %}

{% assign my_title = hero_text %}

<!--
  This component doesn't have the context to map text back to its origin,
  and will error in the visual editor.
  (Assignments _inside_ Bookshop components will work correctly)
-->
{% bookshop hero text=my_title %}

The same is true for site data and collections. Access these directly from inside your component, rather than passing them to the component from your layout.

Jekyll Live Editing Support

Bookshop’s Jekyll live editing is built on top of the liquidjs package. As such, not all Jekyll features are supported within Bookshop components. Generally, functions that interact with Jekyll or the site as a whole are unavailable. The following features have been re-implemented for live editing in Jekyll:

Bookshop Jekyll Support Matrix
Jekyll Feature Notes

Filters: slugify, jsonify, relative_url

Filter: markdownify

ℹ️ Uses a different markdown engine, so output isn’t guaranteed to match Jekyll 1:1

Accessing site.data and site.<collection>

ℹ️ Iterating through collections and data files should be possible when live editing Bookshop components.

Jekyll plugins

❌ — See Rendering Different Content When Live Editing

Rendering Different Content When Live Editing

You can render special content in the live editing environment by checking the Bookshop Live Editor flag. This can be useful to show extra information to your editors, or to use a feature that isn’t supported while live editing.

{% if env_bookshop_live %}
  <p>I am being edited live!</p>
  <h1>Fallback Title</h1>
{% else %}
  <p>Standard build output</p>
  <h1>{% my_plugin %}</h1>
{% endif %}

Disabling Live Editing

Some components won’t be compatible with live editing, in this case you can disable live editing with on a flag in the component’s data. This is intended for components such as navigation and footer blocks that aren’t connected to live editing. In most scenarios, you should use the templating flags in Rendering Different Content When Live Editing.

🌟
This setting will only apply if the component is rendered directly from a site layout. If this component is within another component, it will still update live (as the parent re-rendering will encapsulate it).

Bookshop will look for any of the following keys on a top-level component:

  • live_render

  • liveRender

  • _live_render

  • _liveRender

For example:

<!-- This component will re-render in the visual editor -->
{% bookshop navigation props=props %}

<!-- This component will **not** re-render in the visual editor -->
{% bookshop navigation live_render=false props=props %}

If you have a specific component that you never want to live edit, you can set _live_render in the component’s blueprint.

ℹ️
Since the blueprint only affects the creation of new components, you will need to add the _live_render flag to any existing component data in your front matter.