This release consists of the following new versions of the livingdocs-server and livingdocs-editor:


Livingdocs Server

How to require the server in your package.json:

"dependencies": {
  "@livingdocs/server": "66.0.15",

Livingdocs Editor

How to require the editor in your package.json:

"dependencies": {
  "@livingdocs/editor": "27.0.22",


Content Types - Server πŸ”₯ 🎁

Breaking Change The channel configurations now is based on contentTypes.

Required Actions

  • Postgres data migration needed: Make sure all entries in the documentstable in postgres have a content_type set (see migration)
  • Elasticsearch Mappings need to be updated.
  • Migrate channel configuration to the new format

Postgres Data Migration

The content types feature depends on the introduced db field documents.content_type.

Before you can deploy the January release, you have to run a manual database migration, which pre-fills the documents.content_type. We created a manual migration as this is a long running operation for databases with many documents.

If you have installed the October Release 2017 or December Release 2017, you can execute the manual migration with

`NODE_ENV=<env> ENVIRONMENT=<env> node ./node_modules/@livingdocs/server/db/manual-migrations/002-write-content-type.js`

Updated Elasticsearch mapping

The contentType was added to the documents index.

To update the mapping run:

grunt search-index:document:update-mapping
grunt search-index:document

Server Configuration

Channel Configuration

Example Channel Configuration in the new format:

projects: {

    // Example static channel configurations
    channelConfigurations: [{
      // If a channel has the channel `name` 'web' the channel configuration with
      // the `handle` 'web' will be used.
      handle: 'web',
      editMode: 'default',

      copy: [{
        source: {
          channelHandle: 'web',
          // If a design contains a layout gallery the content type is 'gallery'
          contentType: 'gallery'
        targets: [{
          channelHandle: 'web',
          contentType: 'gallery'

      // Content Types
      contentTypes: [{
        handle: 'gallery',
        documentType: 'article',

        metadata: {},
        renditions: require.resolve('./path/to/rendition/config')

Rendition Configuration

The format is exactly the same as before, it just must be in a different file as it contains code and is not really a configuration:

const CheerioHtml = require('../../../lib/render-pipeline/output/cheerio_html')

module.exports = {
  'web': {
    output: {
      'page-html': new CheerioHtml()

Copy Configuration

An example of the new copy configuration with contentTypes instead of layouts:

  channelConfigurations [
    copy: [{
      source: {
        // 'channelHandle' instead of 'design'
        channelHandle: 'web',
        // 'contentType' instead of 'layout'
        contentType: 'regular'
      // 'targets' instead of 'target'
      targets: [
        channelHandle: 'print',
        contentType: 'regular'
        // ...other properties remain the same

Public Api

GET public-api/v1/project

Changed return value with the contentTypes (array of contentType which contains configuration e.g. metadata) in the response -> See the public api docs for details ( <livingdocs-host>/public-api.html#/public-api.html)

GET public-api/v1/channels/:channelHandle

Modified return value. This is exactly the same as one channel in the project response. (there is also a schema: LivingdocsPublicChannel) -> See the public api docs for details ( <livingdocs-host>/public-api.html#/public-api.html)

GET public-api/v1/documents/…

content_type is now included in the response -> See the public api docs for details ( <livingdocs-host>/public-api.html#/public-api.html)

Editing Api

GET /documents

content_type is now included in the response content_type can be used in fields (GET /documents?fields=content_type) content_type can be used as a filter (GET /documents?content_type=article)

GET /project

New channel configuration is included in the response

Feature Apis


content_type is required. It will be verified, that the content_type exists. = content_type document_type is set as before. It uses the document_type defined in the specified content_type config.


-> requires contentType param instead of layout


New return value:

  channelHandle: 'web'
  contentType: 'article'
}, {
  channelHandle: 'web'
  contentType: 'minimal'
}, {
  channelHandle: 'print'
  contentType: 'default'


Changes in features.api('li-projects').channel:

  • Changed: channelApi.getRenderConfigForRenderWorker -> new required param contentType
  • Removed: channelApi.getChannelsWithLayoutsByProject
  • Removed: channelApi.getDocumentTypeConfig
  • Removed: channelApi.getPageConfig
  • Removed: channelApi.getArticleConfig
  • Removed: channelApi.getChannelConfigByChannelName


  • projectsApi.getProject

New return value:

  id: 1,
  projectHandle: 'project-handle',
  name: 'project-handle', // deprecated
  defaultChannelId: 10, // previous: default_channel_id
  config: {},
  channels: [{
    channelHandle: 'web', // previous: name
    designName: 'timeline', // previous: design_name
    designVersion: '1.0.0', // previous: current_version
    availableVersions: [], // previous: available_versions
    disabledVersions: [], // previous: disabled_versions
    editMode: 'default', // previous: mode
    copySources: [ // previous: copy_cource_channels
      {channelHandle: 'web', contentType: 'article'}
      {channelHandle: 'web', contentType: 'minimal'}
    contentTypes: [...], // new
    pushNotifications: {...} // new


  • channels[0].config
    • channel.config.articles.copy_source_channels
    • channel.config.articles.available_versions
    • channel.config.articles.disabled_versions

Previous value for copy_source_channels:

copy_cource_channels = [
  {design: 'basic', layout: 'default'}
  {design: 'basic', layout: 'minimal'}



documentType got replaced with contentType in the beforeRenderHook

  # before
  const renderPipeline = liServer.features.api('li-render-pipeline')
    projectHandle: 'my-project',
    channelHandle: 'web',
    beforeRenderHook: ({documentType, rendition}, callback) => {
      liServer.log.warn(`Hook called for documentType: ${documentType}!`)
      callback(null, rendition)
  }, done)

  # after
  const renderPipeline = liServer.features.api('li-render-pipeline')
    projectHandle: 'my-project',
    channelHandle: 'web',
    beforeRenderHook: ({contentType, rendition}, callback) => {
      liServer.log.warn(`Hook called for contentType: ${contentType}!`)
      callback(null, rendition)
  }, done)


// pass `importJob.contentType` instead of `importJob.documentType` the passed layout
// will be ignored (should we implement that backwards compatible?)

  importJob, rawDocument, shouldCreateNew, updateCondition, userId
}, callback)

Server PR #1696

Content Types - Editor πŸ”₯

Breaking Change The editor depends on the server >= 66.0.0 Make sure all users refresh their session after the new editor is deployed.

The editor consumes contentTypes from the server through the channel configuration. The create new document Dialog shows the information from the contentType configuration. But the groups and defaultContent configuration are still loaded from the layouts in the design.

There is a new filter with type contentType that can be used in the dashboard or document searches.

Editor PR #1759

Allow to replace an image by an image drop 🎁

When dragging an image from the file system over an image in the editor the image will replace said image.

Editor PR #1796

Improved document history 🎁 πŸ”₯

Editing Api

PUT /documents/:id

New param force_new_revision to force the creation of a new revision (we use that in the editor in the case a user restores an old version in the history)

GET /revisions

Mark on the revision (list) if a revision was created because a user published the document. The response will contain an event field that can read publish or be null (for edit).

The /revisions endpoint previously didn’t require passing a document_id. This is now mandatory since the endpoint makes no sense without a document_id.

History UI

The new document history aims at making the history faster and easier to navigate.

We introduce a small section at the top that shows who has edited a document and a small activity section with a line graph of number of revisions over days and total revisions due to publish and edit changes.

The main section of the history is still segmented by day. In addition each day is then also segmented by user, so if a user made many changes in a day (a common use case) you first see that this user made x changes in time a to b and then can open the entries section to drill deeper.

We also introduced the restore functionality. You can now restore any old revision. The exception is revisions with an outdated design. Those can still be seen but due to the possibility of conflicts in the design versions, can not be restored.

Server PR #1762

Editor PR #1174

Extended design loader configurations 🎁 πŸ”₯

The Design Loader gets its own configuration:

designLoader: {
  hostedDesigns: [{ // optional
    designName: 'timeline',
    url: ''
  localDesigns: [{ // optional
    path: '/designs/timeline/v1.1.0' // path to design
  designRepository: { // optional, defaults to the local design server
    remoteHost: ''
  cacheSize: 100 // defaults to '20'

For details see the detailed changelog in the Server PR #1787

Removed designLoader module in the editor πŸ”₯ πŸ”§

Breaking Change The module designLoader was removed. Use designProxy instead. It offers the same api.

From now on the editor always requests the design from the Livingdocs Server it points to. The design is proxied through the server in case the server is configured with a different design server. This solves a few inconsistencies as previously it was possible to load a different design than the one that was cached on the server.

Editor PR #1803

Mark list that have pending changes with a blue dot 🎁

In the editor lists screen a blue circle is shown for lists with pending changes.

In the server the documentListApi returns the inbox size of every list.

Editor PR #1792 Server PR #1776

Fix the behaviour of read-only mode during collaboration πŸͺ²

Editor PR #1791

Other Changes

Icon Legend

  • Breaking changes: πŸ”₯
  • Feature: 🎁
  • Bugfix: πŸͺ²
  • Chore: πŸ”§