Three Plugins to Power up Your Strapi Blog

Strapi - Aug 22 '22 - - Dev Community

Developing a Jekyll Strapi blog powered with plugins for SEO, internationalization and commenting

Author: Mark Munyaka

Plugins are a powerful tool to customize and extend the functionality of your Strapi app. The Strapi Market is the official marketplace to find plugins comprising more than sixty (60) plugins to choose from. These plugins were developed by the Strapi team, technology and solution partners, and individual community members. You can find plugins that integrate Strapi with other tools, such as Sentry, Mux, and Moesif, and plugins that extend Strapi features, such as SEO, content versioning, comments moderation, internationalization, database configuration, sitemap, and more.

This tutorial aims to show how you can enhance functionality in your Strapi blog by making use of 3 plugins from the Strapi Market. You will use the official Strapi SEO plugin to make your content more SEO friendly, the Internationalization (i18n) plugin to help distribute the content in different languages, and the Comments plugin to moderate comments on your blog. You will start by creating a simple static blog with Strapi as the backend and Jekyll for the frontend. Then, you will install the plugins and show their use cases. At the end of this tutorial, you should know how to install and use plugins from the Strapi Market to power up your app.

Why Strapi?

Strapi is the leading open-source headless Content Management System (CMS) with over 45000 Github stars. It saves its users API development time through an advanced and feature rich API CMS. It makes it simpler to access content through provision of fast and secure APIs built in an efficient and scalable manner.

Strapi is open source; the entire codebase is available and maintained on Github by thousands of contributors. It’s highly customizable with a beautiful admin panel that anyone can use and customize to their taste. The API as well can be customized to one’s needs. Content management functionality can be extended through the use of plugins available through the Strapi Market.

The APIs you generate using Strapi can be consumed using any frontend client from vanilla HTML, CSS and Javascript sites to frontend frameworks like React, Vue, Angular etc. to mobile apps and even IoT devices using REST or GraphQL.

Another reason why Strapi is so compelling is that you can self-host it. That’s right, you can host on your own servers or any other hosting providers. These include cloud platforms such as 21YunBox, Render, Heroku, AWS, Azure and others or locally using Docker

What is Strapi Market?

Strapi Market is the official marketplace that lists all the plugins created by the Strapi team, technology and solution partners, as well as individual community members. It is the trusted place where people can access all the submitted plugins. Anyone is free to develop and submit a plugin to the marketplace. All submitted plugins go through a Review Process. The verified plugins are highlighted and listed on the marketplace so that every plugin creator’s work is showcased and acknowledged.

What is Jekyll?

Jekyll is a static site generator (SSG). It takes text written in your favorite markup language and uses layouts to create a static website. You can tweak the site’s look and feel, URLs, the data displayed on the page, and more. Some of the features include permalinks, categories, pages, templates and custom layouts.

Jekyll was developed using the Ruby language and uses Liquid as its templating language. It is also the SSG powering Github Pages.

Goals

In this tutorial, we will build a simple static blog using Jekyll and Strapi
and install and showcase the functionality of the following plugins:

Prerequisites

To complete the tutorial, the following prerequisites need to be installed:

Backend

  • Node.js: Node.js is the server-side runtime environment used to run our Strapi application. Only LTS versions are supported (minimum v12). You can download from the Downloads | Node.js page and install it using the provided instructions. To check if Node.js has been installed correctly, open up your command line and type node -v.

  • npm (minimum v6) or yarn: This is the package manager for Node.js to run the CLI scripts. We will use this to install Strapi. npm comes bundled with Node.js. To check your version, enter npm -v in your shell. If you prefer yarn, follow the instructions on the Installation | Yarn - Package Manager page to install it. To check if yarn is installed, type yarn -v in your shell after installation.

Frontend

  • Ruby v2.5.0 or higher, including all development headers (check ruby installation using ruby -v)
  • RubyGems
  • GCC and Make
  • Jekyll (minimum v4)

NOTE:
Knowledge of the Ruby language and the Liquid templating language is not necessary but can be helpful to understand and complete the tutorial.

You can find the instructions on how to install Jekyll on the installation page for the Jekyll website.

Backend Setup

