How to Use Sitecore Placeholders to Create a Reusable Next.js Container

Provide your Sitecore authors with advanced containers that are customizable on a per component level

March 19, 2024

By Tyler Holmes

This guide will teach you how to create a fully customizable React Container inside Sitecore using Placeholders. This will provide you with an easy way to organize your renderings into sections within the Sitecore Experience Editor. You'll learn how to efficiently restrict which components your authors can use inside each container, enabling you to create custom containers for specific components.

1. Next.js: Create Container.tsx

First, we need to create a new .tsx file that we will use for our Placeholder. This container file will be where you make your container wide style changes. I'm going to name mine Container.tsx to keep it simple, but other common container styles are Grid and Full/Half width containers.

Screenshot showing code files named 'Container.tsx' and 'Container100.tsx' in a development IDE

Inside our new .tsx file, we want to add our container <div> which will hold whatever styles you want your container to have. You can leave the div empty (like I am in this example), or you can configure it to use CSS Grid or Flex-Box. *Note: I've also added a data-component="container" to my div. This can be used to more easily debug when looking at an issue in production, allowing you to quickly differentiate between components.*

import React from 'react';
    import { ComponentParams, ComponentRendering } from '@sitecore-jss/sitecore-jss-nextjs';
<span class="hljs-keyword">const</span> Container = <span class="hljs-function">(<span class="hljs-params">props: ContainerProps</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag"><span class="hljs-tag">&lt;</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">div</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">data-component</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"container"</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">className</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">''</span></span></span></span></span></span></span><span class="hljs-tag">&gt;</span></span>

    <span class="hljs-tag"><span class="hljs-tag">&lt;/</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">div</span></span></span></span></span></span></span><span class="hljs-tag">&gt;</span></span></span>
  );
};

<span class="hljs-comment">//Types</span>
type ContainerProps = {
  <span class="hljs-attr">rendering</span>: ComponentRendering &amp; { <span class="hljs-attr">params</span>: ComponentParams };
  params: ComponentParams;
};
</code></pre>

2. Sitecore: Create a New Rendering

The next step requires us to create a new Rendering Item for our container in Sitecore. To do this, we want to find an existing Rendering Item, right click → Scripts → Clone Rendering. You can clone any rendering and turn it into a container.

Dropdown menu in Sitecore with various editing options including 'Refresh' and 'Clone Rendering'

Next, we want to update the information for our new rendering. Under the “General” tab, we only need to update the name. Under “Parameters” and “Datasource” it's important to select “Make a Copy”.

Interface for adding a new rendering name and selecting the module location

Don't forget to update the Component Name on your new rendering to match your .tsx file.

Text field for entering a shared component name 'Container'

After updating your Component Name, scroll down to Other Properties and make sure that there is a value of IsRenderingsWithDynamicPlaceholders set to true.

Property setting for 'IsRenderingsWithDynamicPlaceholders' set to true

To keep all your new containers organized, and to make it accessible inside the Sitecore Experience Editor, we can create a new Category under “Available Renderings” named Containers. We can use this for all our future container types.

Context menu showing an 'Insert' option pointing to 'Available Renderings'

After adding our new “Available Renderings”, we can click “edit” and add our new Container rendering by double-clicking on it.

Dialog box for selecting items with 'Container' moved to the selected column

3. Sitecore: Create a New Placeholder

Next, we want to configure our new rendering to work as a placeholder. First, you want to find your new item’s “Rendering Parameters”, and add IDynamicPlaceholderto the "Base Template".  You will be able to find the “Rendering Parameters” under/sitecore/templates.

You can find IDynamicPlaceholder under Foundation/Experience Accelerator/Dynamic Placeholders/Rendering Parameters.

Sitecore interface showing the process of selecting the 'IDynamicPlaceholder' for a container

Scroll back up and open “Layout”. You want to open up the “Placeholder Settings” folder and insert a new placeholder under “Feature”. Give the new placeholder the same name as your Container Rendering. Path: Layout/Placeholder Settings/Feature

Sitecore navigation pane with an arrow indicating the action to insert a new placeholder

The important part, is to ensure you update the “Placeholder Key”. This is what we will use in our .tsx file to help Sitecore link our component to our placeholder. Enter the name of your rendering followed by -{*}.

Note: Every placeholder you make should have a unique placeholder key.

Screenshot of a user interface showing placeholder key settings with the text 'container-{*}

Finally, return to your original rendering item that we created in step 2. Scroll down to the “Layout Service” sections and find the placeholder you just created.

Screenshot of a layout service interface with selectable containers in a web development environment

Add the placeholder details to the container .tsx

Next, we want to import the <Placeholder/> component from sitecore-jss-nextjs, and create a placeholder key that matches our Placeholder configuration in Sitecore. We can then pass down our key value, and the props rendering value, directly into the <Placeholder/> container.

import {ComponentParams, ComponentRendering, Placeholder } from '@sitecore-jss/sitecore-jss-nextjs';
<span class="hljs-keyword">const</span> Container = <span class="hljs-function">(<span class="hljs-params">props: ContainerProps</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> phKey = <span class="hljs-string">`container-<span class="hljs-subst">${props.params?.DynamicPlaceholderId}</span>`</span>;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag"><span class="hljs-tag">&lt;</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">div</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">data-component</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">"container"</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">className</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">""</span></span></span></span></span></span></span><span class="hljs-tag">&gt;</span></span>
      <span class="hljs-tag"><span class="hljs-tag">&lt;</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">Placeholder</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">name</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">{phKey}</span></span></span></span></span></span></span><span class="hljs-tag"> </span><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr"><span class="hljs-tag"><span class="hljs-attr">rendering</span></span></span></span></span></span></span><span class="hljs-tag">=</span><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string"><span class="hljs-tag"><span class="hljs-string">{props.rendering}</span></span></span></span></span></span></span><span class="hljs-tag"> /&gt;</span></span>
    <span class="hljs-tag"><span class="hljs-tag">&lt;/</span><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name"><span class="hljs-tag"><span class="hljs-name">div</span></span></span></span></span></span></span><span class="hljs-tag">&gt;</span></span>
  );
};</span>
</code></pre>

5. Sitecore: Restricting Which Components Can Be Used Inside Your Placeholder (Optional)

There is a chance that you want to restrict the renderings that your authors can place inside a container. By default, Sitecore allows all renderings to be used within your placeholder; however, it's extremely simple to restrict the accepted renderings. Simply return to the placeholder that we created in step 4 under Layout/Placeholder Settings/Feature and scroll down to the “Allowed Controls” section. Once opened, you are able to selectively choose which renderings you want to allow inside your new placeholder.

User interface displaying an edit button with arrows pointing to the selected option 'Classic Banner'

Now You’re a Container Master!

Now, you know how to create custom Next.js containers by utilizing Sitecore Placeholders. Containers can be extremely versatile and used in a large variety of ways. A common approach is creating a Bento Box-style Grid container, enabling your authors to construct a custom grid layout on any page!



Tyler Holmes

Full Stack Developer

Tyler is an experienced Full Stack Developer who has worked on a plethora of unique projects. He possesses a deep understanding of Technical SEO, C#, and React/Next.js.

Second CTA Ogilvy's Legacy

Today, David Ogilvy's influence can still be felt in the world of advertising.

Ogilvy's Influence Example
Emphasis on research Market research is a crucial part of any successful advertising campaign
Focus on headlines A strong headline can make the difference between an ad that is noticed and one that is ignored
Use of visuals Compelling images and graphics are essential for capturing audience attention