Monday, October 2, 2023

Exploring Atomic, Modular, and Headless Content Paradigms

 How we structure, manage, and deliver content continuously changes in today’s fast-evolving digital landscape. As businesses strive to provide seamless user experiences across various platforms and devices, the methodologies behind content creation and delivery become crucial. Enter the paradigms of atomic, modular, and headless content. While they might sound like buzzwords to the uninitiated, these concepts represent the forefront of modern web development and content management strategies. In this post, let us deep dive into Atomic, Modular, and Headless Content Paradigms.

Atomic content, drawing inspiration from the world of atoms — nature’s fundamental building blocks — emphasizes creating content in its smallest, indivisible units. This approach ensures content is versatile, platform-agnostic, and ready to be served whenever and wherever needed.

Modular content takes a slightly broader perspective. Imagine constructing a building with LEGO blocks; each module or block is self-contained but forms a cohesive whole when combined. This modular methodology streamlines content creation promotes consistency, and provides flexibility in tailoring content for varying needs. Content modularization is the process of creating small blocks of content that will be pre-approved, stored, and repurposed across channels.

Meanwhile, the headless approach revolutionizes how we think about content storage and delivery. Stripping away the traditional coupling of content and presentation, a headless system serves content through APIs, making it a breeze to deliver across websites, mobile apps, IoT devices, and more.

Atomic, Modular, and Headless Content Approaches

The modular content is organized in the below levels.

  • Content Blocks: These are standalone, pre-approved items (like files) that can be used in content pieces or campaigns. They might be single items, like a picture or a piece of writing. Or, they could be small combinations of different items, like a picture with text.
  • Content Sets: This is when you take multiple content blocks and group them into larger, well-matched sets. You can use these sets on their own or mix them across different platforms. This helps ensure the brand feels consistent everywhere without repeating the same content.
  • Content Experiences: This is how people experience the content sets in real life — whether on websites, social media, kiosks, etc. Though the content may vary across platforms, it should still feel connected and offer a consistent experience for the user.

Atomic/Modular content is content reuse, stemming from a need to deliver content on multiple devices and screens and in variations for different audiences based on location. Previously, without modular content capabilities, publishers typically focused on creating content for one medium or audience at a time.

Modular content helps simplify this complex challenge by providing finite control over where and how content appears. Think of modular content like building blocks. The way modular content is defined varies by business use case and need. Depending on your business needs, the smallest block could equate to a single sentence or a single module on a page; for example, stack several small sentences “blocks” together, and you’ve created an article that can be displayed on a website.

The idea of content as blocks that can be reused, mixed, and matched is beneficial when you’re going omnichannel. With this approach, marketers don’t need to create new content. Instead, they have an inventory of previously created content (perhaps originally for another channel campaign or region) that they can then reuse. Having such reusable content enables higher quality and greater consistency in content creation.

Some of the benefits of Atomic/Modular Content:

  • Faster Time-to-Market: It’s quicker to assemble and deploy content when needed.
  • Personalization: Modular content can be combined in different ways to cater to specific audience segments, allowing for more personalized user experiences.
  • Reusability: Once created, content components can be reused across different channels, mediums, or platforms without needing to recreate or copy them.
  • Consistency: With atomic content, there’s a higher likelihood of maintaining a consistent tone, style, and message across all platforms because you’re using the same modular pieces.
  • Easier Updates: When an update is needed, you can modify the base component, which will reflect across all instances where it’s used, ensuring up-to-date content.
  • Cost-Effective: In the long run, reusing content components can lead to cost savings as teams spend less time creating and more time optimizing.
  • Scalability: As your content needs grow, it’s easier to scale with a modular approach than to keep creating new content from scratch.
  • Future-Proofing: As new channels or technologies emerge, atomic content can be easily adapted or repurposed to fit, ensuring longevity and relevance.
  • Reduces duplication: Atomic/Modular content approaches help to reduce the duplicated content.

When to Consider Atomic/Modular Content:

