Sitemaps & Feeds

Added in: release-2021-06

Sitemaps

The livingdocs-server ships with a set of APIs to automatically create sitemaps. The full (public) API specification can be found in our public API documentation at https://edit.livingdocs.io/public-api

This guide will focus on the setup of Sitemaps within a delivery and the downstream customizations that need to be done to set up Feeds.

We provide a running minimal delivery, in the “Live Delivery Setup” section

Robots.txt

You will need to link the Sitemap and Feed in the robots.txt of your delivery

Sitemap: https://www.livingdocs.io/sitemap.xml
Sitemap: https://www.livingdocs.io/feed.xml

Sitemap index

The Sitemap index points to individual months, that contain all the actual entries of a Sitemap. Several Sitemaps for various content types could be created if they are individually linked in the robots.txt file.

Sitemap entries

The Sitemap entries follow the schema sitemap.YYYY-MM.xml or if it has more than the suggested limit of entries it will be split into a separate file such as sitemap.YYYY-MM.2.xml. We suggest keeping the limits the livingdocs API provides.

Feeds

Feeds are highly customizable and no there is no ‘one-fits-it-all’ solution. We will still outline a way to integrate Feeds using one of our helper methods for Feeds that builds upon the RSS 2.0 Specification

Server Downstream You will need to add your own HTTP-API.

// Register the feature
liServer.features.register('feeds', require('./feeds'))
// Setup the Feature - ./feeds/index.js
module.exports = function (feature, server) {
  const searchManager = server.features.api('li-search').searchManager
  const sitemapsApi = server.features.api('li-sitemaps')

  const feedsApi = require('./feeds_api')({
    searchManager,
    sitemapsApi
  })

  const controller = require('./feeds_controller')({feedsApi})
  const routes = require('./feeds_routes')

  feature.registerResource({controller, routes})
}
// Setup the Feature - ./feeds/feeds_routes.js
module.exports = {
  title: 'RSS Feeds',
  description: 'Feed endpoints',
  endpoints: [{
    path: 'custom/api/v1/feed',
    auth: 'public-api:read',
    method: 'get',
    action: 'getFeed'
  }]
}
// Setup the Feature - ./feeds/feeds_controller.js
module.exports = ({feedsApi}) => {
  return {
    async getFeed (req, res) {
      const {channelId, projectId} = req.verifiedToken
      const feed = await feedsApi.getFeed({channelId, projectId})
      return res.success(feed)
    }
  }
}
// Setup the Feature - ./feeds/feeds_api.js
module.exports = ({searchManager, sitemapsApi}) => {
  return {
    async getFeed ({projectId, channelId}) {
      // gather the latest published documents with the 'article' contentType
      const res = await searchManager.searchPublications({
        projectId: projectId,
        channelId: channelId,
        contentTypes: ['article']
      })
      // render the XML
      const xml = sitemapsApi.renderFeedXml({
        title: 'Feed title',
        description: 'Feed description',
        language: 'de',
        copyright: 'Feed copyright',
        link: 'https://livingdocs.io/',
        pubDate: res.results[0]?.createdAt,
        lastBuildDate: new Date(),
        image: {
          url: 'https://example.com/foo',
          title: 'image title',
          description: 'image description',
          link: 'https://example.com/foo',
          width: '144',
          height: '400'
        },
        items: res.results.map((doc) => {
          return {
            title: 'document title',
            description: 'document description',
            pubDate: doc.createdAt,
            link: `https://livingdocs.io/article/${doc.documentId}`
          }
        })
      })
      return xml
    }
  }
}

Result Note: This still result still needs to be consumed in the delivery, similar to the already implemented examples in the live delivery example in the next section.

<!-- example payload of the new downstream Feeds endpoint -->
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
  <title>Feed title</title>
  <description>Alle Artikel von Livingdocs</description>
  <language>de</language>
  <copyright>copy-foo-right</copyright>
  <image>
    <url>https://example.com/foo-image</url>
    <title>foo-image-title</title>
    <description>some description for this image</description>
    <link>https://example.com/foo-image</link>
    <width>144</width>
    <height>400</height>
  </image>
  <pubDate>Wed, 19 May 2021 14:55:06 GMT</pubDate>
  <lastBuildDate>Wed, 19 May 2021 14:55:06 GMT</lastBuildDate>
  <link>https://livingdocs.io/</link>
  <item>
    <title>foo item title</title>
    <description>foo item description</description>
    <link>https://livingdocs.io/article/1</link>
    <pubDate>Tue, 01 Jan 2030 00:00:00 GMT</pubDate>
  </item>
</channel>
</rss>

Live Delivery Setup

This live demo of a minimal delivery runs against a real livingdocs instance.

You can explore the following routes in the example

  • /robots.txt
  • /sitemap.xml
  • /sitemap.2021-06.xml
  • /feed.xml

Interactive minimal delivery example