Logo Strapi et Nuxt

Intégrer Strapi sur Nuxt

C’est quoi Strapi ?

Strapi est un CMS headless, ce qui vous permet de créer votre propre API et de le diffuser sans avoir de contraintes.

Bannière Strapi

Strapi

Un CMS headless open-source pour créer et diffuser votre contenu partout.

Backend avec Strapi

Installation de Strapi

Avant d’installer le CMS, veuillez vous prémunir de Node.js v20.

bash
npx create-strapi-app@latest my-project

Ou avec yarn :

bash
yarn create strapi-app my-project --quickstart

Avec cette commande, vous allez suivre un simple process pour l’installer. Rien de plus simple. Pour la suite, nous utilisons SQLite (par défaut) dans cet exemple, mais libre à vous d’installer ce que vous voulez en base de donnée.

bash
thomasbnt@thomasbnt:~/lab$ yarn create strapi-app my-project --quickstart
yarn create v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...

success Installed "create-strapi-app@4.19.0" with binaries:
      - create-strapi-app
Creating a quickstart project.
Creating a new Strapi application at /lab/my-project.
Creating files.
Dependencies installed successfully.
Initialized a git repository.

Your application was created at /lab/my-project.

Available commands in your project:

  yarn develop
  Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)

  yarn start
  Start Strapi without watch mode.

  yarn build
  Build Strapi admin panel.

  yarn strapi
  Display all available commands.

You can start by doing:

  cd /lab/my-project
  yarn develop

Running your Strapi application.

> my-project@0.1.0 develop
> strapi develop

 Building build context
 Building build context[INFO] Including the following ENV variables as part of the JS bundle:
    - ADMIN_PATH
    - STRAPI_ADMIN_BACKEND_URL
    - STRAPI_TELEMETRY_DISABLED
 Building build context (100ms)
 Creating admin (10071ms)
 Loading Strapi[2024-01-27 18:49:09.061] info: The Users & Permissions plugin automatically generated a jwt secret and stored it in .env under the name JWT_SECRET.
 Loading Strapi (2075ms)
 Generating types (320ms)

 Project information

