Monday, June 17, 2024

AEM Universal Visual Editor: Easily Author AEM Content Anywhere with In-Context Editing (Part 1)

 The Universal Editor is the next generation of AEM in-context page editors, designed to overcome the current limitations of the AEM Page Editor and SPA Editor. It offers a truly universal editing experience by being independent of frameworks, rendering engines, and data sources. This flexibility provides developers with the freedom they seek, as the only requirement is a rendered HTML with the necessary instrumentation. Additionally, the Universal Editor streamlines the content creation process, enhancing productivity and efficiency for content creators and editors. The Universal Editor supports both headless and headful (traditional pages and EDS content) content authoring. In this post, let us explore the high-level details of the Universal Editor.

What is the Universal Editor?

The Universal Editor is a versatile visual editor that is part of Adobe Experience Manager (AEM) Sites. It enables authors to perform what-you-see-is-what-you-get (WYSIWYG) editing for any headless or headful experience.

AEM currently uses various editors for content authoring:

  • Page Editor: Enables in-context editing for the pages.
  • SPA Editor: Enables in-context editing for Single Page Applications (SPAs).
  • Content Fragment Editor: Provides editing capabilities for content fragments; in-context editing is not applicable.
  • Documents Editing: Allows direct management and editing of content through familiar documents (Word/Google Docs) from EDS websites.
  • Universal Editor: Enables in-context editing for various scenarios, including AEM pages(HTL-based), AEM headless content, AEM content for SPA applications, and AEM content for EDS.

The Universal Editor enables powerful in-context editing for both headless and headful content, including editing AEM content for EDS.

The Universal Editor supports Editing AEM Content for

  • Any Architecture — Server-side rendering, edge-side rendering, client-side rendering, and so on.
  • Any Framework — Vanilla AEM, or any third-party framework like React, Next.js, Angular, etc.
  • Any Hosting — Can be hosted locally to AEM, or on a remote domain
Image by Adobe — Universal Visual Editor

Key Features

  1. Responsive Design: Edit content seamlessly across different devices and screen sizes.
  2. Drag-and-Drop Interface: Easily create and arrange content elements within AEM pages.
  3. Inline Editing: Edit content directly on the page without switching views.
  4. Rich Text Editing: Robust text editing with formatting, spell check, and multimedia insertion.
  5. Versioning and Undo/Redo: Track changes and revert to previous versions as needed.
  6. Integration with AEM Components: Seamlessly edit and manage dynamic content like forms and widgets.

Benefits

  1. Increased Efficiency: Quickly and easily edit content without extensive training.
  2. Consistent User Experience: Maintain a uniform experience across different AEM projects.
  3. Improved Collaboration: Facilitate teamwork with a centralized platform for content management.
  4. Enhanced Content Quality: Ensure high-quality content with powerful editing tools and real-time previews

Universal Editor Access:

Universal Editor is a cloud-based service that allows authoring any AEM content. To access Universal Editor, you first need to request access. Follow these steps:

  • Sign in with your organization’s Adobe ID.
  • Contact your Adobe representative if the Universal Editor is not enabled for your organization.

Currently, Universal Editor is supported on AEM as a Cloud Service. It may be supported for AMS and on-premises AEM versions in the future. For local development and testing, you can follow the steps outlined in this document: Local AEM Development with the Universal Editor | Adobe Experience Manager.

Universal Editor Content Authoring:

The Universal Editor enables editing of websites hosted on any platform, including those hosted locally. For local websites to be edited via the Universal Editor, the local URL must be configured with HTTPS and support Self-Signed SSL certificates.

To enable Universal Editing for any websites

Include Universal Editor Core Library:

To enable CORS communication between the Universal Editor and your website, you need to include the Core library. You can do this in one of two ways:

Using npm package:

Install the package:

npm install @adobe/universal-editor-cors

Import it in your index.js:

import "@adobe/universal-editor-cors";

Using the CDN version:

Add the following script tag to your HTML:

<script src="https://universal-editor-service.experiencecloud.live/corslib/LATEST" async></script>

