Adding Scrivito to Create-React-App

Facebook’s create-react-app (CRA) offers an easy and well-documented way of bootstrapping a React app. In this tutorial, we will show you how to add Scrivito to such an app, allowing you to freely combine Scrivito-CMS-managed content with whatever content you wish to deliver separately.

Before you begin, you'll want to verify the current requirements for CRA; this tutorial was last verified with version 3.1.2. For the instructions in this tutorial to work as intended you will need a Scrivito CMS, too.

Create the React app

Let’s start! In a terminal, change to where your projects are, then create the React app and initialize the repository. Here we are naming our application “react-scrivito”, but you could use what ever name you wish:

npx create-react-app react-scrivito
cd react-scrivito

Add Scrivito and its basic configuration, app code and markup

npm i --save scrivito

Now create Scrivito’s configuration file, “src/config/scrivito.js” and set its contents to:

import * as Scrivito from 'scrivito';

  tenant: 'YOUR-CMS-TENANT-ID',

Replace YOUR-CMS-TENANT-ID with exactly that. Please find the tenant ID of your Scrivito website in your dashboard on the “Settings” tab.


Using environment variables is always a safer option compared to hard-coding sensitive data. When using the Create React App Webpack settings, one must prefix any variable with REACT_APP_ for it to be picked up. For this project, the call to Scrivito.configure would look like this:

// src/config/scrivito.js

import * as Scrivito from 'scrivito';

  tenant: process.env.REACT_APP_SCRIVITO_TENANT,

Then add the variable to the “.env” file in your project and on Netlify in your “Build & deploy” settings. Finally, don't forget to add “.env” to your “.gitignore” file.

Then make “src/index.js” look like this:

import React from 'react';
import ReactDOM from 'react-dom';
import './config/scrivito';
import './Objs';
import './Widgets';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

In addition to the configuration we provided above, the (not yet existing) CMS object and widget class definitions are imported. We’ll provide a couple of basic CMS classes later on.

What you render here, in this case via the App component, depends on where you started off. For a fresh React app without any relevant content (like ours), it makes sense to render just the Scrivito-based content, while a fully fledged React app probably requires some kind of routing. There’s a dedicated tutorial on implementing routing using React Router.

To have the app render the current (Scrivito-based) page (in addition to the default header), change “src/App.js” to the following:

import React from 'react';
import * as Scrivito from 'scrivito';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
          Edit <code>src/App.js</code> and save to reload.
          rel="noopener noreferrer"
          Learn React
        <h1 className="App-title">Welcome to React with Scrivito</h1>
      <Scrivito.CurrentPage />

export default App;

Generate and finalize the webpack configuration

First, generate the webpack configuration:

npm run eject

In a standard Scrivito-based app the editing interface is available under the “/scrivito” URL. To make this work here, we will instruct webpack to copy the corresponding HTML file included in the SDK (“index.html”) to somewhere else and make “/scrivito” point to this file. We require the copy-webpack-plugin for copying the file, so first run:

npm i --save copy-webpack-plugin

Then we use the plugin in the webpack configuration, “webpack.config.js”, to actually provide a copy of the UI-enabled “index.html” file:

// Other definitions
const CopyWebpackPlugin = require('copy-webpack-plugin');

// …
plugins: [
    new CopyWebpackPlugin([
      { from: './node_modules/scrivito/scrivito/index.html', to: 'scrivito/index.html' },
    // More plugins
// …

Finally, to let the web server know where to expect this “index.html” file, add the corresponding rewrites to the historyApiFallback key in “config/webpackDevServer.config.js”:

// …

    historyApiFallback: {
      // Paths with dots should still use the history fallback.
      // See
      disableDotRule: true,
      rewrites: [
        { from: /^\/scrivito$/, to: '/scrivito/index.html' },
        { from: /^\/scrivito\//, to: '/scrivito/index.html' },
        { from: /./, to: '/index.html' },

Provide some page and widget classes and components

To be able to create pages and widgets, we require Scrivito CMS object and widget classes. Assuming you have a fresh Scrivito CMS with the sample content for the Example Application, all we need to get started are a Homepage and an Image object class as well as two widget classes; SectionWidget and TextWidget. These classes will suffice to display at least a small portion of the homepage content.

Our “src/index.js” file above imports object classes from “src/Objs” and widget classes from “src/Widgets”. After creating these directories, we will add the following “index.js” file to each of them to have the contents of the class subdirectories imported automatically.

Alternatively, you can download the files as an archive and uncompress it to the “src” directory if you don’t want to create them all manually. The download includes a Page object class and an Image widget class in addition to the examples below, as these are commonly used.

index.js (in src/Objs/ and src/Widgets/)
function importAll(r) {

// Import all js files from subdirectories
importAll(require.context('./', true, /\.js$/));


import * as Scrivito from 'scrivito';

const Homepage = Scrivito.provideObjClass('Homepage', {
  attributes: {
    body: 'widgetlist',

export default Homepage;
import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('Homepage', ({ page }) =>
  <Scrivito.ContentTag tag="div" content={ page } attribute="body" />


import * as Scrivito from 'scrivito';

const Image = Scrivito.provideObjClass('Image', {
  attributes: {
    blob: 'binary',

export default Image;


import * as Scrivito from 'scrivito';

const SectionWidget = Scrivito.provideWidgetClass('SectionWidget', {
  attributes: {
    content: 'widgetlist',

export default SectionWidget;
import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('SectionWidget', ({ widget }) => {
  return (
    <Scrivito.ContentTag content={ widget } attribute="content" />


import * as Scrivito from 'scrivito';

const TextWidget = Scrivito.provideWidgetClass('TextWidget', {
  attributes: {
    text: 'html',

export default TextWidget;
import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('TextWidget', ({ widget }) => {
  return (
      content={ widget }

Fire up your app!

In the terminal, from the project directory of your app, run:

npm install
npm start

This opens http://localhost:3000 in your browser. If you specified the ID of a new Scrivito CMS in “src/config/scrivito.js”, or haven’t used this URL before, you will need to authorize it on the “Deployment” tab of the associated CMS tenant's settings.

If your CMS content includes a page object for the “/” URL and at least a text widget (like the example app does), you should see a page with some text. This is the published content, without the Scrivito UI:

Blind text on the homepage (UI not loaded)

To have the Scrivito UI displayed, add ”/scrivito” to the URL: http://localhost:3000/scrivito:

Homepage (UI loaded, published content)

Remember that we defined only two widget classes (section and text), so only content from widgets of these types will be displayed. Now, click “Edit” in the top panel; you will see errors from all the other (not defined) widgets on the page:

Homepage (editing mode)

The missing widget classes causing the “application error” messages are included in the Example App you could install to transfer and adapt the classes as needed. As this tutorial is based on the idea of starting from scratch, you might want to delete the sample content from your Scrivito CMS.

Final words

You now have Scrivito integrated with Facebook's create-react-app and can start developing your app further. Add page and widget classes for handling Scrivito-based content, include some styling, and implement routing if you plan to deliver mixed-source content. If you are new to Scrivito, take a look at the other guides and tutorials we have available.

This tutorial was written using React 16.9.0, Webpack 4 and Scrivito SDK 1.9.0. The directions should work without change with all minor versions going forward, but let us know if you encounter any issue.