The Atomic/Modular content approaches may only fit some of the use cases and scenarios; sometimes, the traditional content may work well compared to Atomic/Modular content. Before opting for an atomic/modular content approach, ensure you understand the content’s purpose, whether channel-specific, short-term news/articles or something else.

  • Multi-Channel Distribution: If your content is distributed across various platforms (e.g., websites, mobile apps, social media, print), atomic content allows for seamless adaptation and consistency across channels.
  • Frequent Updates: For content that requires regular updating, it’s more efficient to change a single module than to find and edit every instance of a content piece.
  • Scalability Needs: If you anticipate scaling your content in volume or across new platforms, atomic content can simplify the scaling process.
  • Personalization Goals: Atomic content is ideal for organizations aiming for deep personalization, allowing them to mix and match content pieces for different audience segments.
  • Content Reuse: If similar content pieces are used in different places or for various purposes, atomic content can reduce redundancy.
  • Future-proofing: When preparing for emerging technologies or platforms, modular content can ensure that you’re ready to adapt.

In some cases, the Atomic/Modular Content may not fit well.

  • Narrative or Linear Content: For content with a strong linear narrative (like a novel or a long-form journalistic article), breaking it down into atomic pieces might disrupt the flow.
  • Limited Scope: The effort to go atomic might outweigh the benefits if your content is only meant for a single channel and doesn’t require frequent updates or repurposing.
  • Overhead and Complexity: Implementing a modular content strategy might require changes in content creation processes, training, and possibly even the CMS. The initial investment in time, effort, and possibly money can be substantial.
  • Loss of Context: Content pieces risk losing their context when they’re separated from the whole. Care must be taken to ensure that standalone pieces make sense in isolation.
  • Short-Term Projects: For projects with a short lifespan where content won’t be repurposed or redistributed, atomic content might be overkill.

From my perspective, it’s crucial to identify which content is suitable for the atomic/modular content approach before adopting this strategy. Reorganizing existing content to fit the atomic/modular framework can sometimes be labor-intensive and costly. In such cases, it might be more practical to adopt the atomic/modular approach solely for new content while exploring alternative methods to manage and share the existing content.

The headless or hybrid CMS systems utilize Content APIs to distribute atomic/modular content across various channels. This content is managed within a centralized repository, ensuring seamless sharing across diverse channels and systems. While many CMS systems facilitate content or page sharing through APIs, the crucial consideration is not just adopting a headless system. Instead, embracing a content management strategy(process) that aligns with the headless approach is essential, emphasizing atomic/modular content.

Atomic, modular, and headless content concepts are interconnected and frequently employed in contemporary content management. Atomic and modular content strategies emphasize the organization, structure, and reusability of content, ensuring it’s crafted in a manner that’s both platform-agnostic and scalable. On the other hand, headless content underlines the decoupling of content from its presentation, facilitating the delivery of atomically structured and modular content to any platform or device through APIs.

Every CMS system follows different approaches to managing and sharing Atomic/Modular content. Let’s take a high-level look at how Atomic/Modular content is managed and shared in Adobe Experience Manager (AEM), a hybrid CMS system.

AEM is fundamentally structured around components, which act as the primary units of content. These components can encompass a variety of elements, including text, images, videos, and buttons. Users can craft, modify, and reuse these components across different parts of a website or even span multiple websites. These individual components can then be amalgamated to create page templates, exemplifying the modular content strategy. One notable feature of AEM is its inherent content services, which facilitate content retrieval in a JSON format. This capability shares the content without the entire HTML as a JSON format to mobile apps, single pages, and other platforms. Refers to AEM Experience Manager(AEM): Content Sharing Approaches | by Albin Issac | Tech Learnings | Medium to understand different content sharing options, including Content as a Service API’s

