DEV Community

Sacha Bouillez
Sacha Bouillez

Posted on • Updated on

Créez votre blog (presque) sans code avec Nuxt 3 et Nuxt/Content

Pour certain·e·s, c'est le désir de partager, pour d'autres, c'est une façon de prendre des notes, mais on a tous·tes, en tant que développeur·se, au moins une bonne raison de créer notre propre dev blog. Sauf que bien des fois, on peut se retrouver découragé·e devant la myriade de technologies à notre disposition pour créer un site web, et la potentielle courbe d'apprentissage de celles-ci.

Et si je te dis que grâce à Nuxt 3 et au module Nuxt/Content, il devient beaucoup plus facile de créer un site dit "content-driven", comme le serait notre dev blog.

Nuxt 3 est le framework "piles incluses" de Vue 3. Il est, à l'heure où j'écris cet article, encore en Release Candidate, mais peu de choses devraient changer d'ici la version finale.
Le but de cet article n'est pas de faire une revue détaillée du fonctionnement de Nuxt puisque nous n'allons écrire que peu de code propre au framework mais je t'invite à jeter un oeil à la documentation pour te permettre d'aller plus loin par la suite.

Nuxt/Content est un module Nuxt qui permet au framework de transformer des simples fichiers markdown en véritables pages pour nous permettre de créer un site en se concentrant sur le contenu. Il y a aussi une documentation pour t'aider à approfondir sur le module.

Création du projet

Dans ton terminal préféré, il te suffit de lancer la commande suivante pour initialiser un projet Nuxt :

npx nuxi init mon-blog
Enter fullscreen mode Exit fullscreen mode

Pour être tranquille pour la suite, nous allons installer ce dont on a besoin :

cd mon-blog
npm install
npm i -D @nuxt/content
Enter fullscreen mode Exit fullscreen mode

Le dev server se lance avec la commande :

npm run dev
Enter fullscreen mode Exit fullscreen mode

En navigant sur http://localhost:3000, tu te retrouves alors sur la page de notre nouveau site, auto-générée par la CLI de Nuxt (nuxi).

Afin de pouvoir utiliser le module content, il faut l'ajouter aux modules dans la config Nuxt nuxt.config.ts comme ci-dessous :

import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['@nuxt/content']
})
Enter fullscreen mode Exit fullscreen mode

Un peu de code

Désolé, il y aura quand même un peu de code... Il faut bien préparer la structure!

Une première page

La première chose à faire est de préparer les pages. Nuxt, par convention, transformera chaque composant Vue déclaré dans le dossier pages en page, dont le chemin sera le nom donné au fichier. Ainsi pages/index.vue va créer une route qui correspond à l'index de notre site. Et c'est ce que nous allons faire avec un placeholder:

<!-- pages/index.vue -->
<template>
  <div>index page</div>
</template>
Enter fullscreen mode Exit fullscreen mode

Ensuite, il nous faut soit retirer le fichier app.vue (et laisser Nuxt wrapper les pages lui même) ou l'éditer pour lui indiquer d'utiliser les pages (et layouts).

<!-- app.vue -->
<template>
  <div>
    <NuxtLayout>
      <NuxtPage/>
    </NuxtLayout>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Si l'on essaie d'accéder à une quelconque adresse autre que l'index, Nuxt nous renverra une erreur 404. Ce qui est normal puisque nous n'avons configuré qu'une unique page.

D'autres pages grâce au catch-all

