Recent searches

in

Visually edit components

Learn how to define Component Editable Regions to enable component live re-rendering in the Visual Editor.

On this page

Component Editable Regions are available for Astro, Eleventy, and Hugo, and for sites built with React, Vue, or Svelte, including Next.js, Nuxt, and SvelteKit. The code examples in this step of the guide use Astro.

Component Editable Regions are not yet available for other SSGs. To request support for your SSG, please get in touch with our friendly support team and include the name and version of the SSG you use.

Many static websites use reusable code components (a.k.a., partials) ranging from a small snippet of HTML, to UI elements like a header, profile card, or an entire page layout.

You can use Component Editable Regions to re-render changes to your components in the Visual Editor. They are also required to edit Text or Image Editable Regions nested inside a component. Let's cover how to define one.

Nested text or image values

To avoid data-prop misconfiguration errors, it is best practice to define your Editable Regions from the root of your file first (i.e., from parent elements to child elements). If you want to edit text or image values in a component using the Visual Editor, you should define your Component Editable Region on the parent element before Text and Image Editable Regions.

Install the integration for your SSG#

Unlike other types of Editable Region, Component Editable Regions need an integration, because CloudCannon re-renders your components in the browser rather than on a build server. Astro and Eleventy install an NPM package, Hugo installs a Hugo module, and sites built with React, Vue, or Svelte add a root component to your layout. You only need to do this once per Site. The @cloudcannon/editable-regions NPM package requires Node 20.19 or later.

Astro

Install the NPM package, then add the Editable Regions integration to your Astro configuration file.

Bash
Copied to clipboard
npm install @cloudcannon/editable-regions
JavaScript
Copied to clipboard
import editableRegions from "@cloudcannon/editable-regions/astro-integration";
import { defineConfig } from "astro/config";

export default defineConfig({
  integrations: [editableRegions()],
});

Eleventy

Install the NPM package, then add the Editable Regions plugin to your Eleventy configuration file.

Bash
Copied to clipboard
npm install @cloudcannon/editable-regions
JavaScript
Copied to clipboard
import editableRegions from "@cloudcannon/editable-regions/eleventy";

export default function (eleventyConfig) {
  eleventyConfig.addPlugin(editableRegions);

  return {
    dir: { input: "src", includes: "_includes", output: "_site" },
  };
}

After every build, the plugin writes a register-components.js file into your output directory. Import it from your layout, inside the <body> element.

HTML
Copied to clipboard
<script>
  if (window.inEditorMode) {
    import("/register-components.js").catch((error) => {
      console.warn("Failed to load CloudCannon component registration:", error);
    });
  }
</script>

Hugo

Hugo uses a Hugo module rather than an NPM package. Install the module, add it to your Hugo configuration file, then include the Editable Regions partial in the <head> element of your base layout.

Bash
Copied to clipboard
hugo mod get github.com/CloudCannon/editable-regions@<version>
TOML
Copied to clipboard
[module]
  [[module.imports]]
    path = "github.com/CloudCannon/editable-regions"
    version = "<version>"
HTML
Copied to clipboard
{{ partial "editable-regions" . }}

JavaScript frameworks

Install the NPM package, then wrap your routed page content in the EditableRegions component, in your root layout.

Sites built with React, Vue, or Svelte, including Next.js, Nuxt, and SvelteKit, need the EditableRegions component for every type of Editable Region, not just Component Editable Regions.

Bash
Copied to clipboard
npm install @cloudcannon/editable-regions
JSX
Copied to clipboard
import { EditableRegions } from "@cloudcannon/editable-regions/react";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <EditableRegions tag="main">{children}</EditableRegions>
      </body>
    </html>
  );
}

Import EditableRegions from @cloudcannon/editable-regions/react, /vue, or /svelte, depending on your framework.

