If you’ve ever wished you could repeat a certain pattern in Contentful — maybe a list of ingredients, items or products — but found that the built-in fields don’t quite do what you’re looking for, then the Repeater app is your answer. On a live stream I did with Stefan Judis, we worked on building a prototype of an app that helped with this. Now it’s become a reality.
Today, I am launching the Repeater app on the Contentful App Marketplace. Repeating content should be easy, but the reality is that everyone’s use case is a little different.
I’ll show how I built the app using the App Framework, Forma 36 and a little bit of custom code, and give you the tools to extend it. If you already have a good understanding of building apps, you can check out the Repeater app repo here, fork it, and go to town!
To start, we will use the create-contentful-app CLI tool. This is available free to developers, and helps get apps up and running quickly. The create-contentful-app CLI tool creates a React app project with our design library: Forma 36 and our open-source field editors for an easy way to get to writing business logic fast.
We get all this by running the commands below:
An App Framework app is a front-end single page application that runs in an iframe. At this point our app is running on
localhost:3000. But it won’t be accessible until we create the AppDefinition and select the locations where we want it to show up. In other words, the locations where the iframe will be loaded in the Contentful interface.
Creating the AppDefinition
Simply put, an AppDefinition is the entity that represents an app in Contentful. You can think of it as a sort of blueprint for how your app will function.
To get started, you must be a part of a Contentful organization with an admin or developer account. If you prefer to develop in a space or environment which isn’t production-facing, you can sign up for a free Contentful account and use it as your sandbox.
To create the AppDefinition, head to your organization settings and click on Apps in the top menu bar. Once on the AppDefinition page, click the button to create a new app.
First, we are going to name our app: Repeater
Next, we will make its app URL http://localhost:3000. This is where our app is currently running. Then, we are going to select the field location and pick the JSON field and click the confirm button to save this AppDefinition.
Last, we will create a new instance parameter called valueName, which will be short text.
Here’s what your AppDefinition should look like:
Using a JSON field with the Repeater app
Let’s now head over to a space where we want to see our app show up. In the top menu of our space or environment, click Apps, then Manage apps. From here we can find our newly created Repeater app and install it into our space.
Because we are building an app that will take over the appearance of the JSON field, we must also have a content type that makes use of a JSON field. You can create a content type to do this. When creating the JSON field, we need to configure it by editing the settings of the field and selecting appearance. Choose our Repeater app as its appearance.
Coding the app for custom functionality
Once the app is assigned to a field, we can head over to our entries section and find an entry to see how the app is displayed.
As we can see, our app is running but the functionality now needs to be built. Inside the project code, I’m specifically going to work on the
src/components/Field.tsx React component. This maps to the location of the field inside of a Contentful entry. To start, let’s import some components and tools:
As a note, I am using uuid, a unique ID-generating library, as a way to tag items in our app with an ID.
Because we are using typescript, I’m also going to create a type for our Repeater Item:
I will also start to replace the default functionality inside of the Field component:
In the Field component itself, we have two main things going on.
We are going to read the value of our instance parameter that we created during the AppDefinition process. This value will be a display name for our list which I will point out again later on to clarify.
Items are going to be stored in an array of
items. These items will be created by the
createItemfunction and return an object with the shape of
Itemas outlined by our typescript interface.
Next, let’s add functionality for when the app loads.
We have two main things happening.
When the app loads, ensure the app shows up correctly in the UI by calling the
startAutoResizerfunction, which is provided on the SDK and automatically resizes the app if necessary.
Using the SDK’s
field.onValueChanged, we can listen for changes to the field’s underlying value and set our React state to reflect the data that is stored in Contentful.
Now, let’s add a few utility functions.
These functions will provide our UI with the handlers necessary to take care of any user interaction. Let’s make this component return proper JSX, which will give us the ability to see our app in action.
I’m using Contentful’s Forma 36 Table and Button components to build out the UI and create a cohesive experience with the other built-in fields. I like this approach because it ensures the UI doesn’t seem disjointed and users who are already familiar with Contentful will already feel comfortable using these UI elements.
While our app does take advantage of hot reloading, I always like to refresh the page to ensure all our work has taken effect. After refreshing, we should see the app in action. If you are having trouble seeing this app work or you think something may have missed a step while following the above directions, don’t worry.You can view the full source to see how it works.
While I think many people may benefit from the general Repeater app which is free to install on our marketplace, you can always fork the repo to start your own customization. One cool idea that was proposed and implemented by a member of our community, Martin Schön, is a Repeater app using reference fields instead of JSON. The Reference Matrix Field App is open source and also available for further tinkering. But many options are available. Stitching together UI components from Forma 36 and making use of the different app locations could unlock more ways for you to create a powerful repeater app.
That said, it is always interesting to see the different ways developers have come together and built their own components for the UI/UX they envision for their users. Many developers make use of our Slack Community where help and ideas are easily shared. I’m active on the channel and always happy to help explore ideas or guide other developers through the app-creation process. If you’d like to join our community, you can take advantage of some of the cool things we are doing and discussing over there.