┌────────────────────┬──────────────────────────────────────────────────┐
 Time               │ Sat Jan 27 2024 18:49:10 GMT+0100 (Central Euro… │
 Launched in        │ 2405 ms                                          │
 Environment        │ development                                      │
 Process PID        │ 19885 Version            │ 4.19.0 (node v20.2.0) Edition            │ Community                                        │
 Database           │ sqlite                                           │
└────────────────────┴──────────────────────────────────────────────────┘

 Actions available

One more thing...
Create your first administrator 💻 by going to the administration panel at:

┌─────────────────────────────┐
 http://localhost:1337/admin │
└─────────────────────────────┘

[2024-01-27 18:49:11.419] http: GET /admin (12 ms) 200
[2024-01-27 18:49:11.454] http: GET /admin/runtime~main.b145af60.js (6 ms) 200
[2024-01-27 18:49:11.463] http: GET /admin/main.5eaa19e8.js (2 ms) 200
[2024-01-27 18:49:11.827] http: GET /admin/project-type (2 ms) 200
[2024-01-27 18:49:11.846] http: GET /admin/6707.d7b87269.chunk.js (2 ms) 200
[2024-01-27 18:49:11.983] http: GET /admin/6538.27d4c381.chunk.js (3 ms) 200
[2024-01-27 18:49:11.984] http: GET /admin/9719.fe70b828.chunk.js (2 ms) 200
[2024-01-27 18:49:11.984] http: GET /admin/1025.2d854ef2.chunk.js (2 ms) 200
[2024-01-27 18:49:11.989] http: GET /admin/5019.0d8113a1.chunk.js (3 ms) 200
[2024-01-27 18:49:11.990] http: GET /admin/4944.c9cc5f7f.chunk.js (3 ms) 200
[2024-01-27 18:49:11.991] http: GET /admin/9170.6aa61d26.chunk.js (3 ms) 200
[2024-01-27 18:49:11.994] http: GET /admin/1727.8847f948.chunk.js (1 ms) 200
[2024-01-27 18:49:12.048] http: POST /admin/renew-token (9 ms) 400
[2024-01-27 18:49:12.051] http: GET /admin/init (16 ms) 200
[2024-01-27 18:49:12.054] http: GET /admin/users/me (18 ms) 401
[2024-01-27 18:49:12.144] http: GET /admin/3067.4f4141cb.chunk.js (1 ms) 200
[2024-01-27 18:49:12.149] http: GET /admin/telemetry-properties (2 ms) 401
[2024-01-27 18:49:12.354] http: GET /admin (2 ms) 200
[2024-01-27 18:49:12.588] http: GET /admin/project-type (1 ms) 200
[2024-01-27 18:49:12.686] http: GET /admin/init (2 ms) 200
[2024-01-27 18:49:12.811] http: GET /favicon.ico (0 ms) 200

Vous avez toute la documentation de disponible.

Après avoir tout installé ainsi que les dépendances, le serveur se lance automatiquement comme vous pouvez le voir juste au-dessus. Cependant, si cela n’a pas été exécuté, faites yarn develop.

Créer votre compte sur le dashboard

Quand vous allez sur http://localhost:1337 pour la première fois, on vous demandera de créer un compte Super Admin.

Page d’inscription Strapi pour le premier compte Super Admin avec les champs textes comme le prénom, nom, adresse e-mail et mot de passe.

Youhou ! Vous avez accès à Strapi ! ✨🚀

Dashboard Strapi avec le menu à gauche et le contenu au centre.

Création de la Collection

Dans cet exemple, nous allons créer une collection pour afficher les dernières mises à jour d’un robot Discord, comme ça, on pourra l’afficher où on le souhaite, dans ce cas-là, sur le site web sous Nuxt mais aussi avec une commande Slash sur la plateforme Discord à travers le robot !

Allons dans Content-Type BuilderCollections TypesCreate new collection type.

Création d’une collection type dans Strapi.

Nous allons lui donner un nom propre "ChangelogMrRobotApp” (Ici Mr. Robot fait référence au nom du robot). Puis créer des champs “fields” en cliquant sur le bouton Add new field.
Dans mon cas, je veux simplement afficher :

  • Le titre
  • La version
  • La date de release
  • Le contenu de la version (content)
  • Le slug
  • Et une bannière, mais qui est optionnelle

Puis, nous remplissons tous ces champs dans l’onglet Content Manager. Et nous pourrons passer au front !

Création d’une collection type dans Strapi.

Intégration sur le front sous Nuxt

Je prends Nuxt pour la partie front, car le site web du robot est sous ce framework. Mais libre à vous de l’arranger comme bon vous semble. Ce n’est qu’une requête fetch et du JavaScript.

Création du token API

Avant de continuer sur le code, nous allons créer un Token API, Settings → API Tokens → Add new API Token. Ce que nous voulons, c’est simplement GET la Collection, sans avoir d’autres permissions. Il nous permettra de récupérer les informations depuis l’API. Ce token devrait être privé.

  • Token type en “Read-only”
  • Token duration en “Unlimited”
  • Et permissions seulement sur “find” et “findOne” sur la Collection

Page de Strapi pour créer un nouveau Token API, on y retrouve le nom, description, la durée du token, le type (ici en lecture seule), et les permissions qu’il aura. (ici seulement la Collection ChangelogMrRobotApp)

Récupération des données avec les call API

Maintenant, nous allons pouvoir récupérer depuis l’API de Strapi les données de la Collection. Ayant un contenu sous Markdown, nous devons procéder à une étape en plus, celle de transformer le texte markdown en HTML. Pour ce faire, j’utilise le paquet markdown-it.

Première fonction : Récupérer la data depuis l’API

Tout simplement avec useFetch de Nuxt. On récupère notre data, et on peut la mettre dans une ref.

./pages/changelog.vuejs
const config = useRuntimeConfig();
let changelogs = ref([]);

await useFetch(`${config.public.backendStrapiUrl}changelogs-mr-robot-app?populate=*&sort[0]=version:desc`, {
  headers: {
    Authorization: `Bearer ${config.public.backendStrapiPublicAPIToken}`
  }
}).then((response) => {
  changelogs = response.data._value;
});
  • Ici, backendStrapiUrl contient l’URL de Strapi avec l’API endpoint pour récupérer la Collection des changelogs, en populate (voir ce que c’est le populate) et trié en fonction de la version en descendant.
  • Et backendStrapiPublicAPIToken comme son nom l’indique est votre Token !

On obtient bien un tableau avec tout ce qu’on souhaite. Magie !

Transformer le contenu (content) du Markdown → HTML

Avec markdown-it , nous allons pouvoir faire encore plus de magie. Installez le paquet, et ajoutez-le dans le component/page.

./pages/changelog.vuejs
import MarkdownIt from "markdown-it";
const md = new MarkdownIt();

changelogs.data.forEach((changelog) => {
  changelog.attributes.content = md.render(changelog.attributes.content);
});

function formatDate(date) {
  const options = { year: "numeric", month: "long", day: "numeric" };
  return new Date(date).toLocaleDateString("fr", options);
}

J’ai ajouté une fonction en plus nommé formatDate, elle permet tout simplement de mettre la date au bon format.

Résultat sur une page

Et maintenant… (roulement de tambours)… il faut intégrer cette partie dans votre corps HTML !

./pages/changelog.vuehtml
<article v-for="l in changelogs.data" :key="l.id" v-show="changelogs">
  <NuxtLink :to="'#' + l.attributes.slug">
    <h3 class="changelog_title" v-if="l.attributes.title" :id="l.attributes.slug">{{ l.attributes.title }}</h3>
  </NuxtLink>
  <div class="changelog_infos">
    <div
      v-if="l.attributes.releasedAt">
      <Icon name="lucide:calendar" />
      Sorti le {{ formatDate(l.attributes.releasedAt) }}
    </div>
    <div v-if="l.attributes.version">v.{{ l.attributes.version }}</div>
  </div>
  <div v-html="l.attributes.content" v-if="l.attributes.content"></div>
</article>

Avec un peu de CSS, on rend ça avec style, et voici le résultat !

Résultat du code avec les changelogs, intégrant donc le call API de Strapi, et l’utilisation du paquet markdown-it pour transformer le markdown en HTML.

Cette page web est disponible sur mrrobot.app/changelog si vous êtes curieux. 🚀

Conclusion

J'ai découvert Strapi, il y a pas mal de temps. Et je n'avais rien créé avec, jusqu'à que j'ai eu un projet, où j'ai je l'ai proposé. Depuis, je l'aime beaucoup. Pour sa facilité d'utilisation, sa documentation, sa gestion d'API, et surtout, sa simplicité d'intégration avec n'importe quel framework.


Soutenez-moi
Si vous aimez mon contenu, vous pouvez me soutenir en faisant un don récurant ou spontanément sur Buy Me a Coffee.