Pour garder une structure simple dans le cadre de cet article, nous considérerons, que toutes les autres pages sont potentiellement des articles du blog. Pour les exposer, il suffit alors de créer une page dite "catch-all". Sous le dossier pages/, on appellera ce composant [...slug].vue, c'est la convention retenue par Nuxt pour "attraper" tout autre chemin qui n'est pas clairement défini comme une page (comme l'est index.vue).

<!-- pages/[...slug].vue -->
<template>
  <main>
    <ContentDoc />
  </main>
</template>
Enter fullscreen mode Exit fullscreen mode

Et ça suffit pour le moment pour le code. Mais qu'est-ce que ce composant ContentDoc et d'où sort-il ?

Il s'agit d'un composant auto-importé par Nuxt, exposé par le module Content qui a deux fonctionnalités:

  • Récupérer le contenu d'un fichier markdown.
  • Faire le rendu de celui-ci.

Où va-t-il récupérer le contenu ? C'est le sujet de la suite !

Ajouter du contenu

Par convention, le module content ira chercher tout fichier markdown, yaml, json et même csv dans un dossier content/ situé à la racine.

C'est donc parti pour écrire notre premier post en créant un fichier Markdown content/mon-premier-post.md.

# Mon premier post

Ceci est le contenu du premier post de mon blog Nuxt + Content.
Enter fullscreen mode Exit fullscreen mode

Et juste avec ça, nous venons de créer le premier post de notre blog! En navigant vers http://localhost:3000/mon-premier-post, on peut voir le contenu parsé et rendu en HTML équivalent à notre Markdown.

Rendu de page web avec pour titre 'Mon premier post' et un paragraphe exemple

Pour donner un peu plus de contenu, nous allons créer un deuxième post avec content/un-autre-post.md.

# Un autre post

Et voici un autre post, le premier s'ennuyait.
Enter fullscreen mode Exit fullscreen mode

Et une autre page est ajoutée à notre site : https://localhost:3000/un-autre-post

Ajouter la navigation

Maintenant que nous avons quelque posts, il serait intéressant de pouvoir accéder à ceux-ci depuis notre page d'accueil. Nuxt/Content expose le composant 'ContentNavigation', il s'agit d'un composant dit "renderless": ce composant ne fait aucun rendu mais expose des variables et méthodes à ses composants enfants. Reprenons notre page index.vue comme ceci:

<template>
  <div>
    <h1>Mon blog Nuxt 3 + Content 2</h1>
    <nav>
      <ul>
        <ContentNavigation v-slot="{ navigation }">
          <li v-for="link of navigation" :key="link._path" >
            <NuxtLink :to="link._path">
              {{ link.title }}
            </NuxtLink>
          </li>
        </ContentNavigation>
      </ul>
    </nav>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

Le composant ContentNavigation génère une liste de liens vers chacune des pages que nous avons créées et les expose auto-magiquement au travers de navigation. Si cette mécanique Vue appelée "scoped slots" t'es inconnue, voici la documentation.

Allez plus loin

Maintenant que nous avons une structure, il est temps d'ajouter un peu d'âme et de customisation à notre blog.

Modifier les composants Markdown (Prose)

Il est très facile de surcharger les composants utilisés par Nuxt/Content pour transformer le markdown en HTML. Voici la liste des composants Prose que Nuxt/Content met à notre disposition.

Ainsi, en déclarant un composant ProseH1.vue dans un dossier components/content/ comme ceci:

<!-- components/content/ProseH1.vue -->
<template>
  <h1><slot /></h1>
</template>

<style scoped>
h1 {
  color: red;
  font-weight: bold;
}
</style>
Enter fullscreen mode Exit fullscreen mode

Tous les h1 générés par les # markdown sont maintenant rouge et en gras, comme décidé dans notre composant ProseH1 !

La syntaxe MDC

Toujours dans l'optique de centrer la création des sites sur le contenu, le module Nuxt/Content apporte une syntaxe Markdown particulière : les MDC (ou MarkDown Components). Nous allons pouvoir créer des composants Vue et les réutiliser directement depuis nos fichiers de contenu en Markdown. Cette syntaxe va nous permettre d'utiliser les nombreuses API des composants Vue (props, slots...) depuis les fichiers Markdown.

Voici un bouton pour l'exemple, qu'on mettre lui aussi dans components/content :

<!-- components/content/CustomButton -->
<script setup lang="ts">
defineProps<{ color: string }>()

const sendAlert = () => alert('Hello :)')
</script>

<template>
  <button @click="sendAlert" :style="{ color }">
    <slot />
  </button>
</template>
Enter fullscreen mode Exit fullscreen mode

Allons éditer notre premier post pour y ajouter ce bouton :

# Mon premier post

Ceci est le contenu du premier post de mon blog Nuxt + Content.

::CustomButton{color='red'}
clique sur moi!
::
Enter fullscreen mode Exit fullscreen mode

On peut directement passer des props au composant, comme nous avons passé color dans cet exemple! Cette syntaxe supporte même les named slots.

Image description

Je te laisse approfondir dans la documentation. Tout composant déclaré dans components/content sera accessible depuis les fichier Markdown de contenu, les possibilités sont presque infinies!

Cette article reste une introduction très basique à Nuxt et au module Content, mais j'espère qu'il te donne une idée du monde de possibilités que ces technologies offrent. A considérer aussi qu'à l'heure ou j'écris cet article, elles sont encore jeunes (nuxt@3.0.0RC-6 et @nuxt/content@v2.0.1), et seront surement amenées à évoluer.

Tu peux retrouver le code de cet article sur ce repo. Je t'invite aussi à passer sur mon dev blog, réalisé avec Nuxt3 et Nuxt/Content, dont tu peux retrouver le code ici!

Oldest comments (4)

Collapse
 
thomasbnt profile image
Thomas Bnt ☕

Superbe !

Cependant, une erreur de frappe dans le premier codeblock.

npx nuxi init mon-blog
Enter fullscreen mode Exit fullscreen mode
Collapse
 
prazdevs profile image
Sacha Bouillez

Non, c'est bien un npx nuxi pour exécuter le binary de nuxi qui est le nouveay cli de nuxt3 :)

Collapse
 
thomasbnt profile image
Thomas Bnt ☕

Oh d'accord :o
Je viens de voir la doc, c'est un peu bizarre comme typo, on dirait une faute de frappe 😆

Collapse
 
necraidan profile image
Benjamin🦸‍♂️Auzanneau™

Sympa l'article.
Je cherchais une solution pour mon blog ayant essayé docusaurus et next.js, j'avais une envie de pousser plus sur du vue...
Merci !