If needed, you can specify a particular version of the library by replacing LATEST with the desired version number.

Instrumentation:

The Universal Editor service requires a Uniform Resource Name (URN) to identify and utilize the correct backend system for the content in the app being edited. Therefore, a URN schema is required to map content back to content resources.

To define this, include the following meta tag in the <head> section of your web page:

<meta name="urn:adobe:aue:<category>:<referenceName>" content="<protocol>:<url>">

You can define multiple backend connections, for example, if the data needs to be persisted and retrieved from different AEM systems. The connection URL should be defined as a page meta tag in the <head> section of the web page.

For an AEM connection, use:

<meta name="urn:adobe:aue:system:<connection name>" content="aem:<AEM Author URL>"/>

For Example

<meta name="urn:adobe:aue:system:aemconnection" content="aem:https://author-p124345-e12345.adobeaemcloud.com"/>

Now instrument the elements with the required attributes. Below are some of the important attributes. Refer to Attributes and Item Types | Adobe Experience Manager for more details.

data-aue-resource: URN to the resource, location of the content on AEM or other backends.

data-aue-prop: Attribute of the resource.

data-aue-type: Type of the editable element. Various types available include:

  • text
  • richtext
  • media
  • component (makes part of the DOM movable/deletable)
  • container (acts as a container for other components)
  • reference (e.g., reference to a content fragment)

The Universal Editor supports in-context editing of both headless and full-featured AEM content.

Headless Authoring:

AEM content consumed on external applications, including content fragments or other page content, can be edited in context using the Universal Editor.

Content Fragment:

External websites can consume content fragments from AEM as headless content through GraphQL. Refer to How to deliver headless content through GraphQL API and Content Fragments? | AEM(Adobe Experience Manager) | by Albin Issac | Tech Learnings | Medium for more details on consuming Content Fragments through GraphQL.

I am using a persistent query to fetch the content fragments that capture the location details.

{
"data": {
"locationmodelList": {
"items": [
{
"_path": "/content/dam/sample/Location2",
"name": "Test Name2",
"number": 1234.0,
"street": "Test Street2",
"city": "Test City2",
"state": "Test State2",
"country": "USA",
"zipCode": "12345"
},
{
"_path": "/content/dam/sample/location1",
"name": "Test Name1",
"number": 123.0,
"street": "Test Street1",
"city": "Test City1",
"state": "Test State1",
"country": "USA",
"zipCode": "1234"
}
]
}
}
}

The content is consumed on a React app, with the following instrumentation enabled:

  • Adding data-aue-resource with the path to the content fragment to the parent div; the aemconnection is defined as metadata, with _path coming from the GraphQL query.
  • Setting data-aue-type as reference and data-aue-filter as cf.
  • Mapping the child elements to the corresponding content fragment fields using data-aue-prop and specifying the data-aue-type.
  • The custom label to the editable fields can be added using data-aue-label
const Location = ({ location }) => {
let itemId =
"urn:aemconnection:" + location._path + "/jcr:content/data/master";
return (
<div
data-aue-resource={itemId}
data-aue-type="reference"
data-aue-filter="cf"
data-aue-label={`Content Fragment ${location._path}`}
>

<h2>Location</h2>
Name:{" "}
<p data-aue-prop="name" data-aue-type="text" data-aue-label="Name">
{location.name}
</p>
Number:{" "}
<p data-aue-prop="number" data-aue-type="text" data-aue-label="Number">
{location.number}
</p>
Street:{" "}
<p data-aue-prop="street" data-aue-type="text" data-aue-label="Street">
{location.street}
</p>
City:{" "}
<p data-aue-prop="city" data-aue-type="text" data-aue-label="City">
{location.city}
</p>
State:{" "}
<p data-aue-prop="state" data-aue-type="text" data-aue-label="State">
{location.state}
</p>
Country:{" "}
<p data-aue-prop="country" data-aue-type="text" data-aue-label="Country">
{location.country}
</p>
Zip Code:{" "}
<p data-aue-prop="zipcode" data-aue-type="text" data-aue-label="Zipcode">
{location.zipCode}
</p>
</div>

);
};

