Build a Simple Blog with Reactjs and Contentful

0𝕏koji
3 min readOct 18, 2020

Overview

In this post, I will introduce a way to build a simple web application that is a simple blog with a famous headless CMS, contentful.

Sample

Here is my code for this post.
repo https://github.com/koji/typescript/tree/master/simple_blog_with_contentful

What is Headless CMS?

Let me tell you what a headless CMS briefly.
Roughly speaking, a headless CMS is a CMS without the functionality of displaying content.
Let’s say it is like WordPress that has only a dashboard.
Probably, some of you think why we need to use headless CMS instead of other CMSes.

  • merits
  • Can focus on frontend and there is no limitation by a CMS(You can use anything you want to use and the development process is the same as normal frontend development)
  • In terms of Contentful, it offers the npm package for fetching data
  • demerits
  • It would be hard to change looks for non-tech people
  • If a headless CMS gets issues, we need to wait until they will be fixed by a service provider​About Contentful https://www.contentful.com/developers/ Contentful is great since it has good documentation, Slack group, and forum.​## Step 1 Define Contentful models Loggin Contentful and define models to display data on react application. In this post, I just created 3 items, title, eye-catch image, and body.​
  • Data structure
{
"name": "easysite", <-- コンテンツモデル名
"description": "simple website like a blog",
"displayField": "title",
"fields": [
{
"id": "title",
"name": "title",
"type": "Symbol",
"localized": false,
"required": false,
"validations": [],
"disabled": false,
"omitted": false
},
{
"id": "image",
"name": "image",
"type": "Link",
"localized": false,
"required": false,
"validations": [],
"disabled": false,
"omitted": false,
"linkType": "Asset"
},
{
"id": "description",
"name": "Description",
"type": "Text",
"localized": false,
"required": false,
"validations": [],
"disabled": false,
"omitted": false
}
],
"sys": {
"space": {
"sys": {
"type": "Link",
"linkType": "Space",
"id": "if4se75018sp"
}
},
"id": "easysite",
"type": "ContentType",
"createdAt": "2020-10-01T15:28:51.896Z",
"updatedAt": "2020-10-01T15:28:52.158Z",
"environment": {
"sys": {
"id": "master",
"type": "Link",
"linkType": "Environment"
}
},
"publishedVersion": 1,
"publishedAt": "2020-10-01T15:28:52.158Z",
"firstPublishedAt": "2020-10-01T15:28:52.158Z",
"createdBy": {
"sys": {
"type": "Link",
"linkType": "User",
"id": "0EGNAqGfBgN849uaItzT7r"
}
},
"updatedBy": {
"sys": {
"type": "Link",
"linkType": "User",
"id": "0EGNAqGfBgN849uaItzT7r"
}
},
"publishedCounter": 1,
"version": 2,
"publishedBy": {
"sys": {
"type": "Link",
"linkType": "User",
"id": "0EGNAqGfBgN849uaItzT7r"
}
}
}
}


Step 2 Create content

This step only needs to create an entry that is almost the same as writing a post on dev.to. You can use Markdown.

Content → Add Entry → easysite(In this case, I named entry model easysite)

From the top, title, eye-catch image, and body.​

One thing you should know is that if you publish the body, that doesn’t mean you publish the eye-catch image.
You will need to publish them separately.

Step 3 Get the API-Key

You will need to generate API Key from Settings. Then get SpaceID and Access Token

Step 4 Create React app

Operations on Contentful is over, from this step you just need to develop a react application.

  1. Create an app with create-react-app
  2. Add a component for API-key. In this case, I hardcoded SpaceID and Access Token on the local environment, but if you want to publish this app, you should use environment variables on hosting services such as netlify.
  3. Install contentful by yarn/npm https://www.npmjs.com/package/contentful
  4. Use contentful to fetch data
  5. Parse data and display it​This sample uses useEffect to get data from Contentful and use content_type to specify the target on Contentful (easysite).
  • As you know, we should avoid using any lol​
useEffect(() => {
fetchData();
// console.log(articles);
}, [articles]);

const fetchData = async() => {
try {
const resp = await client.getEntries ({content_type: 'easysite'});
setArticles(resp.items as any);
} catch (error) {
console.log(error);
}
}


Entry part

export const Post = ({ article }: IArticle) => {
// console.log(article);
const { title, image, description} =article.fields;
const postDescription = marked(description);
return (
<div className="post">
<h2 className="title">{title}</h2>
{image && <img className="featuredImage" src={image.fields.file.url} alt={title} title={title} /> }
<section dangerouslySetInnerHTML={{ __html: postDescription}} />
</div>
)
}

--

--

0𝕏koji

software engineer works for a Biotechnology Research startup in Brooklyn. #CreativeCoding #Art #IoT #MachineLearning #python #typescript #javascript #reactjs