Gatsby + Wallabag = ❤️ weekly tech read

September 16th, 2020 · 6 min read

Quel est le problème ?

Ma volonté cette année est de partager mon expérience, une chose que je trouve chronophage c'est de s'organiser et trouver les bonnes informations pour faire de la veille technologique. J'ai décrit mon organisation dans un blog post précédent, il me reste à partager ce que je trouve et lis.

Pour cela je souhaite avoir sur mon site, des pages représentant une semaine de lecture avec les liens vers les différents articles.

L'architecture du site

Ce site est généré par Gatsby qui est un framework basé sur React. Pour ma veille technologique j'utilise principalement Wallabag sur une instance que j'héberge moi-même. Wallabag me permet de sauvegarder des articles à lire plus tard, je peux les consulter sur mon PC et surtout en mode hors-ligne sur mon téléphone. Wallabag est une superbe alternative open-source à Pocket. Il me faut donc importer dans Gatsby les articles lus dans Wallabag.

Gatsby utilises des datas sources et rends les données accessible via GraphQL.

Fonctionnement de Gatsby

Il est donc possible via un système de plugin source d'importer des données provenant de fichier, d'API, etc. L'un des plugins source le plus utilisés est gatsby-source-filesystem il importe des fichiers locaux dans Gatsby.

D'autres plugins peuvent utiliser les données et générer de nouveaux nœud par exemple gatsby-transformer-remark qui transforme du contenu markdown pour générer du contenu HTML. C'est avec ces outils que cet article est écrit un fichier markdow importé ensuite transformé en HTML puis inclut dans une page.

Pour Wallabag je vais utiliser l'API qui permet entre autres d'avoir la liste des articles.

La solution

J'ai donc décider de développer un plugin source qui interroge une instance Wallabag, sauvegarde les articles en tant que nœud dans Gatsby. Pour créer les pages "weekly" je prends les nœuds qui m'intéresse (les artices lus) et les groupes via la date de lecture.

Voici dons les différentes étapes dans le workflow Gatsby:

  1. Téléchargement des articles
  2. Création de la structure pages "weekly" et associations avec les articles lus
  3. Création des pages

Utilisation gatsby-source-wallabag

Installation

Dans le dossier de votre site Gatsby vous pouvez installer le package via yarn ou npm.

yarn add gatsby-source-wallabag
#ou
npm install --save gatsby-source-wallabag

Configuration

Pour communiquer avec votre instance Wallabag il est nécessaire d'avoir l'url de l'API, les identifiants de l'utilisateur et une API clientID, clientSecret.

https://doc.wallabag.org/fr/developer/api/oauth.html

Il faut maintenant déclarer notre plugin et ses options dans le fichier gatsby-config.js.

module.exports = {
  //...gatbsy options
  plugins: [
    //...other plugins
    {
      resolve: "gatsby-source-wallabag",
      options: {
        URL: "https://wallabag-instance.url",
        clientID: "votre_client_id",
        clientSecret: "votre_client_secret",
        username: "votre_usename",
        password: "votre_mot_de_passe"
      }
    }
  ]
};

Transformer les nodes

Maintenant installé le plugin gatsby-source-wallabag importe automatiquement les articles contenues dans votre instance Wallabag. Pour mon utilisation il est maintenant nécessaire de transformer et préparer cette donnée afin d'ajouter les meta-données nécessaires à la création des pages. Je souhaite que tous les articles archivés soit regroupé par semaine dans une même page.

Pour cela il existe hook dans Gatsby permettant de créer de nouveaux nœuds onCreateNode.

Voici le code contenu dans mon fichier gatsby-node.js

exports.onCreateNode ({node, createNodeId, getNode, actions }) => {
  if (node === "WallabagArticles") {
    manageWeeklyPage({ node, createNodeId, getNode, actions });
  }
});

const manageWeeklyPage = ({ node, actions, createNodeId, getNode }) => {
  //Selection des articles archivés
  if (!node.is_archived) {
    return;
  }

  //Création d'un identifiant pour la page
  const { createNodeField, createNode, createParentChildLink } = actions;
  const articleDate = moment(node.archived_at);
  const pageName = `${articleDate.year()}-${articleDate.isoWeek()}`;

  const pageID = createNodeId(pageName);
  let pageNode = getNode(pageID);
  //Création du node correspondant à la page et contenant les articles
  if (!pageNode) {
    const pageDate = moment(pageName, "YYYY-W");
    pageNode = {
      week: pageDate.isoWeek(),
      year: pageDate.year(),
      date: pageDate.toDate(),
      name: pageName,
      id: pageID,
      parent: null,
      children: [node.id],
      internal: {
        type: "weeklyTechPage",
        contentDigest: createNodeId(pageName)
      }
    };
    createNode(pageNode);
  }

  //Création du lien entre l'article archivé et la page des lectures de la semaine
  createNodeField({
    node,
    name: "parent",
    value: pageID
  });

  createParentChildLink({ parent: pageNode, child: node });
};

Utiliser les nœuds

Nous avons maintenant toutes les données nécessaires pour construire nos pages: un nœud parent représentant un page "weekly" et des noeuds enfants correspondant aux articles lus.

La création des pages depuis la base de données se fait en exportannt la fonction createPages depuis le fichier gatsby-node.js

Il faut tout d'abord rechercher les nœuds pour chaque pages et les articles associés. Avec ces informations nous pouvons créer des pages en utilisant un template.

Voici mon code dans le fichier gatsby-node.js:

exports.createPages = ({ graphql, actions }) => {
  const { createPage } = actions;
  //Recherche des pages avec les articles trier par date
  //Vous pouvez y ajouter vos requetes pour la création des pages via markdown
  return graphql(`
    {
      allWeeklyTechPage(sort: { fields: date, order: DESC }) {
        edges {
          node {
            name
            date
            year
            week
            childrenWallabagArticles {
              id
              url
              tags {
                slug
                label
              }
              reading_time
              title
            }
          }
        }
      }
    }
  `).then(result => {
    //Création d'une page pour chaque semaine
    const weeklyTemplate = path.resolve(
      "./src/templates/weekly-tech-read-graphql.js"
    );
    result.data.allWeeklyTechPage.edges.forEach(({ node }) => {
      createPage({
        path: `weekly-tech-read/${node.name}/`,
        component: weeklyTemplate,
        context: {
          articles: node.childrenWallabagArticles,
          year: node.year,
          week: node.week
        }
      });
    });

    //Création d'une page listant toutes les semaines
    const weeklyRecapTemplate = path.resolve(
      "./src/templates/weekly-tech-recap-graphql.js"
    );
    createPage({
      path: "weekly-tech-read/",
      component: weeklyRecapTemplate,
      context: {
        weeklyPages: result.data.allWeeklyTechPage.edges.map(edge => edge.node)
      }
    });
  });
};

Conclusion

Les pages "weekly" sont maintenant génerer de façon automatique via Gatsby. La création de structure intermédiaire me permet de générer un flux RSS également.

Toutes les semaines j'utilise la CI de Gitlab pour lancer le build du site et le mettre à jour.

Pour aller plus loin je souhaiterais ajouter un système pour mettre plus d'informations. Par exemple un système de priorisation (en mettant des tags spécifique sur les articles). J'aimerais également mettre mon ressenti, mes motivations de la semaine, afficher un résumé exprimant mon avis sur les articles.

D'un point de vue technique le plugin source est très basique il serait intéressant de pouvoir spécifier des paramètres de filtre pour ne pas surcharger la base de données Gatsby.

Je suis pour le moment satisfait de mon setup 😄

Feedback

Je serais très heureux d'avoir vos questions et retours via mon twitter