Sitecore Layout Service and Rendering Contents Resolvers

When developing JSS or.NET Core headless solutions, one of the key components is the Layout Service. The Layout Service composes and serves a JSON description of the context, route, placeholders, renderings (components), and datasources that can be used to populate the data which the rendering engine uses to render the final UI of the application. The Layout service is part of Sitecore Headless Services (previously known as JSS Server Components) and powers both JSS and the newer .NET Core headless rendering approaches. You can find out more about the Layout Service here.

In this post we’ll look at the Layout Service payload and at how Sitecore uses a Rendering Contents Resolver to determine the contents and structure of the component rendering data returned via the Layout Service. In a subsequent post we will look at why and how we might extend a Rendering Contents Resolver to suit our needs.

The Rendering Contents Resolver is not the only way to return rendering data to the API – you can also use GraphQL, however that will be the topic of a future post.

Layout Service data

Sitecore Headless Services can be used to expose endpoints that return Sitecore route data as JSON, but you need to create and configure a Sitecore Services Client (SSC) API key in order to query it. For details on how to create an SSC API key, see section 2 of this page. Once created, don’t forget to publish your API key if you are using the API endpoint to query the Web database.

The Layout Service API call has the following structure:

https://[siteUrl]/sitecore/api/layout/render/jss?item=[item ID or sitecore path]&sc_apikey=[your api key]

For example:

https://sc10.sc.dev.local/sitecore/api/layout/render/jss?item=/&sc_apikey={6369DDCB-6A77-439F-8A73-C47496DA1CEE}

or

https://sc10.sc.dev.local/sitecore/api/layout/render/jss?item={66C56C12-F526-4E61-9D75-D76895AC2587}&sc_apikey={6369DDCB-6A77-439F-8A73-C47496DA1CEE}

In the first example above the API will return the Layout Service representation of the site root (since we’ve provided the path “/” ). In the second example it will return the layout for a specific item ID (in this case it’s the Blog Home route). You don’t actually have to use curly braces {} to wrap the ID nor the hyphen in the ID – it will work without them. i.e. jss?item=66C56C12F5264E619D75D76895AC2587&sc_apikey=6369DDCB6A77439F8A73C47496DA1CEE will work just the same.

Let’s look at the JSON output:

In the example above, the layout service represents a route called Blog in the context of the jss-demo site and we can see the item Name (Blog), ID, and a few other properties such as databaseName (in this case it’s the Sitecore master database.)

The root of the JSON contains the context and the route data:

Looking at the route, we can see it contains route-level fields such as pageContent, pageTitle, as well as item name, version, ID, etc:

Basically this is all the stuff you’d expect see about the item, although quite a lot has been filtered out for us already, since we don’t want to send ALL the item data down the pipe in the JSON because that would (a) increase the size of the JSON payload, and (b) expose a lot of irrelevant data or data that should be hidden from the browser. I’m using JSS on top of SXA, so the Page Design field has been returned as well, however there isn’t a page design applied currently.

Within the route, we can also see 3 placeholders:

  • jss-demo-ph-content
  • jss-demo-ph-content
  • jss-demo-ph-content

Each placeholder can contain an array of zero or more renderings (aka “components” in JSS terminology.)

In this case, only one of these placeholders has been populated (jss-demo-ph-content). That placeholder contains a rendering “Blog Promo” which has a datasource {621726E6-4D0C-4C4E-9081-44A874C98A38} that represents a blog article:

As we can see, the fields on the datasource have been serialised and returned in the Layout Service data, as well as the (currently empty) params object which would contain rendering parameters if populated. Back on the Sitecore server the datasource item has been retrieved and serialised for us to use in the rendering engine. This is where the Rendering Contents Resolver fits in.

Note that you can return whatever JSON data you like as component rendering data, but the structure above is what the default serialised item data looks like.

Rendering Contents Resolvers

Out of the box, Sitecore Headless Services provides 6 resolvers, and these are in sitecore/System/Modules/Layout Service/Rendering Contents Resolvers

The default resolver is the Datasource Resolver which, as the name suggests, serializes the datasource item.

The various OOTB resolvers are summarised below

ResolverFunction
Context Item Children ResolverSerializes the children of the context item
Context Item ResolverSerializes the context item
Datasource Item Children ResolverSerializes the children of the datasource item
Datasource ResolverSerializes the datasource item
Folder Filter ResolverSerializes the descendants of the datasource item, excluding folders
Sitecore Forms ResolverRetrieves and serializes a Sitecore Form and its associated items
Rendering Contents Resolvers included with Sitecore Headless Services

[tip of the hat to Gary Wenneker who covered this a while ago]

It is important to note however, that although the default is the Datasource Resolver, it only uses the resolver code with default properties and does not reference the actual Datasource Resolver item. Therefore if you change the properties of the Datasource Resolver item in the Layout Service/Rendering Contents Resolvers section of the tree it will have no effect on your rendering output unless you go into the rendering settings and set the value for Rendering Contents Resolver as per below:

All of the resolvers above (except Sitecore Forms Resolver) use exactly the same code, just with some properties passed in that define what to retrieve and how to serialize it. The type is: Sitecore.LayoutService.ItemRendering.ContentsResolvers which is in the Sitecore.LayoutService assembly.

The properties that can be set are:

Type: the .NET type that retrieves and serialises the output. As is usual with Sitecore, you can create your own, which we will cover the in my next post.

Include Server URL in Media URLs: Fairly self explanatory, fully qualifies the URL for the media item src.

Use Context Item: retrieves the context item instead of the datasource item. You might want to use this to populate route level data into a rendering (e.g. for route metadata values perhaps, although you could do this client side without needing to set this value.) In the code, there is a not very well named method GetContextItem(rendering, renderingConfig) which will return the context item if this property is true, otherwise it will do a GetItem on the datasource item (if one has been provided).

Item Selector Query: Sitecore query to select and filter items for inclusion in the rendering data

All of the above will cover simple rendering data requirements, but there may be situations where it is preferable to modify the structure and the contents of the data returned to a rendering. In my next post I will look at extending the OOTB resolver code and why this might be useful.

[The code and content for this post and the subsequent one are on Github]