Your SSG may need more than this to build in the Visual Editor. For Astro framework renderers, Eleventy's includeWith tag, Hugo module vendoring and version requirements, Nuxt's custom element setting, and static export settings for Next.js, Nuxt, and SvelteKit, please read our documentation on configuring Component Editable Regions. You can also visit CloudCannon's GitHub repository for the Editable Regions NPM package.

Register your components#

Registering a component tells CloudCannon which component a data-component value refers to, and that it should be bundled for client-side use in the Visual Editor. Astro and the JavaScript frameworks need you to register each component by name. Eleventy and Hugo work out the name from your include and partial names, so they have no registration step.

Astro

Create a registration file for your components, then import it from your layout, inside the <body> element.

If you use .astro component files, even if you have React components nested in them, import { registerAstroComponent } in your registration script. Here's an example for the CTA component.

JavaScript
Copied to clipboard
import { registerAstroComponent } from '@cloudcannon/editable-regions/astro';
import '@cloudcannon/editable-regions/astro-react-renderer'; 
import CTA from '../components/CTA.astro';

// Register your components
registerAstroComponent('cta', CTA);

This import is only necessary if you use React components nested inside your Astro components. For Svelte or Vue components, import @cloudcannon/editable-regions/astro-svelte-renderer or @cloudcannon/editable-regions/astro-vue-renderer instead.

If you use .tsx or .jsx component files, import { registerReactComponent } instead.

JavaScript
Copied to clipboard
import { registerReactComponent } from '@cloudcannon/editable-regions/react';
import MyComponent from './MyComponent.jsx';

registerReactComponent('my_component', MyComponent);

Eleventy

There is no registration step. CloudCannon resolves component names the same way your templates resolve includes, so {% include "cta" %} matches data-component="cta".

The plugin you added in the previous step copies your includes into the registration script it writes after every build.

Hugo

There is no registration step. CloudCannon resolves component names as partial names, so data-component="cta" and data-component="cta.html" both render layouts/partials/cta.html.

JavaScript frameworks

Register your components from a file that only runs in the browser, such as a client component in Next.js or a client plugin in Nuxt.

TypeScript
Copied to clipboard
import { registerVueComponent } from "@cloudcannon/editable-regions/vue";
import CTA from "../components/CTA.vue";

export default defineNuxtPlugin(() => {
  if (window.inEditorMode) {
    registerVueComponent('cta', CTA);
  }
});

Import registerReactComponent from @cloudcannon/editable-regions/react or registerSvelteComponent from @cloudcannon/editable-regions/svelte for those frameworks.

Components in layout files#

Components use templating to reference structured data keys. Layout files then reference a component file. At build time, CloudCannon populates the component with the correct values and outputs it to the layout's HTML webpage.

Let's take a look at an example.

This file is a blog post, containing the cta object in the front matter, and the structured data keys description, link, buttonText, and buttonColor.

Markdown
Copied to clipboard
---
title: 'First post'
author: 'C. Kent'
heroImage: '../../assets/blog-banner.jpg'
heroImageTitle: 'Blog gradient'
heroImageAlt: 'An eye-catching color gradient banner.'
cta:
  description: "Need a little more help? Send a message to our friendly support team."
  link: "https://cloudcannon.com/support/"
  buttonText: "Send a message"
  buttonColor: "#034AD8"
---

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra.

Here is an excerpt from our blog layout file, containing a call-to-action component called CTA at the bottom of every blog post.

ASTRO
Copied to clipboard
---
import CTA from '../components/CTA.astro';
---

<html lang="en">
	<body>
		<main>
			<article>
                <!-- Blog HTML here -->
			</article>
			<CTA {...Astro.props.cta} /> 
		</main>
	</body>
</html>

The <CTA> component uses structured data in the front matter of the files in the Blog Collection.

Finally, here's our component layout file, which contains HTML for the component and templating to populate elements with values from each blog file.

ASTRO
Copied to clipboard
---
const { description, link, buttonText, buttonColor } = Astro.props;
---

<p>{description}</p>
<a href={link}>
    <button style={`background-color: ${buttonColor}`}>{buttonText}</button>
