⚡ Unlock faster workflows with Prismic’s newest features!See what's new and upcoming
Performance & UX
·10 min read

How to Implement a Scalable CMS with Slices

This is the second guide in a series teaching you the easiest way to add a content management system (CMS) to a Next.js app.

In the first guide, you learned how to create a new Next.js app, set up a CMS using Prismic, and connect your CMS to the app. You now have a good foundation on which you can further build your CMS and Next.js skills. If you haven’t gone through the first guide yet, check that one out first since this guide builds upon the work you’ll do there.

Want to skip the first guide?

If you want to skip the first guide, you can start with the prepared app using the following commands:

npx degit prismicio-community/easiest-way-to-add-cms-nextjs scalable-cms-tutorial
cd scalable-cms-tutorial
npx @slicemachine/init

The commands will do the following:

1. Start a new Next.js project with the prepared code.
2. Ask you to log in to Prismic or create an account.
3. Create a new Prismic content repository with sample content.

In this guide, you’re going to take your CMS-powered Next.js app and make it scalable. 🏗️  You’ll learn how and why modern agencies and companies build their websites using Prismic.

Before you jump back into the app, let’s first define what we’re aiming for.

What is a scalable app, and how can you build one?

A scalable CMS-powered Next.js app has the following attributes:

  • It allows content writers to create and update pages on their time.
  • Its content is always visually on-brand, without the need for a designer’s or developer’s constant involvement.
  • It lets developers focus more on implementing new features and optimizations and less on mundane maintenance and repetitive tasks.
  • It is architected to reduce development time for sites of any size.

You can accomplish all of this through Prismic’s killer feature: Slices. They are sections of a page that can be reused as many times as needed, each with their own content. Slices bring the component-based workflow that enables efficient website development to the content editing world. You — and your content team — are going to love it.

Through this guide, you’re going to enhance your app by doing the following:

Let’s get started!

1. Create Slices

You’ll begin by making some changes to the CMS you set up in the previous guide.

The app’s home page currently shows two fields from the CMS: a greeting and a description. These fields will be replaced with a single Slice that allows content writers to add any text they want as they create new pages. To make it obvious to writers what the Slice does, you’ll name it “Text.” A writer will be able to add a Text Slice any time text is needed on a page.

You’re also going to create a Slice for the collection of links below the description, something that wasn’t editable in the last guide. You’ll name this Slice “LinkCards” to make the Slice’s contents and design obvious to writers.

With these two Slices, content writers will be able to add Text and LinkCard Slices as many times as they want and in any order they want. Adding text below the collection of links, for example, is just one Text Slice away. A content writer can add it themselves without the need for you to edit the page’s code.

(By the way, we’re keeping this simple so you can focus on learning, but can you imagine if content teams had their own “Call to Action” Slices? Or “Image Gallery” Slices?)

A screenshot of the home page of a Next.js app that reads, "Bonjour!" thanks to the previous tutorial in this series.

To begin, start Slice Machine by running the following terminal command in the root directory of your project. As a reminder, Slice Machine is a tool you run locally to configure your Prismic CMS.

npm run slicemachine

Once the server starts, open Slice Machine by going to http://localhost:9999 in your browser. With Slice Machine running, you can create your first Slice.

1.1. Add a Slice for text context

Your first Slice will allow content writers to add text to a page. They will be able to add as many of these Slices as they want and will support special formatting like headings, lists, and more.

To create your first Slice in Slice Machine, follow these steps:

  1. Click on Slices in the sidebar.
  2. Under "What are Slices," click the purple Create one button.
  3. Name the Slice “Text” when prompted and click Create.
A screenshot of the Slice Machine interface on the Slices tab before any Slices have been created. The headline text reads, "Create your first Slice."

On the next screen, you’ll see that a Slice has two sections for content fields:

  • “Non-repeatable Zone”: This section is for most content that will be used once in the Slice, such as a piece of text or a background image.
  • “Repeatable Zone”: This section allows content writers to add the same element multiple times, which is useful for things like a collection of links or images.

You’ll only use the “Non-Repeatable zone” for your Text Slice. You’ll learn how to use the “Repeatable zone” in the next Slice.

A screenshot of the Slice Machine interface where a new Text Slice is being created. It has two default fields upon creation.

Here’s how to set up your Text Slice:

  1. Your Slice will have two fields in the “Non-repeatable zone” by default: a Title and a Description field. You won’t need either of them, so they can be deleted. Click the “…” button and select Delete field for each field.
  2. Click Add a new field in the “Non-repeatable Zone” and select a Rich Text field.
  3. Enter "Text" as the field’s name and hit Enter.
  4. Editors will likely want to write multiple paragraphs of text, so you’ll need to enable that in the field’s settings. Click the field’s pencil icon, check “Allow multiple paragraphs,” and click Save.
  5. Click the Save to File System button in the top right corner.
  6. Your Slice is now saved locally, but you also need to push it up to your Prismic repository. Once you’re ready, click the Changes tab in the sidebar and click the Push Changes button to send it to your repository.
A screenshot of the Slice Machine interface where a new Text Slice with one field is in the process of being created.

