# ContentLink component for Visual Editing `` is a Vue component that enables **Visual Editing** for DatoCMS content by providing click-to-edit overlays and seamless integration with the DatoCMS Web Previews plugin. - TypeScript ready; - Usable both client and server side; - Compatible with vanilla Vue, Nuxt and pretty much any other Vue-based solution; - Framework-agnostic with easy integration for Vue Router, Nuxt Router, and custom routers; - [What is Visual Editing?](#what-is-visual-editing) - [Out-of-the-box features](#out-of-the-box-features) - [Installation](#installation) - [Basic Setup](#basic-setup) - [Step 1: Configure your DatoCMS client](#step-1-configure-your-datocms-client) - [Step 2: Add the ContentLink component](#step-2-add-the-contentlink-component) - [Usage](#usage) - [Framework-agnostic (no routing)](#framework-agnostic-no-routing) - [With Vue Router](#with-vue-router) - [With Nuxt](#with-nuxt) - [Enabling click-to-edit](#enabling-click-to-edit) - [Flash-all highlighting](#flash-all-highlighting) - [Props](#props) - [Advanced usage: the `useContentLink` composable](#advanced-usage-the-usecontentlink-composable) - [When to use the composable](#when-to-use-the-composable) - [API Reference](#api-reference) - [Example with custom integration](#example-with-custom-integration) - [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 records, and inline blocks in a boundary](#rule-2-wrap-embedded-blocks-inline-records-and-inline-blocks-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) - [Overlays appearing in wrong places](#overlays-appearing-in-wrong-places) - [Navigation not working in Web Previews plugin](#navigation-not-working-in-web-previews-plugin) - [Performance issues with many editable elements](#performance-issues-with-many-editable-elements) - [Content not clickable inside StructuredText](#content-not-clickable-inside-structuredtext) - [Layout issues caused by stega encoding](#layout-issues-caused-by-stega-encoding) ## 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 Vue Router, Nuxt, 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 ```bash npm install vue-datocms ``` The `@datocms/content-link` package is included as a dependency, so you don't need to install it separately. ## Basic Setup Visual Editing requires two steps to set up: ### Step 1: Configure your DatoCMS client 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. ### Step 2: Add the ContentLink component Add the `` component to your app. It doesn't render anything visible, but it activates the Visual Editing features: ```vue ``` That's it! Editors can now press and hold the Alt/Option key to temporarily activate click-to-edit mode. ## Usage ### Framework-agnostic (no routing) For simple sites without client-side routing: ```vue ``` ### With Vue Router For apps using Vue Router, pass routing callbacks to enable in-plugin navigation: ```vue ``` ### With Nuxt For Nuxt applications: ```vue ``` Or create a reusable component: ```vue ``` Then use it in your layout: ```vue ``` ## Enabling click-to-edit By default, click-to-edit overlays are **not enabled automatically**. Editors have two ways to activate them: 1. **Alt/Option key (recommended)**: Press and hold the Alt (Windows/Linux) or Option (Mac) key to temporarily enable click-to-edit mode. Release the key to disable it. This is the most convenient method as it requires no code changes. 2. **Programmatically on mount**: Set the `enable-click-to-edit` prop to enable overlays when the component mounts: ```vue ``` Or with options: ```vue ``` **Options:** - `scrollToNearestTarget`: Automatically scroll to the nearest editable element if none are currently visible on screen. Helpful for long pages. - `hoverOnly`: Only enable click-to-edit on devices that support hover (i.e., non-touch devices). This is useful to avoid showing overlays on touch devices where they may interfere with normal scrolling and tapping behavior. On touch-only devices, users can still toggle click-to-edit manually using the Alt/Option key. ## Flash-all highlighting The flash-all feature visually highlights all editable elements with an animated effect, helping editors discover what content they can edit. This is particularly useful when first exploring a page. To trigger flash-all, you need to use the `useContentLink` composable: ```vue ``` ## Props | Prop | Type | Default | Description | | ---------------------- | ----------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `on-navigate-to` | `(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 | | `current-path` | `string` | - | Current pathname to sync with [Web Previews plugin](https://www.datocms.com/marketplace/plugins/i/datocms-plugin-web-previews) | | `enable-click-to-edit` | `true \| { scrollToNearestTarget?: boolean, hoverOnly?: boolean }` | - | Enable click-to-edit overlays on mount. Pass `true` or an object with options. If undefined, click-to-edit is disabled | | `strip-stega` | `boolean` | - | Whether to strip stega encoding from text nodes after stamping | | `root` | `Ref` | - | Ref to limit scanning to this root element instead of the entire document | ## Advanced usage: the `useContentLink` composable For more control over Visual Editing behavior, you can use the `useContentLink` composable directly. This gives you programmatic access to all Visual Editing features. ### When to use the composable Use the composable instead of the component when you need to: - Programmatically enable/disable click-to-edit based on conditions - Trigger flash-all highlighting from your UI - Access the controller instance directly - Integrate with custom state management - Build custom Visual Editing UI ### API Reference ```typescript import { useContentLink } from 'vue-datocms'; const { controller, // Ref - The controller instance enableClickToEdit, // (options?) => void - Enable click-to-edit overlays disableClickToEdit, // () => void - Disable click-to-edit overlays isClickToEditEnabled, // () => boolean - Check if click-to-edit is enabled flashAll, // (scrollToNearestTarget?) => void - Highlight all editable elements setCurrentPath, // (path: string) => void - Notify plugin of current path } = useContentLink({ // enabled can be: // - true (default): Enable with default settings (stega encoding preserved) // - false: Disable the controller // - { stripStega: true }: Enable and strip stega encoding for clean DOM enabled: true, onNavigateTo: (path) => { /* handle navigation */ }, root: myRootElementRef, // Optional: limit scanning to this element }); ``` **Options:** - `enabled?: boolean | { stripStega: boolean }` - Controls whether the controller is enabled and how it handles stega encoding: - `true` (default): Enables the controller with stega encoding preserved in the DOM (allows controller recreation) - `false`: Disables the controller completely - `{ stripStega: true }`: Enables the controller and permanently removes stega encoding from text nodes for clean `textContent` access - `onNavigateTo?: (path: string) => void` - Callback when Web Previews plugin requests navigation - `root?: Ref` - Ref to limit scanning to this root element **Note:** The `` component allows controlling stega stripping through the `strip-stega` prop. When undefined, the underlying library's default behavior is used. ### Example with custom integration ```vue ``` ## 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 } } ``` ```vue ``` #### `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 `