Getting content in front of your audience hasn't gotten easier over the last decade. The content you're so carefully crafting has to find its way into phones, watches and cars. At the same time, you need to be able to repurpose it for different campaigns, sites and apps. If you want to reach your audience no matter where they are using whatever technology is the next big thing, your content must be structured, flexible and platform-agnostic.
Luckily, we think we figured that one out! Contentful provides ways to create the content structures you need, and you can use our JSON APIs everywhere. This flexibility brings us to the next problem on the list — we cannot know what you’re building and where your content is going. Without this knowledge, it’s impossible to provide a perfect editorial experience for your requirements out of the box.
We made a decision: Rather than build something we think is best for most use cases, we provide you with the tools to make Contentful truly yours! We’re happy to announce that by open-sourcing our field editors, you now have three tools in your belt to customize your Contentful experience.
The Contentful App Framework enables you to customize your editing experience across the whole web application. You can replace fields, create top-level pages and even replace the entire entry editor.
Technically speaking, a Contentful app is a website embedded in an iframe. Inside this iframe, you have access to Contentful’s functionality using the Extensions SDK. Using the SDK, you can update values, react to data changes and interact with the surrounding web application.
You can pair this core functionality with our open-source design system — Forma 36. Contentful’s UI uses React under the hood. We provide components that match our style one to one. While it’s possible to build Contentful apps with any client-side technology, we recommend using React for complex scenarios. Combine the App Framework with Forma 36, and you can create custom UIs that look and feel like Contentful.
But what if you don’t want to reimplement everything from scratch and only need a tiny tweak to an existing experience? In this situation, the new open-sourced field editors come into play. The Contentful UI provides a lot of functionality, from editing text to selecting reference entries to creating rich text. And trust us, you don’t want to build that from scratch! That’s why the React components we run in production are available on GitHub now.
Let’s bring these three technologies together in an example. In this tutorial, we’ll extend the Contentful Markdown editor and add some custom validations to it. To follow along, you have to have npm and Node.js available on your machine. You can find the final source code of this tutorial application on GitHub.
Sound good? Let's get started!
Create a new directory and initialize the project using npm on your command line:
This command creates a new
package.json is the configuration file for front-end projects and defines your dependencies, the commands to build and develop your application and other configurations.
Install the following dependencies:
This tutorial uses the Parcel bundler to get the React application ready to develop and ship. Parcel is a fabulous tool to bootstrap a new project because it offers a lot of functionality while following a zero-config approach. This ease makes it perfect for tutorials like this one.
To start developing your application, create two files in your project root:
index.html looks like this:
index.html is the entry file for Parcel. Parcel traces all the dependencies in this file and creates a beautiful bundle out of everything. All zero-config!
Next, create the referenced
index.js. This file defines your application logic.
init function. An instance of the SDK itself is passed as a function argument to interact with the Contentful user interface. It will come in handy later!
Even though you installed the Parcel bundler, you're not using it yet. Change that by replacing the example
test script with two npm scripts in the
scripts property of your package.json.
You can now run
npm start in your terminal to start the development mode. In development, Parcel starts a web server running on port 8080. Thanks to the
watch argument, the server will refresh pages after code changes. This way, you can develop locally and your embedded Contentful application refreshes automagically.
If you open
localhost:8080 in your browser, you might be surprised that all you see is a blank page. Remember, Contentful apps run in iframes inside of the UI. The
init callback is only called in this particular environment. If you open the page in your browser and nothing shows up, that is correct.
build command comes into play after you finish development. This will be explained at the end of the tutorial.
Contentful apps work on an organization level. While you can install apps using the Content Management API, we prefer to install them right in the organization settings in order to not deal with API endpoint details. Open the space selection in the top left corner and head to the organization settings. There you find "Apps" in the top-level navigation. Click the "Create App" button.
Define the app name and source URL in the app creation dialog. The source URL for development is
http://localhost:8080. After you've done that, define that your app should be available in the
entry-field location for
You can ignore the app configuration screen location in this tutorial. For future apps, if you need to store app-specific configurations like third-party tokens or visual settings, use the app config location to accept and store needed values.
When your app configuration looks like the above, press "Create App." Congratulations, you just created a Contentful app for your organization!
To install the app in a specific space, click "Install to space" in the top right corner and choose your desired space and environment. Unless you're running in an advanced setup with several environments, choose the
This selection redirects you to the app configuration screen of the space to install the app. But wait, you didn't define the "App Configuration Screen" in the app definition. What are you seeing here?
When writing a Contentful app, you can use this app location to provide a settings screen. If there’s no further configuration needed, you don't have to set it up and be presented with a default screen as shown in the screenshot above.
To go on, click "Install."
After installing the app, it's time to enable it for particular field types like the "long text" field. From the top navigation, head over to the content model section and edit the content model of a content type. If you already have an existing content model, edit the field configuration for a "long text" field. If you don't, create a new "long text" field. Open the "Appearance" section of the particular fields and select the app that you just created.
Navigate to edit an entry of the given content type and find your app that says "Hello world" where the Markdown editor is usually displayed.
To use Contentful's design system and field editors, you have to use React. Luckily, you installed the library already. Use React's
render function and change the
index.js file to the following:
After this change, the "long text" field appearance is still a "Hello world", but you're now ready to build a custom implementation that looks and feels like Contentful.
Contentful apps offer a way to run the same code in different UI locations. These range from the app configuration screen previously mentioned, to top-level pages, to the entry sidebar and, like in this case, entry fields.
index.js is the entry point for all of these locations. To figure out what to render, the Extensions SDK offers a
locations object and the
location.is helper function.
Create a new functional component called
MyMarkdownEditor and change your
index.js to use
These changes enable your app to render different components depending on their location. The app renders the
MyMarkdownEditor component only when it's used as an entry field.
Make sure to also call
sdk.window.startAutoResizer when the Markdown editor is rendered. It guarantees that the iframe embedding your components has the correct height.
The ”long text” field is now greeting you with a "hello from my markdown editor" rendered with the
At this stage, what you’ve accomplished is:
Creating and installing a Contentful app
Defining and setting your app for a content entry field
Rendering a custom entry field
With all of the above, it's time to build your custom Markdown editor.
With the release of our field editors, you’re free to build custom UI sections sitting on top of the functionality Contentful already provides. Install the following packages from your terminal:
This command installs Contentful's Markdown editor and Forma 36's React components. Add the following imports right below the other
import statements in
The Contentful Markdown editor uses the Codemirror text editor. Include Codemirror's stylesheet, the Forma 36 styles and the
MarkdownEditor React component.
Go and change the
MyMarkdownEditor component to wrap Contentful's
And voilà — you just enriched the Markdown editor with your headline. The Markdown editing experience is functional and ready to use, thanks to Contentful's extensibility tools.
Let's move on and add some functionality!
After installation, import
alex on top of the
MyMarkdownEditor is a functional component, you have to use
useEffect which you can import from React.
To check if you imported everything correctly, you can find all import statements on GitHub.
MyMarkdownEditor component. Start with using
useState. You can use
useState in functional React components to keep track of component state and trigger rendering.
useState returns an array that includes a getter variable and a setter function. In this case, you're initializing the local state with an empty array. This array represents all the Alex.js warnings. Call
setWarnings whenever you want to define new items and re-render the whole custom Markdown component.
But how do you get these warnings? Use
sdk.field.onValueChanged to register a callback that will be invoked whenever the underlying field value changes. It's important here to register this callback in an
useEffect hook and not in the component function itself.
A functional React component is invoked on every re-render. If you're not careful, you could register hundreds of
onValueChanged callbacks quickly. To only register the callback once use
useEffect(() => …, ). You can find more information about the useEffect hook in the React documentation.
Call Alex.js in the
onValueChanged callback, use the passed in value and set the resulting warnings to the local state using
Every time you edit the Markdown, the local state will be updated with potential issues in your wording. These updates lead to re-rendering the component. The last step is to display the errors in the returned JSX:
Check for the
length of the
warnings array, and if it includes warnings, iterate over every entry and display a list item including the warning's
With these changes, you accomplished the following:
You defined a local state dealing with an array of warnings
You attached an event listener to react to value changes and analyze it
You rendered a list of potential text issues
The complete code of the
MyMarkdownEditor component looks now like this:
The list of rendered warnings above the Markdown editors are everything but "on brand" right now. They don’t match Contentful's styling. Let's fix this!
Contentful's design system Forma 36 offers a lot of ready-to-use components. Head over to its Storybook and have a look. Implement three components:
Note. Go to the top of the file and import them.
Adjust the rendering of the Alex.js warnings to use Forma 36's components instead of
And here you go! You now have an official Contentful Markdown editor paired with custom functionality. And it looks good too!
With the Markdown editor rendering properly, you're almost there. You might have noticed one thing missing. When you press the full screen button (the cross with the arrows) you notice that it's not opening the editor in full screen.
The reason for that is that the full screen mode is another app location. To make it work, your application code has to run in two locations: in an entry field and in the dialog location.
Luckily, the documentation for the Markdown editor provides guidance on how to implement this app in the dialog location. Adjust the import statement for
renderMarkdownDialog method can then be used in the
init function handling all the different locations:
With these adjustments you can now open your Markdown editor in full screen, too!
The application is served from
localhost:8080 so far. To run your application in production, you should optimize the source code and host it outside of your local machine.
Luckily, Parcel takes care of the optimization part. Run
npm run build on your command line. This command generates a
dist directory that includes everything you need to host this app. Upload it to your static hoster of choice.
We use Netlify for a lot of projects. If you only want to see the enriched Markdown editor in action, head back to the app definition in your organization settings and set https://contentful-enriched-markdown.netlify.app/ as your app source.
This tutorial shows how you can leverage Contentful's App framework, the design system Forma 36 and the open-sourced field editors to tailor your editing experience to your needs. We can't even say how excited we are about this. A lot of Stefan's sites run on Contentful, too, and that's why he started building a collection of custom editor experiences. Feel free to use it and open issues with requests for other components.
So what's next? To use this tutorial application, find the final source code on GitHub. And to learn more about Contentful's fields editors head over to the field editors section in the docs or look at the detailed developer documentation.
Providing you the tools to customize the Contentful UI is one of our top priorities, and we can't wait to see what you build with this new set of tools. Let us know what you create or reach out to Stefan via Twitter or Email; we'd love to learn more about the Contentful experiences that are truly yours!
Alex has ten years of professional expertise in web development and creating complex SPAs. I'm focused on performance and maintainability, simplifying processes and getting things done. Currently, I'm most interested in React, React Native, Reason, Kotlin, and GraphQL.