The initial setup for the project involves installing and setting up Strapi as the backend for your Jekyll blog. It will host the content as well as the plugins to power up your blog.

  1. First, make sure node and npm/yarn are installed by running node -v.
  2. Create a new Strapi project. I’ll name mine jekyll-blog-backend.
    yarn create strapi-app jekyll-blog-backend --quickstart
Enter fullscreen mode Exit fullscreen mode

Launch Strapi Quickstart

The strapi server should be running automatically on port 1337. Go to http://localhost:1337/admin in your browser to set up your admin for Strapi.

Create an Admin User

Add an admin user to your Strapi app from the registration page.

Strapi Admin User Registration

Create Content Types

Select Content-Type Builder from the Strapi Dashboard sidebar to open up the Content-Type Builder page.

Strapi Content Type Builder Fields

Posts

In this stage,

  1. Create a Collection Type for posts.
  2. Select Create new Collection Type and enter a post name. You can name it Post.
  3. Click on Advanced Settings and disable the Drafts System then click Continue.
  4. Add the following fields to your Post collection type:
  • A Text field with name title and type short text.
  • A Text field with the name description and type long text.
  • A Rich Text field named content.

Click Save and wait for Strapi to restart. Once Strapi has restarted, "Post" is listed under Content Manager > Collection types in the navigation.

Strapi Content Type Builder Fields for Posts

If you get stuck, refer to the Strapi Quick Start Guide, for detailed instructions.

Add Relation Field

Let's add a relation between Post and User from the users-permissions plugin. This makes it easier to link a post to a user to display key data like the Author's name and profile picture, posts etc.

  1. Add a new Relation field to the Post content type. The column on the left should be Post, and the column on the right should be User (from: users-permissions).
  2. Select the fourth relation, User has many Posts, and click Finish.

Strapi Content Type Builder: Relation Field Settings

Click Save and wait for Strapi to restart for the changes to appear.

Add Slug UID to Posts

Next, we will add a dynamic auto-generated slug to the Post collection.

  1. Go to Content-Types Builder and click Post.
  2. Select Add another field and choose UID.
  3. Set the field Slug and set the attached field to title.
  4. Click Save and wait for Strapi to restart for the changes to take effect.

Add Slug UID field

  1. Click on Configure the view, and select the Slug field.
  2. In the Edit Slug menu set Editable Field to TRUE.
  3. Click Finish and then Save.

Make slug uneditable

Now, the slug will be the same as the title for a blog article.

Add Posts

Let’s create new entries for our blog posts.

  1. Create an entry for the “Post” collection type.
  2. Go to Content Manager > Collection types - Post.
  3. Click on Create new entry.
  4. Add the title, description and content to your blog entry.
  5. Click Save.

Create Blog post

Repeat these steps to add multiple blog entries. Feel free to enter any content of your choice. Go to Content Manager > Collection types - Post to see a list of your blog entries.

Post Entry List

Allow Access

For security reasons, the API access is restricted by default. We need to make the content available publicly through the API.

  1. Click on Settings under GENERAL at the bottom of the main navigation.
  2. Under Users & Permissions Plugin, choose Roles.
  3. Click the Public role.
  4. In the Permissions tab, find Post, click on it and select the checkboxes next to find and findone.
  5. Save.

Enable Permissions for Posts

Now, test the link to the API by visiting http://localhost:1337/api/posts. If it’s working you should see an output showing the raw posts data as seen below.

Working Posts API

Great job, your API is now working. With that, the backend is all set.

Frontend Setup

The next step is to set up your frontend for the blog. You will install Jekyll CLI and all its prerequisites using the instructions from the Jekyll installation page.

Next, install the jekyll bundler and gems using the following command:

    $ gem install jekyll bundler
Enter fullscreen mode Exit fullscreen mode

Generate Jekyll project

In this stage, we will generate our Jekyll project.

  1. In the root of your application folder, create a new Jekyll site at ./jekyll-blog or any other name you prefer to use.
    $ jekyll new jekyll-blog
Enter fullscreen mode Exit fullscreen mode

Generate New Jekyll project

Start Development Server

To start the development server,

  1. Change directory into your Jekyll project directory.
    $ cd jekyll-blog
Enter fullscreen mode Exit fullscreen mode
  1. Build the site and start the server to make it available on your local machine.
    $ bundle exec jekyll serve
Enter fullscreen mode Exit fullscreen mode

Start Jekyll Development Server

  1. Browse to http://localhost:4000 to see your new Jekyll blog.