</a>

Together, these files output a webpage that looks like this:

A screenshot of a blog page on our Astro website shows a call to action component under the blog content.

In this example, the <CTA> component uses the properties in the cta object in each blog post. We can add a Component Editable Region to our layout file to enable the Visual Editor to re-render any changes made with the Data Panel or sidebar.

First you need to import the component registration file you made earlier with a <script> HTML element. The <script> element should go inside the <body> element of your layout, which could be a different file depending on how your Site is structured (e.g., you may have a base layout file that all your other layouts reference). When you import the component registration file, you can also add instructions to check if your browser window is in Editor Mode (i.e., your webpage is open in CloudCannon's Visual Editor) and add an error warning.

Next, since the <CTA> component lacks an appropriate parent DOM element, you should wrap it in the <editable-component> web component. Our Component Editable Region also needs a data-prop to define where our component data is stored which, in this case, will be the cta front matter object in our blog post.

Finally, you need to add the data-component HTML attribute to define which registered component we are using which, in this case, is also called cta.

Here's what our blog layout code should look like:

ASTRO
Copied to clipboard
<html lang="en">
  <body>
    <script> 
      if (window.inEditorMode) {
        import("../scripts/register-components.js").catch((error) => {
          console.warn("Failed to load CloudCannon component registration:", error);
        });
      }
    </script>
    <main>
      <article>
        <!-- Blog HTML here -->
      </article>
      <editable-component data-prop="cta" data-component="cta"> 
        <CTA {...Astro.props.cta} />
      </editable-component>
    </main>
  </body>
</html>

The <script> element instructs your browser to import the register-components.js file if your webpage is open in the Visual Editor.

The editable-component web component defines a Component Editable Region. The data-prop attribute defines the path to the data we want to edit, and the data-component defines which registered component we are using. In this case, we want to edit the cta structured data key in the blog front matter and use the registered component cta.

If we were to save and rebuild our Site now, the Visual Editor would allow you to re-render the CTA component when you edit values using the Data Panel or sidebar, but would not allow inline editing for the text values description and buttonText. To achieve this, we also need to add Text Editable Regions to the CTA component file.

Here's what our CTA component code should look like:

ASTRO
Copied to clipboard
---
const { description, link, buttonText, buttonColor } = Astro.props;
---

<p data-editable="text" data-prop="description">{description}</p> 
<a href={link}>
    <button data-editable="text" data-prop="buttonText" style={`background-color: ${buttonColor}`}>{buttonText}</button> 
</a>

This <p> element contains data-editable="text" and data-prop="description" to define a Text Editable Region.

This <button> element contains data-editable="text" and data-prop="buttonText" to define a Text Editable Region.

Once we save and rebuild our Site, CloudCannon will show a yellow Editable Region box around all the content inside the <CTA> component in the Visual Editor. There are also two Text Editable Regions around the description and button text.

A screenshot of the Visual Editor shows a yellow Editable Region box around the Call to Action component on the blog page.

CloudCannon will show an edit icon in the top right of the Component Editable Region. Clicking the edit icon opens a Data Panel with inputs for all four structured data keys in the component: description, link, buttonText, and buttonColor. The edit icon only appears if your Component Editable Region has a data-prop or data-prop-* HTML attribute.

Common errors#

If you accidentally misconfigure your Editable Regions, CloudCannon will replace them in the Visual Editor with a red Error Card headed Failed to render component, or Failed to render component: [Component Name] if your component fails to render, followed by a message describing the problem.

A screenshot of an Error Card in the Visual Editor shows a message headed Failed to render component, followed by the reason the region could not render.

Here are a few common errors you might encounter with Component Editable Regions:

  • You did not define the data-component HTML attribute.
  • You reference a component that does not exist, or has not been registered.
  • Your component throws an error while rendering, or does not return HTML.

In the next step of this guide, we'll cover how to define Editable Regions for complex arrays.

Set up Visual Editing (9/11)
Visually edit components
Open in a new tab