/**
* Main component to render all locations.
*/

const LocationList = ({ locations }) => {
return (
<div>
{locations.map((location, index) => (
<Location key={index} location={location} />
))}
</div>

);
};

Now, when we open the website (in my case, https://localhost:3000) through the Universal Editor, the Universal Editor will make the parent DIV selectable and also mark individual fields as editable. Selecting the parent DIV or an individual field will display the Content Fragment (CF) editor on the right side. The CF values can be edited, modified CF values will be stored in the AEM CF, and the corresponding DOM elements updated. Additionally, we should be able to preview the page, perform device testing, and publish/unpublish the changes.

Additionally, the CF editor for the corresponding Content Fragment can be opened from the Universal Editor for a more detailed review and editing.

Using the Universal Editor, content fragments consumed by headless applications can be edited in context. This means that content displayed within a headless application can be directly modified within the application’s interface. The Universal Editor lets users see how changes will appear in real-time, ensuring that edits are seamlessly integrated into the live application. This capability enhances the efficiency of content updates, providing a more intuitive and streamlined editing experience.

Page Content:

Suppose you are sharing regular AEM page content with a headless application. In that case, the Universal Editor can assist in editing the content in context and ensure that the content changes persist to AEM. For example, if you have text content in AEM located at /content/sites/test/jcr: content/root/container/container/text, this content can be consumed by the headless application through model.json, accessed via /content/sites/test/jcr:content/root/container/container/text.model.json

/root/container/container/text.model.json.

The text content is consumed on an external app with the following instrumentation enabled:

  • Adding data-aue-resource with the path to the content, where the aemconnection is defined as metadata.
  • Setting data-aue-type as richtext and data-aue-prop as text.
  • Setting a custom label with data-aue-label as 'Text Data'."
 return (
<div
dangerouslySetInnerHTML={{ __html: textData.text }}
data-aue-resource={`urn:aemconnection:/content/sites/test/jcr:content/root/container/container/text`}
data-aue-type="richtext"
data-aue-prop="text"
data-aue-label="Text Data"
/>

);
};

// Main App component
const App = () => {
return (
<div>
<h1>Text Field</h1>
<TextField />
</div>

);
};

