Headless Editing — Edit Mode Anywhere (Legacy)

Last Updated: May 12, 2022
documentation for the dotCMS Content Management System

⚠️ Note: The legacy EMA feature is now deprecated in favor of the newer and more powerful Universal Visual Editor, which does everything EMA could do, and more — and more simply!

dotCMS allows full in-context editing for JamStack, SPAs (Single Page Apps) or remote apps (.js, .NET, php) that have been built to pull content from dotCMS. To enable Edit Mode Anywhere, or EMA for short, your app should:

  1. Be built to read and deliver dotCMS content using the dotCMS PageAPI and ContentAPI for specific sections/pages/routes
  2. Be able to do SSR (server side render) of your site at a given page route
  3. Edit Mode Anywhere can enabled using any external hosting service: including Vercel, AWS Amplify, etc.
  4. Be able to accept POSTs to an endpoint at /ema which can render the Page API JSON information coming from dotCMS into a version of the expected page.
  5. When accepting these POSTs, add the additional HTML markup (mainly data attributes) dotCMS requires to enable edit mode.

How it works

When a user requests to edit a page with Edit Mode Anywhere enabled, dotCMS proxies the request, and POSTs the page api payload to your remote SPA or site to be server side rendered. This POST includes the template, containers, layout , content and vistor information to your SPA or remote site. For reference, the EMA payload is the same as what is returned from the page endpoint /api/v1/page/json/{path}. dotCMS POSTs this payload to your SPA or remote site renderer with the content type of application/x-www-form-urlencoded and the Page API data as a JSON string as the form parameter dotPageData. The remote application or SPA needs to be built to accept this POSTed parameter, parse the dotPageData param and use it to statically render your App server-side in that state our route. dotCMS will read this rendered state/html and return it to edit mode.


dotCMS EMA supports two kinds of routes — page routes and slug routes. This works because dotCMS is a hybrid system and the page API supports requests for page data using real page URLs, which are both page URLs and slug URLs in dotCMS. This means that both of these routes are valid API requests for page data https://demo.dotcms.com/api/v1/page/json/about-us/index and https://demo.dotcms.com/api/v1/page/json/blogs/your-blog-slug-url-mapped-title

Slug Content

When a slug route is requested via API, dotCMS will include the slug content for the route in a property called urlContentMap, which contains the entire slug content object for that route.

Note: While page routes can have distinct, manageable content and layouts, slug routes generally cannot. Changes made to a page routes' layouts/content will only affect the page being edited. This is different for slug based routes. Because all slug content of a type shares the same detail page, changes made to the slug detail page/layout will affect all the slug routes for that specific content type.

Adding/Removing Routes

To add a new route for an SPA in dotCMS all you need to do is add a page or a new Slug based content. The new route will automatically be included in calls to the Navigation API and/or the content APIs which dictate valid routes for your application. Unpublishing/deleting a route will automatically remove the route from your SPA/app.

Edit Mode JS Events

dotCMS expects certain events to fire actions while in Edit Mode. These are important if you want to build a custom application or SPA that supports Edit Mode Anywhere. These include:

  1. Internal User Navigation This forces a page refresh in your APP and should fire when a user clicks an internal link in your SPA

  2. Reorder Navigation This opens the reorder nav modal and should fire when an editing user clicks the “reorder nav” link

  3. Edit Contentlet This opens a contentlet up for editing in a modal editor window.

EMA Limitations

The current EMA implementation requires an authoring environment that is capable of handling POSTed Page API data. As of now, this requires at least server side / isomorphic page rendering.

By way of example, our dotCMS starter uses NextJS to act as the server side implementation.

It accepts the Page API the posted data and wraps the included content objects in the SPA with specific custom components that add attributes dotCMS reads for when rendering a page in edit mode.

Some version of this pattern would likely be a requirement for any 3rd party SPAs or apps looking to support EMA.


Enable and configure the APP

  1. In your dotCMS instance go to Settings > App
  2. Click on EMA app
  3. Select your host
  4. Enter the url of your webapp like: https://yourdemo.vercel.com/ema
  5. Go to site browser and edit a page


If you webapp is running in your localhost and the dotCMS instance in a server you need to use a tunnel tools like https://ngrok.com/

Optional — dotCMS Next JS Example

dotCMS provides a NextJs example implementation that is intended to act as a starting point for building your own Edit Mode Anywhere site. While the dotCMS example uses NextJs, the code and components needed to render the dotCMS elements in edit mode are part of separately installable js libraries called:


Live Content vs. Previewing Content

dotCMS requires an API key to access content and pages stored in dotCMS. These dotCMS API keys can be generated from the command line or from the backend of dotCMS from the User Manager screen. In dotCMS, an API key grants the permissions of the user to which they are issued, including permissions tied to any roles that the user might have. All content and API calls are permission-based and will return differently based on the key's user permissions.

dotCMS has the concept of “Front End” users and “Back End” users. Front end users can only see live/published content. Back end users can preview drafted/unpublished content. This means that if an API key is generated for a “Front End” user (a checkbox in the User's Account) then that key will only be able to view and access published/live front-end content (this includes content that has CMS Anonymous access set to READ). If an API key is generated for a “Back End” user (again, a checkbox in the User's Account), then that key will enable preview access to unpublished/working content based on the “Back End” user's permissions.

API Authentication Strategies

Setting up preview vs. production environments for API only access presents some challenges, though there are a number of strategies you can use to secure your environments.

Viewing Live Content: a Single Key

For publicly accessible and read-only sites, an API key can be generated for a front-end user and embedded in an app or SPA that is used to make the API requests. While the embedded API key would be discoverable by a snooping web developer, it only grants read access to public content and is not unlike anonymous read access on any web property.

Previewing Content: a Single Key

If your content is not sensitive and your preview environment is only accessible by trusted visitors, the same strategy can be used to create a “Preview” user key in dotCMS. To do this, you create a limited back-end user in dotCMS and with them generate an api key or .env file for your preview environment. While this back-end api key is easy to use, it has the significant downside that it will also be discoverable by anyone who can access your preview environment. That said, the risks of this approach might be acceptable if simplicity is important, the content is not overly sensitive and the keys' permissions are limited only to reads and/or specific pages or content types.

Previewing Content: dotCMS Auth before

A more involved strategy requires users to authenticate against dotCMS or another 3rd party authentication system before they access the preview url. Out of the box, dotCMS provides an authentication api that could be used to authenticate users before they can view any content. The api call below authenticates joe@dotcms.com user and sets a cookie on the user's browser which is then used to authenticate further dotCMS API calls. The authenticated user's browser passes this cookie with each API request and is granted the permissions based on their dotCMS permissions.

curl 'https://demo.dotcms.com/api/v1/authentication' -v \
-H 'Content-Type: application/json' \
--data-binary ' 

Previewing Content : 3rd Parth Auth before

dotCMS can also integrate with 3rd party authentication mechanisms such as OAUTH, SAML or AD. When an unauthenticaed user accesses the preview site, they are redirected to the 3rd party authentication mechinism. Once authenticated there, they are returned to your app with a token or a cookie they can pass to dotCMS, which will validate the token against the 3rd party and map the newly authenticated user to a user in dotCMS. dotCMS provides both an OAuth and SAML plugins to do just this.

On this page


We Dig Feedback

Selected excerpt: