What Is Strapi And How To Build Your First API?
Tags: webdev, gatsby, todayilearned
Published: 2020-03-16 15:30:43

<h2><b>Introduction</b></h2>
<p>We can read in an <a href="https://strapi.io/" target="_blank" rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)">official Strapi website</a>- “The open-source Headless CMS Front-End Developers love”.</p>
<p>I wanted to experience this firsthand, so I had to get into Strapi world. In this article, I will share my insights about headless cms’, describe Strapi in detail, and few ways to connect it to any view layer.</p>
<h2><b>What is Headless CMS?</b></h2>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/02/headless.png" alt="headless statue" class="wp-image-2795"/>
<p>A headless CMS is a content management system that allows you and members across your organization to manage and write content and access it across all your applications using an API.</p>
<p>The term “headless” comes from the concept of chopping the “head” (the frontend, i.e. the website) off the “body” (the back end, i.e. the content repository).</p>
<p>A headless CMS does not care about how and where your content gets displayed. It has only one focus: storing and delivering structured content.</p>
<h3><b>Use cases for Headless CMS:</b></h3>
<ul><li>Build a website with a technology you are familiar with.</li><li>Websites and Web apps that use JavaScript frameworks (Vue, <a href="https://pagepro.co/react-development.html" target="_blank" rel="noreferrer noopener nofollow" aria-label="React (opens in a new tab)">React</a>, Angular)</li><li>Websites created with static site generators (<a href="https://pagepro.co/gatsby-development.html" target="_blank" rel="noreferrer noopener nofollow" aria-label="Gatsby (opens in a new tab)">Gatsby</a>, Jekyll, etc.)</li><li>Native Mobile Apps (iOS, Android, Windows Phone, <a href="https://pagepro.co/react-native-development.html" target="_blank" rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)">React Native</a> …)</li><li>Enrich product information on e-commerce sites.</li></ul>
<h3><b>Reasons to adopt a headless CMS solution</b></h3>
<ul><li>Freedom from developing the legacy software of tomorrow</li><li>Ability to easily manage content on multiple channels.</li><li>Content management from a single place across the organization.</li><li>Prepared for growth and scalability.</li></ul>
<h2><b>What is Strapi?</b></h2>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/02/logo-strapi-black-blue-1024x286.png" alt="strapi logo" class="wp-image-2802" width="174" height="48"/>
<p>Strapi is an open-source headless CMS front-end developers love. It's more than a Node.js Framework and more than a Headless CMS. </p>
<p>It saves API development time through a beautiful admin panel anyone can use.</p>
<h3><b>Strapi most advantages</b></h3>
<ul><li><strong>Open source</strong> - free and open-source, forever. The entire codebase is available on GitHub and is maintained by hundreds of contributors.</li><li><strong>Self-hosted</strong> - security is crucial for companies. Host your data safely, on your own servers. GDPR compliant.</li><li><strong>Customizable</strong> - each project requires specific requirements. Easily customize the admin panel as well as the API.</li><li><strong>RESTful or GraphQL</strong> - consume the API from any client (React, Vue, Angular), mobile apps or even IoT, using REST or GraphQL.</li><li><strong>100% JavaScript</strong> - one language to rule them all. Use JavaScript everywhere: both for your front-end and your Headless CMS.</li><li><strong>Extensible by design</strong> - plugins system included. Install the auth system, content management, custom plugins, and more, in seconds.</li><li><strong>Authentications &amp; Permissions</strong> - secure your endpoints by allowing or not allowing users to access your API by role.</li></ul>
<h3><b>Alternatives to Strapi</b></h3>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/02/Screen-Shot-2020-02-28-at-12.04.12-1024x798.png" alt="different coffies on a wooden table" class="wp-image-2798"/>
<p>There are quite a few alternatives to Strapi that you may be already familiar with. </p>
<p>Most interesting are:</p>
<ul><li><a rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)" href="https://wordpress.org/" target="_blank">Wordpress</a>: an open-source software to build websites, blogs, and apps.</li><li><a rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)" href="https://www.contentful.com/" target="_blank">Contentful</a>: a modern platform to manage content in web and mobile apps.</li><li><a rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)" href="https://www.netlifycms.org/" target="_blank">Netlify CMS</a>: an open-source content management system with support for static site generators. </li><li><a href="https://firebase.google.com/" target="_blank" rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)">Firebase</a>: cloud service for real-time working apps.</li><li><a href="https://www.drupal.org/" target="_blank" rel="noreferrer noopener nofollow" aria-label=" (opens in a new tab)">Drupal</a>: an open-source content management platform for websites and apps.</li></ul>
<h2><b>How to create the first API in Strapi</b></h2>
<h3><b>Small introduction</b></h3>
<p>To build a Strapi application I’ve used  a tool called Docker. </p>
<p>I found a docker compose file which includes strapi application configuration with postgres database to store data.</p>
<p>Below you see a code that creates 2 containers - one with strapi app, and the second one with a database container (strapi app is using the database container).</p>
<p>To build an application and start developing, we only have to be in the directory where we got this docker-compose file and run a docker-compose up command in terminal.</p>
```javascript
version: '3'
 
services:
 strapi:
   container_name: strapi
   image: strapi/strapi
   environment:
     - DATABASE_CLIENT=postgres
     - DATABASE_HOST=db
     - DATABASE_PORT=5432
     - DATABASE_NAME=strapi
     - DATABASE_USERNAME=strapi
     - DATABASE_PASSWORD=strapi
   ports:
     - 1337:1337
   volumes:
     - ./app:/srv/app
   depends_on:
     - db
 
 db:
   container_name: postgres
   image: postgres
   restart: always
   volumes:
     - ./db:/var/lib/postgresql/data
   environment:
     POSTGRES_USER: strapi
     POSTGRES_PASSWORD: strapi
     POSTGRES_DB: strapi
```
<p>If everything went good, we should see something like this:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/Zrzut-ekranu-2020-02-17-o-14.50.33-1024x316.png" alt="" class="wp-image-2822"/>
<p>For the first time you will be seeing a bit more info than you see on screen above, (I run that command already for the second time) so only run database and strapi container. </p>
<p>To start managing, we should go to http://localhost:1337/admin. Try to put that into your browser.  It’s a <strong>sign up</strong> page. To start developing we have to create an <strong>admin account</strong>.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/2-1024x520.png" alt="" class="wp-image-2823"/>
<p>After successful login, we should be moved to the <strong>dashboard page</strong>. </p>
<p>Strapi has a very clear UX design and it is easy to navigate through the whole app. </p>
<p>There is a <strong>header</strong> where we can change language and our user settings. On left there is <strong>strapi navigation</strong>. </p>
<p>Starting from the top we got <strong>content types</strong> and our app <strong>models</strong>. Next to that, we can find plugins with <strong>content type builder</strong> to create new models. These are the two main things, we are going to use today.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/3.png" alt="" class="wp-image-2824"/>
<p>Ok, let’s go to the first <strong>content type</strong> that was automatically created during build strapi app - <strong>Users</strong></p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/4-1024x518.png" alt="" class="wp-image-2825"/>
<p>We can see an empty <strong>User</strong> table but it isn’t truth. </p>
<p>We have created admin user at the beginning but it doesn’t contain that record. From that view, we can add more users, so try to do that. </p>
<p>We have to click <strong>Add New User</strong> button:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/5-1024x520.png" alt="" class="wp-image-2826"/>
<p>After we click, we are going to create an entry page where we can create a new user record. </p>
<p>We can see username, email, password string fields and also confirmed and blocked boolean fields. </p>
<p>On the right side we see roles field which is a relation field. It is a select field with two values: <strong>public</strong> and <strong>authenticated</strong>. We will try to add new user, so fill all the fields and click the green <strong>Save</strong> button.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/6-1024x521.png" alt="" class="wp-image-2827"/>
<p>We are again on <strong>User</strong> table page, and we can see the latest added user. </p>
<p>From that view we can add new records or edit the existing one. It is very easy for non-technical people to manage the application. They don’t have to write the code like developers. Instead, they can create data shapes only by clicking in the dashboard.</p>
<p>Ok, we have added a new user to the existing content type. </p>
<p>Let’s create new content type. We can do that by using <strong>Content Type Builder</strong>. </p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/7-1024x520.png" alt="" class="wp-image-2828"/>
<p>There are 3 content types in our app for now. The <strong>User</strong> content type we saw in navigation menu, and two more - <strong>Permission</strong> and <strong>Role</strong> (every strapi app created from the scratch got these content types).</p>
<p>In this article we won’t go deeper into it. </p>
<p>Better option will be to create a new model. </p>
<p>Let’s assume we are creating a headless cms for blog, so we will try to add <strong>Post</strong> content type. </p>
<p>By clicking “create new content-type” we move to form:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/8-1024x522.png" alt="" class="wp-image-2829"/>
<p>We can see a modal where we can pick the type of field we want to add to our new model.</p>
<p>After we choose, for example, text field, the next step is adding the name to that field and choosing more specific text field type - <strong>short text </strong>or <strong>long text</strong>. </p>
<p>Every post got the <strong>title</strong> and in most cases it is short text. </p>
<p>So we added this field into our <strong>Post</strong> model. Next, I have also added <strong>content</strong> field as a rich text type, <strong>short description</strong> field as a long text, and <strong>User</strong> relation field, so any user can have many posts.</p>
<p>So our <strong>Post</strong> model looks like:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/9-1024x520.png" alt="" class="wp-image-2830"/>
<p>Then we can move to our <strong>Post</strong> model, which will appear at the top of navigation:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/10.png" alt="" class="wp-image-2831" width="767" height="390"/>
<p>In the next step we will create an exemplary post that later can be displayed on our blog. Just like in the User model, we should hit the “<strong>Add New Posts</strong>” button. </p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/11.png" alt="" class="wp-image-2832" width="777" height="397"/>
<p>We have to fill all the fields chosen when we built a post model. </p>
<p>So, add a post title, content, short description, and select a post’s author. </p>
<p>After that, let’s save our first post - it will be automatically added to the database. If everything went good, we will see our post on the list.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/12-1024x520.png" alt="" class="wp-image-2833"/>
<p>If we have any data in our strapi application (post assigned to user), we can use it to be displayed on the frontend - in our case Gatsby blog.</p>
<p>To make that happen, we need to do one more thing - We have to change permission to models, which we want to get by api. </p>
<p>In navigation, we should go to roles and permission page. We can see a content with some tabs. We need the first, displayed immediately after we enter the site. Try to edit the authenticated option by clicking on the pencil icon.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/13-1024x435.png" alt="" class="wp-image-2834"/>
<p>After moving to editing section, we can see a form with fields we can edit. </p>
<p>The one we need is <strong>Permission</strong> section. We have to allow developers fetch data about posts. </p>
<p>Mark the find checkbox related to the Post model. After that, save your choice.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/14-1024x440.png" alt="" class="wp-image-2835"/>
<p>We have to do the same thing for <strong>Public</strong>. Go to the edit and mark <strong>find</strong> option related to the Post model.</p>
<p>This is a basic example done for the article. In real application you have to be careful with permission settings (for example adding create or edit role only for authenticated users).</p>
<p>So I am creating a common classical Gatsby application, but I won’t be going too much into details, I will only show the things related to fetch our strapi data to gatsby and display it.</p>
<p>First, we have to add a gatsby plugin, which will magically connect strapi and gatsby together. </p>
<p>The plugin is called ‘<strong>gatsby-source-strapi</strong>’. We should use npm or yarn to install it like a normal npm package inside gatsby project directory. </p>
<p>After that, go to the <strong>gatsby-config.js</strong> file and add plugin.</p>
<p>There is a code below:</p>
```javascript
{
     resolve: 'gatsby-source-strapi',
     options: {
       apiURL: 'http://localhost:1337',
       contentTypes: [
         'post',
       ],
       queryLimit: 1000,
     },
   },
```
<p>In options you need to add <strong>apiUrl</strong> (in our case it is http://localhost:1337), and <strong>contentTypes</strong>. There are models which we want use.</p>
<p>Run our Gatsby application and try to get data via graphQL. You should go to in-browser IDE and explore data and schema. I have built app on port 8000 so use url: http://localhost:8000/___graphql</p>
<p>We Need to create query to get posts and fields, that we need to display to all blog users. </p>
<p>This is an example of query and its response:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/16.png" alt="" class="wp-image-2836"/>
<p>Let’s create a basic react components, in this case articles list:</p>
```javascript
import React from 'react'
import { graphql, Link } from 'gatsby'
 
import Layout from '../components/layout'
import PostsListStyled from '../components/styles/PostsListStyles'
 
const BlogPage = ({ data }) => {
 const { edges: posts } = data.allStrapiPost
 
 return (
   <Layout>
     <PostsListStyled>
       {posts.map(({ node: post }) => (
         <li key={post.id}>
           <Link to={`/blog/${post.id}`}>
             <h1>
               {post.created_at}: {post.title}
             </h1>
             <p>{post.short}</p>
             <p>by {post.user.username}</p>
           </Link>
         </li>
       ))}
     </PostsListStyled>
   </Layout>
 )
}
 
export default BlogPage
 
export const pageQuery = graphql`
 query {
   allStrapiPost {
     edges {
       node {
         id
         title
         content
         created_at(formatString: "YYYY-MM-DD")
         user {
           username
         }
         short
       }
     }
   }
 }
`
```
<p>If everything went well, after running gatsby blog, we should see a listing. Let’s check it.</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/17.png" alt="" class="wp-image-2837"/>
<p>Everything seems to be working correctly.</p>
<p>It is exactly the same data we have saved in our strapi cms.</p>
<p>Next step will be creating an article page. That is an example of basic component page implementation:</p>
```javascript
import React from 'react'
import { graphql, Link } from 'gatsby'
import Layout from '../components/layout'
 
const Template = ({ data }) => {
 const { strapiPost: post } = data
 
 return (
   <Layout>
     <Link to="/blog">Back to the list</Link>
     <div>
       <h1>{post.title}</h1>
       <h2>{post.created_at}</h2>
       <h2>{post.user.username}</h2>
       <img src={post.image.childImageSharp.original.src} />
       <div dangerouslySetInnerHTML={{ __html: post.content }} />
     </div>
   </Layout>
 )
}
 
export default Template
 
export const query = graphql`
 query ArticleTemplate($id: String!) {
   strapiPost(id: { eq: $id }) {
     title
     content
     created_at(formatString: "YYYY-MM-DD")
     user {
       username
     }
     image {
       childImageSharp {
         original {
           src
         }
       }
     }
   }
 }
`
```
<p>One more thing. Making createPages function in gatsby-node file. </p>
<p>It is necessary to our graphQL query for <strong>Template</strong> component to work correctly. </p>
<p>This is the code you have to add to <strong>gatsby-node</strong>:</p>
```javascript
exports.createPages = ({ actions, graphql }) => {
 const { createPage } = actions;
 
 const getArticles = makeRequest(graphql, `
   {
     allStrapiPost {
       edges {
         node {
           id
         }
       }
     }
   }
   `).then(result => {
   // Create pages for each article.
   result.data.allStrapiPost.edges.forEach(({ node }) => {
     createPage({
       path: `/blog/${node.id}`,
       component: path.resolve(`src/templates/post.js`),
       context: {
         id: node.id,
       },
     })
   })
 });
 
 // Query for articles nodes to use in creating pages.
 return getArticles;
};
```
<p>Build Gatsby blog again and check results of our hard work:</p>
<img src="https://pagepro.co/blog/wp-content/uploads/2020/03/18.png" alt="" class="wp-image-2838"/>
<h2><b>Conclusion</b></h2>
<p>Strapi is a fantastic powerful tool for creating CMS without a head to our applications. </p>
<p>Headless approach (thanks to the possibility of using data through many applications) makes us free from using one specific technology and enables us to use any of the newest ones.</p>
<p>We don’t need to know any backend language to write it. We can just click and use it in our business easily.</p>
<p>It is also a great tool for frontend devs, they can quickly make an API to their frontend applications and use it even to learn new technologies. </p>
<p>It provides us with a full range of other possibilities. I hope the above article will encourage you to try it out, and start the new adventure with strapi. </p>