Now, when we open the website (in my case, https://localhost:3000) through the Universal Editor, it will make the DIV selectable and editable. The text values can be edited, and the modified text values will be stored in AEM with the corresponding DOM elements updated. Additionally, we will be able to preview the page, perform device testing, and publish/unpublish the changes.

Using the Universal Editor, AEM page content consumed by headless applications can be edited in context. This means that content displayed within a headless application can be directly modified within the application’s interface. The Universal Editor lets users see how changes will appear in real-time, ensuring that edits are seamlessly integrated into the live application. This capability enhances the efficiency of content updates, providing a more intuitive and streamlined editing experience.

Head Full Authoring:

The Universal Editor not only facilitates editing AEM content in a headless manner but also supports headful editing, allowing for a more traditional, full-page editing experience. It enables users to edit both AEM pages and AEM content intended for Edge Delivery Services(EDS). This dual capability ensures that content creators can efficiently manage and update content across various formats and platforms, maintaining consistency and ease of use.

AEM Pages:

AEM pages are traditionally edited through the AEM Page Editor. However, they can now be edited through the new Universal Editor. This applies to pages with AEM core components as well as custom components and templates. Currently, Core Components are not pre-configured for the Universal Editor, so manual configuration is necessary. You need to open the Universal Editor externally to edit any AEM pages configured with it. In the future, AEM Core Components might support these configurations out-of-the-box, and the Universal Editor may become the default, replacing the traditional Page Editor.

Steps to Enable AEM Page Editing through Universal Editor:

Add URN Connection: Add the URN connection to the page core component (e.g., /apps/test/components/page) in customheaderlibs.html:

<meta name="urn:adobe:aue:system:<connection name>" content="aem:<AEM Author URL>"/>

Example:

<meta name="urn:adobe:aue:system:aemconnection" content="aem:https://author-p12345-e12345.adobeaemcloud.com">

Add Universal Editor Cors Library: Add the Universal Editor Cors Library to the page core component in customheaderlibs.html:

<script src="https://universal-editor-service.experiencecloud.live/corslib/LATEST" async></script>

Configure AEM SlingMainServlet: By default, AEM’s SlingMainServlet sets X-FRAME-OPTIONS: SAMEORIGIN to block iframing of AEM pages from external domains. Adjust this configuration to allow the Universal Editor to iframe the pages for editing:

  • Enable the OSGI configuration org.apache.sling.engine.impl.SlingMainServlet.cfg.json with:
{
"sling.additional.response.headers": [
"X-Content-Type-Options=nosniff"
]
}

Configure Token Authentication Handler: The Universal Editor requires authentication tokens to be sent (via cookies) when accessing the page within an iframe. By default, AEM cookies are set with samesite as LAX, which blocks cookies in third-party contexts. Set the samesite attribute to None by enabling the OSGI configuration com.day.crx.security.token.impl.impl.TokenAuthenticationHandler.cfg.json with:

{
"token.samesite.cookie.attr": "None"
}

Instrument Components: Instrument the required components and elements for editing through the Universal Editor. For example, for a core text component (/apps/test/components/text), overlay text.html from the core library component (/libs/core/wcm/components/title/v2/title) to your custom proxy component (/apps/test/components/text) and add the required instrumentation configurations (e.g., data-aue-resourcedata-aue-typedata-aue-propdata-aue-label):

<div
data-sly-use.textModel="com.adobe.cq.wcm.core.components.models.Text"
data-sly-use.component="com.adobe.cq.wcm.core.components.models.Component"
data-sly-use.templates="core/wcm/components/commons/v1/templates.html"
data-sly-test.text="${textModel.text}"
data-cmp-data-layer="${textModel.data.json}"
id="${component.id}"
data-aue-resource="urn:aemconnection:${resource.path}"
data-aue-type="richtext"
data-aue-prop="text"
data-aue-label="Text Data"
class="cmp-text"
>
<p
class="cmp-text__paragraph"
data-sly-unwrap="${textModel.isRichText}"
>
${text @ context = textModel.isRichText ? 'html' : 'text'}
</p>
</div>
<sly
data-sly-call="${templates.placeholder @ isEmpty = !text, classAppend='cmp-text'}"
></sly>

Testing the Configuration:

Once the configurations are ready, you can open the AEM page with the instrumented component (e.g., text) through the Universal Editor by appending ?wcmmode=disabled to the URL. For example: https://author-p12345-e12345.adobeaemcloud.com/content/ewp/microsite/preventice/test.html?wcmmode=disabled

When opened through the Universal Editor, the DIV will be selectable and editable. Text values can be edited and stored in AEM, and the corresponding DOM elements will be updated. Additionally, you can preview the page, perform device testing, and publish/unpublish changes.

Edge Delivery Services Content on AEM:

The Universal Editor also supports authoring AEM content rendered through the EDS website. This approach uses EDS blocks directly in AEM through the Universal Editor. Using xwalk EDS AEM templates allows for a quick start with editing AEM content for EDS through the Universal Editor. Editing EDS content on AEM through the Universal Editor is seamless, as the pages can be directly opened through the page Edit option. Refer to the article AEM Edge Delivery Services — AEM Authored Content | by Albin Issac | Tech Learnings | Jun, 2024 | Medium for more details.

Conclusion:

The Universal Editor is a new approach for in-context editing of AEM content for any website — headless or headful. AEM is enabled with multiple editors, and in the future, some current editors (e.g., traditional Page Editor) may be replaced with the Universal Editor once it includes all required features. This post explored the Universal Editor and its use for in-context editing of headless and headful content. In our next blog, we’ll discuss how to use component/container approaches for authoring and how to enable component drag-and-drop from the property rail.

References:

Universal Editor Introduction | Adobe Experience Manager

Saturday, June 1, 2024

AEM Edge Delivery Services — AEM Authored Content

 Most of you might have already heard about AEM Edge Delivery Services. Edge Delivery Services (EDS) is a set of composable services designed to enhance the capabilities of Adobe Experience Manager, along with expanded content authoring functionalities.

EDS significantly improves website performance, shortens development processes, democratizes authoring at scale, and enables real-time experimentation to drive better engagement. When you hear EDS, the first assumption might be authoring content through known tools like SharePoint and Google Docs. However, EDS also supports authoring content in AEM through the Universal Editor. By using EDS blocks, similar to how you would author content in Google Docs or SharePoint, EDS renders AEM authored content directly to the website.

In this post, let’s explore some details on authoring EDS-supported content in AEM.

As you all know, Edge Delivery Services (EDS) supports authoring content through SharePoint documents and Google Docs, and EDS renders this content on the website in a way that achieves high Core Web Vitals (CWV) scores.

Additionally, content for EDS can be authored through AEM. While the traditional Page Editor and Core Component-based content can be used, this requires an external converter to transform the traditional HTML into EDS-supported markup so that the EDS front end can render the content.

Another option is using the Universal Editor along with EDS blocks to author the content. This approach uses EDS blocks directly in AEM through the Universal Editor, eliminating the need for an additional converter setup. While the traditional Page Editor/Core Component-based approach is not recommended, it can be used as a starting point for completely migrating to an EDS-based approach. Start by rebuilding the front end with EDS, and later adapt the Universal Editor along with EDS blocks to author the content within AEM.

Some existing projects may have complex components, so a step-by-step approach works well — the migration is not mandatory for existing websites. They can continue to work with the traditional approach, but you should decide based on your primary focus and benefits. However, new projects can start by adopting EDS with the Universal Editor.

Document based and AEM Content through Universal
AEM Edge Delivery Services with Existing AEM Projects

Creating and editing EDS-based content directly in AEM through the Universal Editor brings additional benefits. EDS leverages AEM’s JCR repository to store content, ensuring secure storage. The Universal Editor can utilize most of the existing AEM authoring capabilities, such as MSM (with some current restrictions, like only page-level inheritance being supported, not block-level), translation, launch, workflow, and publishing/scheduled publishing. No code changes to AEM are required, as the code changes are directly synced to Edge Delivery Services from GitHub, avoiding the need to install and maintain a local AEM instance for development.

Let’s quickly explore the details of authoring content in AEM through the Universal Editor and EDS blocks, and how to render that content on a website using the EDS front-end approach.

The authors create and edit pages using EDS blocks defined in the GitHub repository through the Universal Editor. The content is persisted in the JCR repository. Scripts, styles, and other resources are applied from the Edge Delivery Service deployment. The code from the GitHub repository is synced to Edge Delivery Services. Additionally, the Universal Editor pulls scripts, styles, and other resources from GitHub to render the authoring view. A Publish Event Handler subscribes to publication events and calls the AEM Admin API to retrieve the content, which is then persisted to Edge Delivery Services. Requests for content from users are served from Edge Delivery Services through a CDN

Currently, EDS content authoring through the Universal Editor is supported only for AEM as a Cloud. In the future, it may be supported by AMS. The Universal Editor can be set up in a local AEM SDK, but it will have some restrictions, such as limited access to AEM assets from the local AEM system. To start with EDS content authoring through AEM, ensure that you have access to an AEM as a Cloud Sandbox or a real AEM as a Cloud environment. Also, ensure that the Universal Editor is enabled for your AEM as a Cloud program. If it is not enabled, reach out to Adobe support. The Universal Editor allows you to directly author content using EDS blocks inside AEM. The content is persisted in the AEM JCR repository and shared with EDS for rendering.

EDS Boilerplate for AEM Content:

The https://github.com/adobe-rnd/aem-boilerplate-xwalk GitHub repository provides a boilerplate template for EDG projects with AEM content. Create a project using this template to obtain the basic configurations, blocks, scripts, and styles, which can then be customized as needed. Additionally, configure https://github.com/apps/aem-code-sync to the new repository. AEM Code Sync listens to changes in your code repository and publishes the code to EDS.

Configure the AEM Author server details in the fstab.yaml file. Replace the default URL with the URL of your AEM as a Cloud Service authoring instance: https://<aem-author>/bin/franklin.delivery/<owner>/<repository>/main.

Additionally, change the mapping of the content paths in the paths.json file. For example, map /content/test to /content/aem-boilerplate/:/.

The files component-models.json, component-definition.json, and component-filters.json are used to manage and configure components:

component-models.json: This file defines the data models for components. It specifies the structure and properties that each component can have, detailing how data is represented and handled within the component.

component-definition.json: This file contains the definitions of the components. It includes metadata such as the component’s name, type, and other configurations that determine how the component behaves and interacts with other components within AEM. Additionally, it enables the mapping between EDS components and AEM component resource types.

component-filters.json: This file is used to define filters for components. Filters are used to manage the visibility and availability of components based on certain criteria. This can include conditions under which a component should be displayed or hidden, or how components should be filtered when queried.

Using component-models.json, component-definition.json, and component-filters.json, new components can be created and the behavior of existing components can be modified — Content Modeling for AEM authoring with Edge Delivery Services Projects | Adobe Experience Manager Creating Blocks Instrumented for use with the Universal Editor | Adobe Experience Manager. Additionally, scripts, styles, and other resources can be updated as needed.

The AEM Command Line Interface (CLI) can be used to develop and test the websites on a local system.

AEM Site Template for EDS Sites:

The AEM Site for EDS Sites template helps create new AEM sites through the EDS site template. The new site content can be created and edited through the Universal Editor and Blocks. Access the latest AEM Authoring with Edge Delivery Services site template from GitHub at https://github.com/adobe-rnd/aem-boilerplate-xwalk/releases

Authors can now create, edit, publish/unpublish and test pages in AEM through the Universal Editor for EDS websites. Styles, scripts, and other resources are managed in a GitHub repository, while the content is directly managed and persisted in AEM. The Universal Editor pulls scripts, styles, and other resources from GitHub for authoring. EDS syncs the code from the GitHub repository for the live website and fetches the content from the AEM JCR repository.

EDS blocks and Content mapped to franklin core components
The Franklin core components help map the EDS blocks and content to AEM. They also assist in instrumenting the pages and components for Universal Editor authoring.

Apart from content pages (e.g., index) and fragments (e.g., header and footer), different page types can be created, such as placeholders, spreadsheets, metadata, configurations, headers, and redirects.


The EDS website can be accessed through https://main--<repository-name>--<owner>.hlx.page or https://<branch>--<repo>--<owner>.hlx.live/. Custom website domains can also be mapped. Like the EDS documentation, there are no separate preview and live URLs; both display the same published content from AEM. The preview and approval to live should be part of the AEM Content Authoring workflow. The repository is mounted to a single AEM Author instance. The published EDS content on this instance is displayed on the live site, but you can adjust this by creating environment-specific branches and pointing those branches to the appropriate AEM Author instances.

Conclusion:

In summary, leveraging AEM Edge Delivery Services (EDS) for AEM authored content brings numerous benefits to your content management and delivery workflow. By utilizing the Universal Editor, authors can efficiently create and edit content directly within AEM, making use of advanced features like MSM, translation, workflow, and scheduled publishing. The integration with GitHub allows for seamless synchronization of scripts, styles, and other resources, ensuring a smooth authoring experience and consistent content delivery.

The EDS boilerplate and the configuration of key files such as fstab.yaml, paths.json, component-models.json, component-definition.json, and component-filters.json streamline the process of setting up and managing components. This setup not only enhances the flexibility and scalability of your AEM projects but also reduces the need for local AEM instances, simplifying development and deployment processes.

By adopting AEM Edge Delivery Services, organizations can ensure secure, efficient, and scalable content delivery, making it a powerful solution for modern content management needs.

References:

https://youtu.be/buR0IzGhryI

Getting Started — Developer Tutorial | Adobe Experience Manager

Developer Getting Started Guide for AEM Authoring with Edge Delivery Services | Adobe Experience Manager