Creating and managing landing pages with React and GrapesJS
… or how to configure GrapesJS to store and load your customer’s content…
Let’s imagine one of your customers asks you to make it possible with his application to build is own page without asking you to do it.
Hmm ok, is WordPress is the right tool for that? Probably but he hasn’t enough money to pay a WordPress integration with his actual stack: React desktop App with an Express back-end connected to MySQL database.
After some research on the web and read many papers on this, it’ll appear that GrapesJS is an easy to use and install page builder that could match my customer requirements.
What you’ll se here:
- Installation of GrapesJS
- GrapesJS block basis plugins, and why it is the choosen one
- RemoteStorage (DB) to save and load customer’s work
- AssetsManager to upload and use custom pictures.
- Custom blocks creation
- Custom css rules
- Avoid tricky error
- and so on…
What you’ll don’t see:
- Create-react-app
- Back-end
- Really deep dive into the editor
Installation:
Nothing special here we need those two packages from npm/yarn to play around (I skipped the create-react-app part) :

If you search on the web, you’ll read that a lot of people uses grapesjs-preset-webpage, there is many blocks/style out of the box and works well but all the structure for now use the display table property to align items and I’m not really comfortable with it, and the last reason is you can use display flex with “preset-webpage” plugin but can’t (for now I think/hope) use align-items or justify-content property, result on an useless display flex property.
Configuration:
Let’s create our main component in our react app: Editor.js which initialize an instance of a grapesJs editor:

We create our Editor component with two state, one for pictures that our customers will use to build page, and editor state that contain our editor instance.
Don’t forget to use useEffect to initialize your editor, here I “watch” and wait my image from the api and display my editor.
We specify the container with the value of the id of the div inside the return of our component.
And last one, we tell grapesjs which plugin we’ll use and with which options, I let you read the docs to select which options could be useful for you.
Here’s the result (you have some difference between the blockbar on the right, I choose to remove some unnecessary blocks) :

AssetManager, upload and display pictures:
With this library, you can open an asset manager when you drag n drop the image block inside the editor which looks like this:

Now let’s look on the assetManager configuration object :

Important things are:
- Headers: to pass some custom headers to the request
- params: if you need to passe some extra info inside the req.body (not the req.params one)
- assets: your state with your pictures
- credentials: Normally the value is on “includes” but makes some CORS problems with my requests, so I switched the value with “omit”.
- uploadName: the name of your file upload that should match with the multer name (really important)
- upload: the endpoint where we send our post request to upload our files, if you want to see your new pictures directly into your assetManager without rerender, the response of your request should be: { data: [“https://myFirstPicture.com”,”https://mySecondPicture.com”, etc…] }
StorageManager and database record, store and load content…
Here I’ll describe methods to store and load content into the database with api call but you can use the local storage to do it -btw grapesjs will use it if remote storage connexion failed.
I write a lot of config line on a separated file to make my Editor component shorter:

Let’s explain important lines here:
- type:”remote” to use XMLHttpRequest to POST/PATCH && GET
- autoload with ternary operator depend if an id is provided, if yes you trigger the get Request.
- urlStore: our api endpoint to store content.
- urlLoad: our api endpoint to load content.
- fetchOptions: Here is the main trick, I don’t know if it’s the right way but I manage the problem with this property:
Two things to focus on:
The first, easier, is: to stay restfull, I use the ternary to use a PATCH instead of POST method.
When my customer click on “new page”, I’ll send a post request that create the page, when the editor send content to the API it’s with a PATCH method:

The second is a bit more tricky:
When you store and load content grapesJS send inside the req.body a JSON object that looks like this:

Ok so what’s the problem?
The problem is that this req.body object could be long, very long… and you could be face to this issue:

The main problem is that Grapesjs send all your assets links into the gjs-assets property, and if you don’t disable the base64 encoded file when uploading them…that’s a very, very long request.
So I tried the “beforeSend” method that we could use with the storageManager but didn’t figure out. So I decide to use the fetchOptions to remove the gjs-assets property from the req.body :

I said that I’ll not talk about back-end but I think it could be useful for you to know that you have to extend the limit of the req.body request used by the bodyParser package in your express application:

If someone have a better solution, please let a comment to this post :)
Nice, we’ve got our file upload and storageManager working, let’s do some little customization!
Creating Custom Blocks, Custom Styles, importing google fonts and adding some css rules :
In our EditorConfig.js we can add :

I’ll start by the easiest part:
- canvas object is to inject google font into our editor.
- customfonts object is to display it in the right toolbar:

- customCss object is a list of class that my customer can use avoiding create them with the builder :

To understand the concept of component:
And to understand the block one:
We add a custom block to our EditorConfig.js, and linked it to a custom component:

We create a custom component which extends the “link” grapesjs component and we associate a block to display it in the right toolbar:

You can now drag n drop a link into the editor and when you select the component settings in the toolbar you can provide a link to your component :

Let’s inject all of this stuff into our editor:

Let’s detail those useEffect:
The first one is to get our token from local storage to pass it as un argument of our storageManager function. (don’t forget to get the pages id into the params of your url to pass it to the function too).
The second one is a bit more tricky: before I created a state “storageManagerconfig” I’ll write the storageManager function directly inside editor initialization but I had some performance issues so I decided to pass it into a useEffect and update a state with it, it solves the problem.
You alreay know the third one, I just add the canvas and storageManager properties.
The fourth one is, after the editor is loaded, inject custom rules, block, type on it !
I think we are done for the configuration of grapesJS, I’ll show you the React component to display your page, using the “gjs-html” and “gjs-css” stored into your database :

And here you are, you can use your page builder, uploading your pictures to use it, save your content and load it and display your amazing page on the web :) Enjoy !!
If you have any suggestions or..anything feel free to contact me !!