Further enhancing AEM’s offering is the introduction of Content Fragments. This feature paves the way for creating structured content indifferent to the channel it’s presented on. Tailored at both Atomic and Modular tiers, relationships between Content Fragments can be orchestrated, allowing Modular content’s formation in diverse contexts. Equipped to handle variations specific to different channels, Content Fragments also play a pivotal role in localizing content. Such structured content can be used within AEM pages or Experience Fragments. These Content Fragments can also be shared as Headless content through GraphQL endpoints to various channels. For a deeper dive into sharing Content Fragments via GraphQL API in AEM, How to deliver headless content through GraphQL API and Content Fragments? | AEM(Adobe Experience Manager) | by Albin Issac | Tech Learnings | Medium.

Experience Fragments (XF) in AEM deserve a special mention. Crafted to facilitate the creation and distribution of channel-agnostic content, XFs are aggregations of one or multiple components, coupled with their layout, all fine-tuned for reuse. They align with the modular content strategy, allowing content creators to curate adaptable content detached from any specific page or template. This design inherently fast-tracks content updates, with changes to an XF instantaneously reflecting wherever deployed. AEM supports XF variations, enabling customization tailored to specific scenarios or channels. While XFs are effortlessly integrated into AEM pages, they can be combined with AEM’s Content Services to share with external systems/channels as JSON or HTML formats. This ensures that content can be consumed across various channels, apps, or platforms in a headless mode.

In AEM, the Digital Asset Management (DAM) aligns with the Atomic/Modular approach, efficiently managing various assets such as images, videos, and documents. Metadata tagging within the DAM ensures assets are systematically organized and swiftly retrievable, streamlining content creation. Beyond in-platform usage, these assets can be seamlessly shared outside of AEM. Importantly, when assets are integrated into content fragments or disseminated externally, AEM ensures that the latest approved version is used, guaranteeing brand consistency and accuracy across all channels.

In conclusion, while the Atomic/Modular and headless content strategies are indispensable in today’s rapidly changing digital environment, assessing business challenges and needs is essential before committing to an approach. Not all scenarios may benefit from these strategies. It’s prudent to pinpoint content that’s ripe for this strategy and initiate it there. Additionally, retrofitting existing content to align with an Atomic/Modular approach might demand significant resources. Therefore, adopting this strategy primarily for new content creation often proves more logical.

Friday, September 15, 2023

Leveraging 3rd Party Packages in AEM as a Cloud

 In this post, let us explore how to deploy and use third-party (external) package bundles into the AEM as a Cloud platform.

Most of the time, we must embed third-party packages into the AEM platform to enable tool-specific functionalities. In AEM versions other than AEM as a Cloud platform, the external packages can be directly installed through the package manager without any issues. But in AEM as a Cloud platform, due to the architecture change, the package that has immutable content, e.g., /apps, are not allowed to be installed through package managers and should be part of the code deployment; some of the Adobe-supported external packages like CIF add-on, Core Components, and ACS Commons packages are enabled through Cloud Manager in AEM as a Cloud platform.

Let us understand how the external packages can be enabled for AEM as a Cloud platform.

Let’s start with the package/bundle hosted through an external repository.

As a first step, add the external repository where the package is hosted to the parent pom.xml and the existing Maven repositories.

<repositories>

.............

<repository>
<id>project.local</id>
<name>project</name>
<url>https://test.repo.com/repository</url>
</repository>

</repositories>

Now add the package or bundle dependency to the all/pom.xml (the version can be managed through the parent pom property)

<dependency>
<groupId>com.test.components</groupId>
<artifactId>com-test-components.all</artifactId>
<version>1.0.0</version>
<type>zip</type>
</dependency>

Now add the embed as part of the filevault-package-maven-plugin in all/pom.xml.

<plugin>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>filevault-package-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<group>com.test</group>

.............

<embeddeds>

................

<embedded>
<groupId>com.test.components</groupId>
<artifactId>com-test-components.all</artifactId>
<type>zip</type>
<target>/apps/test-vendor-packages/container/install</target>
</embedded>

</embeddeds>
</configuration>
</plugin>

Now, while deploying the code, the external package will also get deployed to the AEM as a Cloud server. Ensure the external package follows the AEM as a Cloud best practice for their packages; the package may not function as expected in AEM as a Cloud.