Congratulations! You just built your first Slice! It’s simple, but it will allow you and your content team to add and edit text content throughout your app with ease.

Now on to building your second Slice.

Your second Slice will allow content writers to add a collection of links to a page with a card-like design. Like the Text Slice, they will be able to add as many of these Slices as they want. And because Slices are modular, content writers can add them in any order and as often as needed.

To create your second Slice in Slice Machine, follow these steps:

  1. Click on Slices in the sidebar.
  2. Click the Create a Slice button in the top right corner to create a new Slice.
  3. Name the Slice “LinkCards” when prompted and click Create.
A screenshot of the Slice Machine editing interface where a LinkCards Slice is being created. There are default fields that will need to be deleted.

This time, you’re going to add fields to the "Repeatable zone." The Slice will display a collection of links, so content writers will need the ability to “repeat” the fields you give them.

Continue creating your LinkCards Slice by adding your fields:

  1. Delete the Title and Description fields in the "Non-Repeatable zone," just like with the Text Slice.
  2. Click Add a new field in the "Repeatable zone" and select a "Key Text" field. This type of field holds plain text with no formatting like headings or bold text.
  3. Name the field "Name" and hit Enter. This field will be used as the link’s label.
  4. Add a "Rich Text" field named "Description". This field will let content writers add a short sentence below the link’s name.
  5. Add a "Link" field named "Link". This field will hold the URL for the link card.
  6. Click the Save to File System button in the top right corner.
  7. Click the Changes tab in the sidebar and click the Push Changes button to send it to your repository.
A screenshot of the Slice Machine editing interface where a new LinkCard Slice is being created. Now the Slice has three fields in the "Repeatable zone."

Nice! You just built your second Slice! This one is a little more complex than the Text Slice; it has multiple fields and lets content writers “repeat” the fields as needed.

Next, you’ll need to connect these Slices to your Page Custom Type.

1.3. Add the Slices to your Custom Type

To allow content writers to use your new Slices, you first need to add them to your "Page" Custom Type.

To add the Slices to the "Page" Custom Type, follow these steps:

  1. Click on Custom Types in the sidebar and select the “Page” Custom Type.
  2. In the “Slice Zone” section, click the Add a new Slice button.
  3. You’ll see your Text and LinkCards Slices appear as options. Check the box next to each Slice and click Save.
  4. Click the Save to File System button in the top right corner.
  5. Click the Changes tab in the sidebar and click the Push Changes button to send it to your repository.
A screenshot of the Slice Machine editing interface, where new Slices are being added to a new Custom Type.

The Slices are now available for content writers to add to pages. They don’t yet have a way of displaying themselves in your app, however. Luckily, Slice Machine has secretly been doing some of the setup work for you in the background.

2. Display the Slices in your Next.js app

Your next step is to connect your Slices from Prismic to your Next.js app. Slice Machine has already created some files in your app to do this.

2.1. Create React components for each Slice

Look in the slices directory in your project and you’ll find a Text and LinkCards directory. These are named just like the Slices you created. Each directory contains an index.js file with a React component that will be rendered anytime a content writer adds its Slice to a page.

Replace the contents of each index.js file with the code given below. Notice how the React components use the slice prop to read the fields you created. The components also use @prismicio/react to render content from the Slices.

For your Text Slice:

// slices/Text/index.js

import { PrismicRichText } from '@prismicio/react'
import styles from '../../styles/Home.module.css'

const Text = ({ slice }) => (
  <section className={styles.description}>
    <PrismicRichText
      field={slice.primary.text}
      components={{
        heading1: ({ children }) => (
          <h1 className={styles.title}>{children}</h1>
        ),
      }}
    />
  </section>
)

export default Text

For your LinkCards Slice:

// slices/LinkCards/index.js

import { PrismicRichText, PrismicLink } from '@prismicio/react'
import styles from '../../styles/Home.module.css'

const LinkCards = ({ slice }) => (
  <section className={styles.grid}>
    {slice.items.map((item) => (
      <PrismicLink
        key={item.link.url}
        field={item.link}
        className={styles.card}
      >
        <h2>{item.name} &rarr;</h2>
        <PrismicRichText field={item.description} />
      </PrismicLink>
    ))}
  </section>
)

export default LinkCards

2.2. Update your page component to render Slices

Your app already has a pages/index.js file that displays content from Prismic. It doesn’t display the Slices you just created, however.

To do that, first import the <SliceZone> component from @prismicio/react at the top of your file:

// pages/index.js, top of the file

import { PrismicText, PrismicRichText, SliceZone } from '@prismicio/react'

Next, import your Slices’ React components. Slice Machine automatically exports them as a nice, single object in slices/index.js which works great with <SliceZone>. Add the following import at the top of your file:

// pages/index.js, top of the file

import { components } from '../slices'

Lastly, you need to use <SliceZone> to render your Slices. Delete everything in the <main> element around line 17 and replace it with the following code:

// pages/index.js, around line 17

<main className={styles.main}>
  <h1 className={styles.title}>
    <PrismicText field={page.data.greeting} />
  </h1>

  <div className={styles.description}>
    <PrismicRichText field={page.data.description} />
  </div>

  <SliceZone
    slices={page.data.slices}
    components={components}
  />
