Scrivito is proudly made by JustRelate Group in Berlin, Germany, and Wrocław, Poland.
Scrivito is proudly made by JustRelate Group

Adding Scrivito to Create-React-App

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 4.0.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

Note that Scrivito is not yet compatible with React 17 but will be soon. In the meantime, you can rewrite the “package.json” file to use 16.8.0.

package.json
...
"react": "^16.8.0",
"react-dom": "^16.8.0",
...

Then run:

npm i --save scrivito

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

src/config/scrivito.js
import * as Scrivito from 'scrivito';

Scrivito.configure({
  tenant: 'YOUR-CMS-TENANT-ID', adoptUi: true
});

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 WITH CREATE-REACT-APP

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';

Scrivito.configure({
  tenant: process.env.REACT_APP_SCRIVITO_TENANT, adoptUi: true
});

Next, 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, add imports for Scrivito-related files to “src/index.js” like so:

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

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:

src/App.js
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" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <h1 className="App-title">Welcome to React with Scrivito</h1>
      </header>
      <Scrivito.CurrentPage />
    </div>
  );
}

export default App;

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 that 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 ImageWidget class in addition to the examples below, as these are commonly used.

index.js (in src/Objs/ and src/Widgets/)
function importAll(r) {
  r.keys().forEach(r);
}

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

Homepage

src/Objs/Homepage/HomepageObjClass.js
import * as Scrivito from 'scrivito';

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

export default Homepage;
src/Objs/Homepage/HomepageComponent.js
import * as React from 'react';
import * as Scrivito from 'scrivito';

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

Image

src/Objs/Image/ImageObjClass.js
import * as Scrivito from 'scrivito';

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

export default Image;

SectionWidget

src/Widgets/SectionWidget/SectionWidgetClass.js
import * as Scrivito from 'scrivito';

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

export default SectionWidget;
src/Widgets/SectionWidget/SectionWidgetComponent.js
import * as React from 'react';
import * as Scrivito from 'scrivito';

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

TextWidget

src/Widgets/TextWidget/TextWidgetClass.js
import * as Scrivito from 'scrivito';

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

export default TextWidget;
src/Widgets/TextWidget/TextWidgetComponent.js
import * as React from 'react';
import * as Scrivito from 'scrivito';

Scrivito.provideComponent('TextWidget', ({ widget }) => {
  return (
    <Scrivito.ContentTag
      tag="div"
      content={ widget }
      attribute="text"
    />
  );
});

Fire up your app!

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

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, after clicking “Edit” on the top bar, 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 it or 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.8.0, and the Scrivito SDK 1.20.0. The directions should work without change with all minor versions going forward, but let us know if you encounter any issue.