Sometimes, you may not have the package stored in the external repository, but if the package is locally available, you need to follow some additional steps.

Create a folder with the name repository under the root of the project.

Now install the local package/bundle to the project repository

mvn install:install-file -Dfile=<Local Package path> -DgroupId=<Group ID of the external Package> -DartifactId=<Artifact ID of the external Package> -Dversion=<Version of the external Package> -Dpackaging=<Packing Type of the external Package> -DlocalRepositoryPath=<Project Repository Folder Path>
mvn install:install-file -Dfile=C:\Test\com-test-components.all-1.0.0.zip -DgroupId=com.test.components -DartifactId=com-test-components.all -Dversion=1.0.0 -Dpackaging=zip -DlocalRepositoryPath=C:\Projects\AEM\mysite\repository

Now, the package will be installed in the project repository.

Update the repository location in parent pom.xml to point to the local project repository; the remaining steps are the same.

<repositories>

.............

<repository>
<id>project.local</id>
<name>project</name>
<url>file:${maven.multiModuleProjectDirectory}/repository</url>
</repository>

</repositories>

Now, while deploying the project through the Cloud Manager pipeline, the external package also gets installed to the AEM as Cloud servers.

Friday, September 8, 2023

Support Custom Run Modes in AEM as a Cloud | Environment Specific Variables in AEM as a Cloud

 This post explores the approach to supporting current custom run modes in AEM as a Cloud using Cloud Manager environment-specific variables and OSGI configurations.

Run Modes lets you tune your AEM instance for a specific purpose: author or publish test, uat, development, intranet, or others.

You can:

  • Define collections of configuration parameters for each run mode.
  • A basic set of configuration parameters is applied for all run modes; you can then tune additional settings to the purpose of your specific environment. These are used as required.
  • Define additional bundles to be installed for a particular mode.

All settings and definitions are stored in the repository and activated by setting the Run Mode.

In AEM versions other than AEM as a Cloud (On-Prem, AMS, Hosted), apart from default run modes (Author, publish, samplecontent, nosamplecontent), we can define custom run modes such as test and uat. Let’s assume you have different AEM environments like Dev, UAT, Stage, and Prod, and each environment needs to connect to a corresponding third-party service, e.g., Dev Service, UAT Service, Stage Service, and Prod Service; this can be achieved by enabling a custom run mode to differentiate each environment then enable OSGI configurations based on the run mode(multiple run modes can be combined if required e.g. publish.uat)to enable environment specific service URL.

Create a configuration file in ui.config project— /apps/<Project Name>/osgiconfig/config.<RunModes>/<Persistent Identity>.cfg.json

The configurations that are common across all the environments can be placed under the config folder — /apps/<Project Name>/osgiconfig/config/<Persistent Identity>.cfg.json

e.g /apps/test/osgiconfig/config.uat/com.test.EndpointService.cfg.json

{
"serviceURL":"https://uat.service.com/testservice"
}

The run mode approach is changed in AEM as a Cloud Service; in AEM as a Cloud Service, run modes must reference RDE, development, stage, and production for the environment or author and publish for the service. A combination of <service>.<environment_type> is being supported, whereas these environments have to be used in this particular order (for example, author.dev or publish.prod)

In AEM as a Cloud service, the environment-specific configurations can be enabled using the Cloud manager environment variable and OSGI configuration. Two value types can be enabled — secret values and standard variables. The OSGI configurations can directly reference the Cloud Manager environment-specific values, replaced with actual values during the runtime.

{
"my_var1": "$[env:my_var1;default=val1]"
"my_var2": "$[secret:my_var1]"

}

As the stage and prod run modes are supported in AEM as a Cloud, the Major concern is on having multiple Dev environments(each AEM as a Cloud program by default enables one dev environment but allows the addition of additional Dev environments as required) and designating those for different purposes, e.g., UAT testing and QA testing, etc.; each Dev instance will have the run mode enabled as “Dev,” so by default, you will not be able to enable different configurations for different Dev environments by following the current approach. Still, you can do it for Stage and Prod.