</main>

The <SliceZone> component will read the page’s Slices and render the appropriate React component.

Your page is now set up to display Slices! To see if it all works, hop over to your Prismic repository to write content — this time with Slices.

3. Write content with Slices

Writing content is done within your Prismic repository at https://prismic.io/dashboard/. Log in, if needed, and select the repository you created in the previous guide.

Once in your repository, update your content to use Slices by following these steps:

  1. Open the Page document you created last time you were in Prismic.
  2. Below the “UID” field, you’ll see your Text and LinkCards Slices as options. Select a Text Slice.
  3. Enter some content into the “Text” field. This text will appear at the top of your page.
  4. Add a second Slice by clicking the + button below the Text Slice you just added. Select a LinkCards Slice this time.
  5. Fill out the Name, Description, and Link fields for your first link card. Then add another link card by clicking the Add a new element in Group button and filling out the fields again. These links will appear below the Text Slice.
  6. Once everything looks good, click the Save button in the top right corner. Then click the Publish button in the same location and Publish again in the drawer that slides into view.
A screenshot of the Prismic editing interface with a new page document being created. The headline will read, "Bonjour!"

You just leveled up your homepage by using Slices to manage its content!

Test out your site by loading your Next.js app in your browser. If you haven’t already started your Next.js app, you can do so with the following terminal command in your app’s root directory:

npm run dev

Once the server is running, open http://localhost:3000. You should see your new content on the page rendered using Slices.

A screenshot of a plain web page with a headline that reads, "Bonjour!"

So what was all that work for? Now you (or your content writers) can add as many Text or Link Card Slices as you want! Try it out by going back into Prismic, adding more Text and Link Card Slices (don’t forget to publish your changes!), and refreshing your homepage.

There’s just one last piece to add before your Next.js app is truly scalable: allowing content writers to create their own pages.

4. Enable content writers to create pages

Your app currently only has one page: its homepage. What if you or your content writers want to create more pages using your Slices? You really only need to change a couple of things in your app to support this. Everything you’ve done so far was made with content scalability in mind. 🧠

Here’s how to enable content writers to create pages:

  1. Rename pages/index.js to pages/[[...path]].js. This lets you read the URL’s path to fetch the correct "Page" document from Prismic. It uses a Next.js “catch all” Dynamic Route.
  2. Replace the getStaticProps() function at the bottom of pages/[[...path]].js with the following code. Be sure to include the new getStaticPaths() function. If you want to understand what the code does, read the comments throughout the functions.
// pages/[[...path]].js, bottom of the file

// This function fetches the Page document from the CMS.
// The document is passed to the page as a prop.
export async function getStaticProps({ params }) {
  // Client used to fetch CMS content.
  const client = createClient();

  // Page document from the CMS.
  const uid = params.path?.[params.path?.length - 1] || "home";
  const page = await client.getByUID("page", uid);

  // Pass the document as prop to our page.
  return {
    props: { page },
  };
}

// This function tells Next.js which URLs to accept.
// Each Page document from the CMS will be given a URL.
export async function getStaticPaths() {
  // Client used to fetch CMS content.
  const client = createClient();

  // Page documents from the CMS.
  const pages = await client.getAllByType("page");

  // URL paths for each Page document from the CMS.
  return {
    paths: pages.map((page) => ({
      params: {
        path: page.uid === "home" ? [] : [page.uid],
      },
    })),
    fallback: false,
  };
}

With this in place, you can create new "Page" documents in Prismic with their own URLs based on their UIDs. If you create a Page document with a UID of about, for example, you’ll be able to see it at http://localhost:3000/about. Try it out!

A screenshot of a plain web page where the headline reads, "About Us."

Wrap up

Congrats! 🎉 You just upgraded your Next.js app to scale and grow with your team.

When new content is needed, writers can go into the CMS and write with Slices without worrying about design or technical details. When they need new pages, they can create them themselves. And when they need to display a new style of content, you only need to develop a single Slice, not a whole new page. This frees up your time to iterate on new features, focus on website performance, and deliver on time.

This is what Prismic is all about: enabling you to build websites easily and efficiently with growth and longevity in mind.

This guide (and the one before it) walked you through using Prismic with Slice Machine in a small demo app. I hope you got a sense of how powerful Prismic is, and I encourage you to use it on your next real project. Check out the resources below to learn more about using Prismic in your Next.js apps.

Happy coding! 🚀

Stay on Top of New Tools, Frameworks, and More

Research shows that we learn better by doing. Dive into a monthly tutorial with the Optimized Dev Newsletter that helps you decide which new web dev tools are worth adding to your stack.

Article written by

Angelo Ashmore

Senior Developer Experience Engineer at Prismic focusing on Next.js, React, and TypeScript.

More posts

Join the discussion

Hit your website goals

Websites success stories from the Prismic Community

How Arcadia is Telling a Consistent Brand Story

Read Case Study

How Evri Cut their Time to Ship

Read Case Study

How Pallyy Grew Daily Visitors from 500 to 10,000

Read Case Study