[Hugo]: Strapi CMS And Hugo integration
Published: 2023-07-14 13:36:59

Hi there!
First, what you need to know is that you can fetch data from the Strapi API using JavaScript.

In this test project, we are using [Render.com](https://render.com/) to deploy the Strapi database and [Netlify.com](https://www.netlify.com/) to deploy the Hugo frontend.

[1] Create [database](https://dashboard.render.com/new/database) in Render.com  watch the [video](https://youtu.be/akvItcWW81g). For example:
- **Name:** strapi-v0
- **Database:** sample
- **User:** admin
- **Region:** Oregon
- **Datadog API Key:** [nothing]
- **Instance Type:** free
- click button Create Database

[2] Install Strapi for example 
```
npx create-strapi-app@4.11.4 my-project
- instalation type: Custom
- preferred language: JavaScript
- default database: postgres
and from render.com select your db data:
- database name: sample_5rhn
- host: dpg-cinr7slgkuvudif7bedg-a.frankfurt-postgres.render.com (External Database URL: value after @ and include last .com)
- port: 5432
- username: admin
- password: ahrhvB6JCLPXcZovPsIjXVd3Yl9q4Zdj (render password)
- enable ssl: true
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgyiio7rzgqf7a7l1k49.jpg)
Do `cd my-project` and run `npn run develop` and sign up.

[3] Add entries in Strapi admin:
- Go to Settings > [Internationalization](http://localhost:1337/admin/settings/internationalization) and add other language > click save button.

- Go to Content-type-builder and create **Single Type** like About and Term with field title (text) and content (rich text).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebxkj4nnwkmhfrs0q5ni.jpg)

- Click on **Edit** button near collection Name go to tab **Advanced settings** and checked **Internationalization** field.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmj7fnvgfl0vsinjblxw.jpg)

- Go [to](http://localhost:1337/admin/settings/users-permissions/roles/2) Settings > USERS & PERMISSIONS PLUGIN > Roles > Public > choose your Entries (About, Terms) and checked find input.

- Go to **Content Manager** About and paste some text there. Check it like [http://localhost:1337/api/about?locale=fr&populate=*](http://localhost:1337/api/about?locale=fr&populate=*)

[4] Add Hugo template:
I use for this [Dot Hugo Theme](https://github.com/themefisher/dot-hugo).
- At first we need add to config.toml
```
[params]
# !!! The Strapi server URL !!!
StrapiServerURL = 'https://strapi-hugo-v1.onrender.com/api'
```
- In **layouts/partials** add strapi-content.html and content-after.html

**strapi-content.html**
```
<!-- Partial to fetch content from Strapi. -->

{{ $endpoint := $.Param "endpoint" }}
{{ $data := dict "title" "" "content" "" }}

{{ if and $endpoint .Site.Params.StrapiServerURL }}

{{ $contentURL := printf "%s%s" .Site.Params.StrapiServerURL $endpoint }}
{{ $data = getJSON $contentURL }}

{{ end }}

{{ $data }}

{{ return $data }}
```

**content-after.html**

```
{{ $strapiData := partial "strapi-content" . }}

{{ if $strapiData }}
<article class="markdown">
  {{/*  <h1>{{ $strapiData.title }}</h1>  */}}

  <div class="mt-4">
    {{ $strapiData.data.attributes.content | markdownify }}
  </div>
</article>
{{  end }}
```

and add to **/dot/layouts/partials/default.html** or **/layouts/_default/list.html**

```
 {{ partial "content-after.html" . }}
```

- Create in Content **dot\content** folrder about and folder terms with _index.en.md and _index.fr.md
```
---
title: "About Us EN"
endpoint: "/about?locale=en"
---

<br/>
```

- in config.toml Check if languages added:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4vi748fpe2q6ed08wze.jpg)

[5] Publick strapi folder with hugo theme folder inside to github.
[6] Choose your repository in render **[Create a new Web Service](https://dashboard.render.com/select-repo?type=web)** don't forgot your .env local variables 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2xyv1b6j4eympr0tewe.jpg)
Add or .env like:
```
HOST=0.0.0.0
PORT=1337
APP_KEYS=Qou0bjHyhL/cOmRvQUCyrw==,9SwSrmPSfBsZFPYGGVH+Tw==,w9m8P+0A0r+Vq2bk7p93uw==,c5+P9PwXVgHiNAuOjT1Kog==
API_TOKEN_SALT=+LDbAS4rDx/lJ10uLWcxCw==
ADMIN_JWT_SECRET=+qIl5IOcV/44HYGCSHKi4A==
JWT_SECRET=P3pmatNaY0rFyK6xVSLl9w==
CLOUDINARY_KEY=523224738358411
CLOUDINARY_NAME=dzmcv05wy
CLOUDINARY_SECRET=-dZ793AJNiHbkTIRElvFmsjlHtk
DATABASE_CLIENT=postgres
DATABASE_HOST=dpg-cinr7slgkuvudif7bedg-a.frankfurt-postgres.render.com
DATABASE_NAME=sample_5rhn
DATABASE_PASSWORD=ahrhvB6JCLPXcZovPsIjXVd3Yl9q4Zdj
DATABASE_PORT=5432
DATABASE_SSL=true
DATABASE_USERNAME=admin
TRANSFER_TOKEN_SALT=qMa3hHbA1p1TrnzR3Q4dTQ==

```
[7] Add Hugo to [Netlify.com](https://www.netlify.com/) with deploy command `hugo --ignoreCache --gc --minify` for my case: 
- all strapi there [https://github.com/anastasiiaxfr/strapi-hugo-v1](https://github.com/anastasiiaxfr/strapi-hugo-v1)
- Hugo there: [folder dot](https://github.com/anastasiiaxfr/strapi-hugo-v1/tree/main/dot)
and on Netlify I add dot folder there

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yh3ewlst1m8qvxowvi8y.jpg)

[8] Add [Netlify Build hook](url) for Strapi update ([read](https://chriswray.dev/posts/triggering-a-deploy-in-netlify-automatically-after-updating-content-in-strapi)): go to Netlify Deployment Setting > [Build Hooks](https://docs.netlify.com/configure-builds/build-hooks/) and add then copy this hook to **Strapi > Settings > Webhooks** and save it. Reload About entry and look at demo on Hugo Netlify.

That's all)

**Strapi:**
[admin](https://strapi-hugo-v1.onrender.com/admin)

- login: anastasiiaberest@gmail.com
- password: Tg6x-ctg6x

**Hugo:**
[about](https://strapi-hugo-v1.netlify.app/about/)

**Git:**
[strapi-hugo-v1](https://github.com/anastasiiaxfr/strapi-hugo-v1)

---

For [cloudinary](https://cloudinary.com/) add **my-project/config/plugin.js** with: 
```
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: {},
      },
    },
  },
});
```
and **my-project/config/middlewares.js**
```
module.exports = [
  'strapi::errors',
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': ["'self'", 'data:', 'blob:', 'market-assets.strapi.io', 'res.cloudinary.com'],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'res.cloudinary.com',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },
  'strapi::cors',
  'strapi::poweredBy',
  'strapi::logger',
  'strapi::query',
  'strapi::body',
  'strapi::session',
  'strapi::favicon',
  'strapi::public',
];

```