You can follow two approaches.

  • Keep all the configurations under the config folder and separate any configurations that vary between authors and publisher into a config.author and config.publish run mode-specific folders and use Cloud Manager Environment variables in OSGI to enable environment-specific values.
  • Keep the configurations separated by Dev(config.dev), Stage(config.stage), and Prod(config.prod) run modes and also separated by Author and Publish run modes if required. Keep the Stage and Prod specific configurations directly on the Stage(config.stage) and Prod(config.prod) specific configurations. Then, use the Cloud Manager Environment variable to enable environment-specific configurations for Dev environments designated for different purposes.

Accessing the configuration without enabling the environment variable will display the placeholder string; the default value can be provided if required.

I am accessing the configuration value through a servlet.


@Component(service = { Servlet.class }, property = { "sling.servlet.paths=/services/endpoint",
"sling.servlet.methods"
+ "=GET" })

@Designate(ocd = EndpointService.EndpointServiceConfiguration.class)
public class EndpointService extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 7699176851252742022L;

String endpoint;

@ObjectClassDefinition(name = "Endpoint Servlet")
public @interface EndpointServiceConfiguration {
@AttributeDefinition(name = "Endpoint", description = "Configure Endpoint")
String serviceURL() default "";
}

@Override
protected void doGet(SlingHttpServletRequest request,
SlingHttpServletResponse response)
throws ServletException, IOException {

response.getWriter().write("endpoint: " + endpoint);

}

@Activate
@Modified
protected void activate(EndpointServiceConfiguration config) {
this.endpoint = config.serviceURL();
}
}

You can use Cloud Manager Console or API to configure the Environment variables on Cloud Manager.

Login to Cloud Manager Console

Go to Environments and Select the View Details for the specific environment.

Click on Configuration

Add Configurations — Variable or Secret type, and also, the variable can be enabled for all the servers on the environment or specific to Author, Publish, or Preview.

Upon Save, the variable references are updated runtime; this may take some time.

Once the environment configuration update is completed, you can get the value.

You can check the OSGI configuration through the Developer Console, but this will only display the placeholder string not updated with the environment variable.

The variable can be deleted or updated if required; please note that it may take some time to reflect the changes, so plan your changes accordingly.

Also, you can enable secrets if required.

The Cloud Manager API or Command Line also can be used to manage the environment variables.

Dispatcher Configuration Per Environment:

The AMS or AEM as a Cloud uses the same configurations across all the environments and uses environment-specific server variables to support per-environment configurations.

By default, AEM as a Cloud is equipped with several environment variables. One such variable is ENVIRONMENT_TYPE, which indicates the current run mode, such as 'development', 'stage', or 'production'. This variable can be directly referenced in expressions. Additionally, there are "define" flags named ENVIRONMENT_DEVENVIRONMENT_STAGE, and ENVIRONMENT_PROD. These "define" flags can be utilized to construct logic using the <IfDefine> directive.

# Simple usage of the environment variable
ServerName ${ENVIRONMENT_TYPE}.company.com

# When more logic is required
<IfDefine ENVIRONMENT_STAGE>
# These statements are for stage
Define VIRTUALHOST stage.example.com
</IfDefine>
<IfDefine ENVIRONMENT_PROD>
# These statements are for production
Define VIRTUALHOST prod.example.com
</IfDefine>

In some cases, you may need custom variables, e.g., to separate each Dev environment for different use cases — Dev, UAT, etc.; in this case, you can use Cloud Manager environment variables, e.g., CUSTOM_VARIABLE in your httpd/dispatcher configuration, although not environment secrets. You can refer to this as a variable, e.g., ${CUSTOM_VARIABLE}, but the Define syntax defined in the earlier section will not work.

Refer to Configuring OSGi for Adobe Experience Manager as a Cloud Service | Adobe Experience Manager and Validating and Debugging using Dispatcher Tools | Adobe Experience Manager for more details on managing environment variables, including managing through API/Command lines, and also details on how local development can adopt this approach.