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](https://sebastienviande.name/blog/learning-process-to-become-a-top-notch-developer/) 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](https://www.gatsbyjs.org/) qui est un framework basé sur [React](https://reactjs.org).
Pour ma veille technologique j'utilise principalement [Wallabag](https://www.wallabag.it/fr) 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](/blog/gatsby.png)
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
1. Création de la structure pages "weekly" et associations avec les articles lus
1. 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`.
```javascript
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`:
```javascript
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](https://twitter.com/sviande)