Jekyll blog running in the browser

⚠️ WARNING:
For Ruby version 3.0.0 or higher, bundle exec jekyll serve may not work. You can fix it by adding webrick to your dependencies: bundle add webrick. See image below.

Jekyll webrick fix

NOTE:
Add the --livereload option to serve to automatically refresh the page with each change you make to the source files: bundle exec jekyll serve --livereload.

Fetch Blogposts

Data for statically generated website can come from varying sources. This can be markdown files, XML files, JSON, CSV, etc. The default data source for Jekyll is markdown. Fortunately, the data source which is the Strapi REST API is already in markdown format. We need to construct a simple Ruby script to consume the API.

In your Jekyll project directory, create a new ruby file and give it any name you want, I'll name mine jekapi.rb. Copy and paste the following source code into jekapi.rb.

    # Ruby script to consume the Strapi API endpoint
    require 'net/http'
    require 'json'
    require 'ostruct'

    url = 'http://localhost:1337/api/post?populate=*'
    uri = URI(url)
    response = Net::HTTP.get(uri)

    result = JSON.parse(response, object_class: OpenStruct)

    result.data.each do |document|
        url = 'http://localhost:1337/api/posts?populate=*'
    uri = URI(url)
    response = Net::HTTP.get(uri)

    result = JSON.parse(response, object_class: OpenStruct)

    result.data.each do |document|
        post_file_name_suffix = document.attributes.Slug
        post_file_name_prefix = document.attributes.createdAt
        post_file_name_prefix.slice!(10..24)
        post_file_name = "#{post_file_name_prefix}-#{post_file_name_suffix}"

        post_file_title = document.attributes.title

        post_file_date = document.attributes.createdAt

        post_file_description = document.attributes.description

        post_file_author = document.attributes.author.data.attributes.username

        post_file_content = document.attributes.content

        post_file = File.new("_posts/#{post_file_name}.md", "w")
        post_file.puts("---")
        post_file.puts("layout: post")
        post_file.puts("title: "\"#{post_file_title}\"\")"
        post_file.puts("date: #{post_file_date}")
        post_file.puts("description: "#{post_file_description}\")"
        post_file.puts("author: #{post_file_author}")
        post_file.puts("---")
        post_file.puts("#{post_file_content}")
      end
Enter fullscreen mode Exit fullscreen mode

Run the script below in your terminal:

    $ ruby jekapi.rb
Enter fullscreen mode Exit fullscreen mode

Your _posts folder should have your Strapi posts with extension *.md.

This Ruby script will fetch the blog posts from the api endpoint http://localhost:1337/api/post?populate=*. Requesting using this URL with a * wildcard query will populate all the fields defined in our Strapi API. Refer to the Strapi Documentation - REST API: Population & Field Selection for further details.

The script loops through all the JSON data and creates posts which are added to the _posts folder using the Jekyll post naming convention.

Display Posts List

The next step is to display the list of articles for our blog.

    $ bundle exec jekyll serve
Enter fullscreen mode Exit fullscreen mode

The Jekyll site at http://localhost:4000 should now be displaying a list of our Strapi posts on the homepage:

List articles from Strapi API

Now, we have a fully functional blog. You can read any post by clicking the link in the home page. Each post will merge with the theme settings.

All the data from the Strapi API has been successfully retrieved and displayed. This includes the title, author, date, description and content.

Individual Jekyll article from Strapi API

Now that we have set up our blog, let's power it up with some plugins

Plugin Setup

The next stage involves setting up our various plugins. We'll take them one after the other. Let's begin!

i18n Plugin

Internationalization is the process of developing your software so it can be localized to a particular audience that may vary based on culture, language, or region. It could mean removing all the hard-coded strings in your application and putting them in a JSON file. It is a cool feature you can add to your blog to cover a much wider audience.

The Strapi Internationalization (i18n) Plugin allows Strapi users to create, manage and distribute translated content in multiple languages.

Features

This plugin was developed in house by the Strapi Team. Its features include the following:

  • Admin panel users can create several localized versions of their content.
  • Developers can build localized projects by fetching and consuming the right content depending on the country/language of the audience.

Installation

Strapi v4 comes with i18n plugin by default. The other way is through NPM. To install this plugin, you need to add an NPM dependency to your Strapi application:

    # Using Yarn
    yarn strapi install i18n

    # Or using NPM
    npm run strapi install i18n
Enter fullscreen mode Exit fullscreen mode

Configuration

A STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE environment variable can be configured to set the default locale for your environment. The plugin uses an ISO country code as the value for the environment variable.

This is useful when a Strapi application is deployed in a production environment, with the i18n plugin enabled

How to Use i18n With the REST API

Our blog is using Strapi as a REST API endpoint. The i18n plugin adds new features to the REST API:

  • A new locale parameter to fetch content for a specified locale
  • Creating and updating localized entries

Our blog will fetch localized entries with the locale parameter. The response to requests will include a string field locale for the locale code for the content entry and an object localizations which contains a data array of the id and attributes of the localization.

Go back to your Strapi Admin Dashboard and make sure that internationalization is enabled. Navigate to General > Plugins and make sure that internationalization is seen on the list of installed plugins:

List of Installed Plugins in Strapi

If you face any issues with installation, refer to the Strapi i18n plugin documentation.
Let's set up a new locale for our blog. Proceed to Settings > Internationalization and click on "Add new locale". For this tutorial, choose French (fr):

Add new Locale in Strapi

We need to enable localization for the Post collection. Navigate to Content-Type Builder > Post, click on Edit. Inside the pop-up, select Advanced Settings and check the box labeled Enable localization for this Content-Type. Wait for your server to restart for the changes to take effect:

Enable Localization for the Content-Type in Strapi

Next, add translations to your blog posts. Go to Content Manager > COLLECTION TYPES > Post. Select one of your blog post entries. You should see the INTERNATIONALIZATION tab in the side panel with a Locales drop-down:

Internationalization available for Collection-Type in Strapi

Click on the Locales drop-down and create content for your locale. After selecting your second locale, you’ll be taken to a new page to enter your translated content:

Create post for French locale

Once you’ve created your content, click Save. Repeat the same procedure for the other posts and you should have a few published entries with content available in multiple locales:

Strapi Posts with multiple Locales

At the frontend, we need a way to consume the new locale data for our blog. Update jekapi.rb with the locale data from the Strapi API endpoint:

    #jekapi.rb

    require 'net/http'
    require 'json'
    require 'ostruct'

    url = 'http://localhost:1337/api/posts?populate=*'
    uri = URI(url)
    response = Net::HTTP.get(uri)
    result = JSON.parse(response, object_class: OpenStruct)
    result.data.each do |document|
        post_file_locale_def = document.attributes.locale
        post_file_name_suffix = document.attributes.Slug
        post_file_date = document.attributes.createdAt
        post_file_name_prefix = document.attributes.createdAt
        post_file_name_prefix.slice!(10..24)
        post_file_name = "#{post_file_name_prefix}-#{post_file_name_suffix}"
        post_file_title = document.attributes.title
        post_file_description = document.attributes.description
        post_file_author = document.attributes.author.data.attributes.username
        post_file_content = document.attributes.content

        post_file = File.new("_posts/#{post_file_name}.md", "w")
        post_file.puts("---")
        post_file.puts("layout: post")
        post_file.puts("title: \"#{post_file_title}\"")
        post_file.puts("date: #{post_file_date}")
        post_file.puts("description: #{post_file_description}")
        post_file.puts("author: #{post_file_author}")
        post_file.puts("locale: #{post_file_locale_def}")
        post_file.puts("---")
        post_file.puts("#{post_file_content}")

        post_file_locale = document.attributes.localizations.data[0].attributes.locale
        post_file_title_locale = document.attributes.localizations.data[0].attributes.title
        post_file_description_locale = document.attributes.localizations.data[0].attributes.description
        post_file_content_locale = document.attributes.localizations.data[0].attributes.content

        post_file_alt = File.new("fr/_posts/#{post_file_name}.md", "w")
        post_file_alt.puts("---")
        post_file_alt.puts("layout: post")
        post_file_alt.puts("title: \"#{post_file_title_locale}\"")
        post_file_alt.puts("date: #{post_file_date}")
        post_file_alt.puts("description: #{post_file_description_locale}")
        post_file_alt.puts("author: #{post_file_author}")
        post_file_alt.puts("locale: #{post_file_locale}")
        post_file_alt.puts("---")
        post_file_alt.puts("#{post_file_content_locale}")
      end
Enter fullscreen mode Exit fullscreen mode

Create a folder for your French content in your Jekyll working directory. Name the folder fr to match with the locale: fr configured in the Strapi dashboard. Within fr, create a directory named _posts.

Run the jekapi.rb script, then launch your Jekyll site. Open one of the posts and add a /fr/ prefix to the site link to view the French version of your post. There you have it: a simple implementation of internationalization in your website:

Jekyll Blog Post with multiple locales

SEO Plugin

What's a good blog without some SEO?. The Strapi Team developed the Strapi plugin SEO to help with that.

Features

  • Easily see which Content-Types have the SEO Component or not.
  • Preview content in the Search Engine Results Page (SERP).
  • Manage important meta tags like metatitle and metadescription.
  • Manage meta social tags (Facebook and Twitter) for your content.
  • Get strong SEO analysis for your content.

Installation

Install the SEO plugin by adding it as an NPM dependency to your Strapi backend application.

    # Using Yarn
    yarn add @strapi/plugin-seo

    # Or using NPM
    npm install @strapi/plugin-seo
Enter fullscreen mode Exit fullscreen mode

Configuration

After installing, navigate to ./config/plugins.js in your Strapi backend and add:

    module.exports = ({ env }) => ({
      // ...
      seo: {
        enabled: true,
      },
      // ...
    });
Enter fullscreen mode Exit fullscreen mode

Build your admin panel, then start your Strapi server:

    $ yarn build
    $ yarn develop
Enter fullscreen mode Exit fullscreen mode

Your Strapi dashboard should now have SEO listed under Plugins:

Strapi Dashboard with SEO Plugin

How to Use It

Now that we have learnt how to install and configure it, here's how to use it:

  1. Go to localhost:1337/admin/plugins/seo.
  2. Under the Collection Types tab, select +Add component for the Post collection type. You will be directed to the Content-Type Builder for the Post collection. The SEO plugin enables you to add shared components to your collection type. Listed under the Shared components is MetaSocial and SEO:

Strapi Content Type Builder with SEO Plugin

  1. Next, select Add another field in Post under Collection Types.
  2. Choose Component from the pop-up.
  3. In the Add new component menu, select Use an existing component and click on Select a component. The Select a component drop-down will show the available existing components from the SEO plugin, shared - metaSocial and shared - seo.
  4. Choose shared - seo and name it seo. Click Finish then Save and wait for your server to restart:

Add seo component to Strapi Content Type

The seo component should now be listed under the Post collection type in the Content-Type Builder and if you check the SEO plugin menu you will find Post collection type has been added:

Strapi SEO plugin with added collection type

Now for the fun stuff. Select one of your posts in the Content Manager. The SEO Plugin menu should be available in the right side section of your post. It contains Browser Preview, Social Preview and SEO Summary for your blog post. Below the Slug text box is the seo component for you to add the necessary SEO entries for your blog post:

Strapi SEO plugin in Content Manager

Click on+ in the seo box. In the pop-up you will see numerous seo entries to fill for your post. Add metaTitle, metaDescription, metaImage and keywords entries for your post, select + Add an entry then click Save:

Add SEO entries to post in Strapi Content Manager

The SEO Summary will give you hints together with the SEO Analyzer to improve your SEO entry performances.

SEO Summary in Strapi Content Manager

The SEO Analyzer provides more context for your SEO to boost your performance so that you can have an SEO friendly metatitle and metadescription in your blog.

SEO Analyzer in Strapi Content Manager

For more in-depth uses for the Strapi SEO Plugin check out The first Strapi SEO plugin article.

Cloudinary Provider Plugin

Now that your blog has i18n and improved SEO, an external media management solution can enhance your blog. Visit Cloudinary.

Features

Cloudinary is an image and video management solution for websites and mobile apps. It covers everything from image and video uploads, storage, manipulations, optimizations to delivery. Cloudinary can deliver a large amount of data through a fast Content Delivery Network (CDN). This frees your backend from performance bottlenecks and frees up resources on your server.

Installation

To install the cloudinary provider plugin:

  1. Create a free Cloudinary account and after verifying your email, you will be redirected to the management dashboard of your account:

Cloudinary Account Management Dashboard

  1. Copy and save the following Account Details:
  • Cloud Name
  • API Key
  • API Secret

SECURITY REMINDER
Save your account credentials somewhere safe and keep them secret.

  1. Go back to your Strapi blog backend and stop the server using Ctrl + C. 4. Install the Strapi Cloudinary Provider Plugin:
    # using yarn
    yarn add @strapi/provider-upload-cloudinary

    # using npm
    npm install @strapi/provider-upload-cloudinary --save
Enter fullscreen mode Exit fullscreen mode

Configuration

a. Provider Configuration
Add the following to ./config/plugins.js:

    module.exports = ({ env }) => ({
      // ...
      upload: {
        config: {
          provider: 'cloudinary',
          providerOptions: {
            cloud_name: env('CLOUDINARY_NAME'),
            api_key: env('CLOUDINARY_KEY'),
            api_secret: env('CLOUDINARY_SECRET'),
          },
          actionOptions: {
            upload: {},
            uploadStream: {},
            delete: {},
          },
        },
      },
      // ...
    })
Enter fullscreen mode Exit fullscreen mode

In the root directory of your Strapi blog backend, create a .env file and add the following variables and with their respective values. These can be found in your Cloudinary dashboard under Account Details:

CLOUDINARY_NAME = cloudinary-name
CLOUDINARY_KEY = cloudinary-key
CLOUDINARY_SECRET = cloudinary-secret
Enter fullscreen mode Exit fullscreen mode

Security Middleware Configuration

Due to the default settings in the Strapi Security Middleware, you will need to modify the contentSecurityPolicy settings to properly see thumbnail previews in the Media Library i.e. you will be able to preview images uploaded to Cloudinary in your Strapi Admin dashboard. You should replace strapi::security string with the object below in ./config/middlewares.js as explained in the middleware configuration documentation.

    module.exports = [
      // ...
      {
        name: 'strapi::security',
        config: {
          contentSecurityPolicy: {
            useDefaults: true,
            directives: {
              'connect-src': ["'self'", 'https:'],
              'img-src': ["'self'", 'data:', 'blob:', 'dl.airtable.com', 'res.cloudinary.com'],
              'media-src': ["'self'", 'data:', 'blob:', 'dl.airtable.com', 'res.cloudinary.com'],
              upgradeInsecureRequests: null,
            },
          },
        },
      },
      // ...
    ];
Enter fullscreen mode Exit fullscreen mode

Restart your Strapi server to complete the configuration. After uploading an image, it will upload to Cloudinary.

How to Use It

To use the newly-installed plugin,

  1. Upload an image to one of your posts in Post collection in the Content Manager.
  2. Select Add new assets and then upload an image.
  3. Tick the one you want and click on Finish.

Add image to Strapi Post

Your blog post now has a link to your image hosted on the Cloudinary cloud provider.

Link to image hosted on Cloudinary

Navigate to your Cloudinary Management Console - Media Library and you should see the images you uploaded appear there.

Cloudinary Management Console - Media Library

Next let's rebuild our Jekyll site to see the changes take effect. In your Jekyll frontend working directory stop the Jekyll server using Ctrl+C if you haven't already. Next, in the root folder of your Jekyll blog, clean your site:

    $ bundle exec jekyll clean
Enter fullscreen mode Exit fullscreen mode

Run the jekapi.rb script to update your posts, then start the Jekyll server

    $ ruby jekapi.rb
    $ bundle exec jekyll serve
Enter fullscreen mode Exit fullscreen mode

Navigate to the post you have updated with an image. If you have configured your Cloudinary Upload Provider plugin correctly, an image should appear in your post and if you inspect the html for the image, it should show the cloudinary url to the image.

Jekyll post with image hosted on Cloudinary

Now your blog can benefit from faster performance loading images hosted on a CDN at the same time off loading some work for your Strapi backend server.

Conclusion

That's it. You have seen the power and ease of creating a Jekyll blog powered by Strapi as a headless CMS to store your content and provide the content securely through a REST API. You powered up your blog by adding Internationalization, SEO and Cloudinary as an external upload provider to help manage your media and improve loading speed of your media assets.

Next, you could look at a deployment strategy for your blog on a production server. See this Strapi deployment guide. You can also tinker with adding some more plugins to your blog by checking out the numerous options on the Strapi Market

I hope you were able to follow along. Here's the repo with the complete source code to test out the full working version of the blog.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .