# ContentLink component for Visual Editing `` is a Svelte component that enables **Visual Editing** for your DatoCMS content. It provides click-to-edit overlays that allow editors to click on any content element on your website to instantly open the DatoCMS editor and modify that specific field. This component is built on top of the [`@datocms/content-link`](https://www.npmjs.com/package/@datocms/content-link) library and provides a seamless integration for Svelte and SvelteKit projects. ## What is Visual Editing? Visual Editing transforms how content editors interact with your website. Instead of navigating through forms and fields in a CMS, editors can: 1. **See their content in context** - Preview exactly how content appears on the live site 2. **Click to edit** - Click directly on any text, image, or field to open the editor 3. **Navigate seamlessly** - Jump between pages in the preview, and the CMS follows along 4. **Get instant feedback** - Changes in the CMS are reflected immediately in the preview This drastically improves the editing experience, especially for non-technical users who can now edit content without understanding the underlying CMS structure. ## Out-of-the-box features - **Click-to-edit overlays**: Visual indicators showing which content is editable - **Stega decoding**: Automatically detects and decodes editing metadata embedded in content - **Keyboard shortcuts**: Hold Alt/Option to temporarily enable editing mode - **Flash-all highlighting**: Show all editable areas at once for quick orientation - **Bidirectional navigation**: Sync navigation between preview and DatoCMS editor - **Framework-agnostic**: Works with SvelteKit or any routing solution - **StructuredText integration**: Special support for complex structured content fields - **[Web Previews plugin](https://www.datocms.com/marketplace/plugins/i/datocms-plugin-web-previews) integration**: Seamless integration with DatoCMS's editing interface - [Installation](#installation) - [Basic Setup](#basic-setup) - [1. Fetch content with stega encoding](#1-fetch-content-with-stega-encoding) - [2. Add ContentLink component to your app](#2-add-contentlink-component-to-your-app) - [SvelteKit integration](#sveltekit-integration) - [Enabling click-to-edit](#enabling-click-to-edit) - [Flash-all highlighting](#flash-all-highlighting) - [Props](#props) - [ClickToEditOptions](#clicktoeditoptions) - [Data attributes reference](#data-attributes-reference) - [Developer-specified attributes](#developer-specified-attributes) - [`data-datocms-content-link-url`](#data-datocms-content-link-url) - [`data-datocms-content-link-source`](#data-datocms-content-link-source) - [`data-datocms-content-link-group`](#data-datocms-content-link-group) - [`data-datocms-content-link-boundary`](#data-datocms-content-link-boundary) - [Library-managed attributes](#library-managed-attributes) - [`data-datocms-contains-stega`](#data-datocms-contains-stega) - [`data-datocms-auto-content-link-url`](#data-datocms-auto-content-link-url) - [How group and boundary resolution works](#how-group-and-boundary-resolution-works) - [Structured Text fields](#structured-text-fields) - [Rule 1: Always wrap the Structured Text component in a group](#rule-1-always-wrap-the-structured-text-component-in-a-group) - [Rule 2: Wrap embedded blocks, inline blocks, and inline records in a boundary](#rule-2-wrap-embedded-blocks-inline-blocks-and-inline-records-in-a-boundary) - [Low-level utilities](#low-level-utilities) - [`decodeStega`](#decodestega) - [`stripStega`](#stripstega) - [Troubleshooting](#troubleshooting) - [Click-to-edit overlays not appearing](#click-to-edit-overlays-not-appearing) - [Navigation not syncing with Web Previews plugin](#navigation-not-syncing-with-web-previews-plugin) - [StructuredText blocks not clickable](#structuredtext-blocks-not-clickable) - [Layout issues caused by stega encoding](#layout-issues-caused-by-stega-encoding) ## Installation ```bash npm install --save @datocms/svelte ``` The package includes `@datocms/content-link` as a dependency, which provides the underlying controller for Visual Editing functionality. ## Basic Setup Visual Editing requires two steps: ### 1. Fetch content with stega encoding When fetching content from DatoCMS, enable stega encoding to embed editing metadata: ```js import { executeQuery } from '@datocms/cda-client'; const query = ` query { page { title content } } `; const result = await executeQuery(query, { token: 'YOUR_API_TOKEN', environment: 'main', // Enable stega encoding contentLink: 'v1', // Set your site's base URL for editing links baseEditingUrl: 'https://your-project.admin.datocms.com', }); ``` The `contentLink: 'v1'` option enables stega encoding, which embeds invisible metadata into text fields. The `baseEditingUrl` tells DatoCMS where your project is located so edit URLs can be generated correctly. Both options are required. ### 2. Add ContentLink component to your app Add the `` component to your app. It doesn't render any visible output but sets up the click-to-edit functionality: ```svelte ``` That's it! The component will automatically detect editable content and create interactive overlays. ## SvelteKit integration For SvelteKit projects, you can integrate with the routing system to enable full Web Previews plugin support: ```svelte goto(path)} currentPath={$page.url.pathname} /> ``` This integration enables: - **Navigation from plugin**: When editors navigate to a different URL in the Visual Editing mode, your preview updates accordingly - **Current path sync**: The plugin knows which page is currently being previewed ## Enabling click-to-edit Click-to-edit overlays are **not enabled by default**. Instead, editors can: - **Hold Alt/Option key**: Temporarily enable click-to-edit mode while the key is held down - **Release the key**: Disable click-to-edit mode when released If you prefer to enable click-to-edit programmatically on mount, set the `enableClickToEdit` prop: ```svelte ``` Or with options: ```svelte ``` The `hoverOnly` option is useful to avoid showing overlays on touch devices where they may interfere with normal scrolling and tapping behavior. When set to `true` on a touch-only device, click-to-edit will not be automatically enabled, but users can still toggle it manually using the Alt/Option key. ## Flash-all highlighting The flash-all feature provides visual feedback by highlighting all editable elements on the page. This is useful for: - Showing editors what content they can edit - Debugging to verify Visual Editing is working correctly - Onboarding new content editors When you enable click-to-edit with the `scrollToNearestTarget` option, it triggers the flash-all effect: ```svelte ``` The `scrollToNearestTarget` parameter scrolls to the nearest editable element, useful on long pages. ## Props | Prop | Type | Default | Description | | ------------------- | ------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `onNavigateTo` | `(path: string) => void` | - | Callback when [Web Previews plugin](https://www.datocms.com/marketplace/plugins/i/datocms-plugin-web-previews) requests navigation to a different page | | `currentPath` | `string` | - | Current pathname to sync with [Web Previews plugin](https://www.datocms.com/marketplace/plugins/i/datocms-plugin-web-previews) | | `enableClickToEdit` | `boolean \| ClickToEditOptions` | - | Enable click-to-edit overlays on mount. Pass `true` or an object with options. If undefined or false, click-to-edit is disabled | | `stripStega` | `boolean` | - | Whether to strip stega encoding from text nodes after stamping | | `root` | `ParentNode` | - | Root element to limit scanning to instead of the entire document | ### ClickToEditOptions When passing an object to `enableClickToEdit`, the following options are available: | Option | Type | Default | Description | | ----------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scrollToNearestTarget` | `boolean` | `false` | Automatically scroll to the nearest editable element if none is currently visible in the viewport when click-to-edit mode is enabled. Also triggers the flash-all highlighting effect. | | `hoverOnly` | `boolean` | `false` | Only enable click-to-edit on devices that support hover (non-touch devices). Uses `window.matchMedia('(hover: hover)')` to detect hover capability. Useful to avoid overlays interfering with touch scrolling. | ## Data attributes reference This library uses several `data-datocms-*` attributes. Some are **developer-specified** (you add them to your markup), and some are **library-managed** (added automatically during DOM stamping). Here's a complete reference. ### Developer-specified attributes These attributes are added by you in your templates/components to control how editable regions behave. #### `data-datocms-content-link-url` Manually marks an element as editable with an explicit edit URL. Use this for non-text fields (booleans, numbers, dates, JSON) that cannot contain stega encoding. The recommended approach is to use the `_editingUrl` field available on all records: ```graphql query { product { id price isActive _editingUrl } } ``` ```svelte ${product.price} ``` #### `data-datocms-content-link-source` Attaches stega-encoded metadata without the need to render it as content. Useful for structural elements that cannot contain text (like `