Cet article est une archive publiée à l'origine sur Medium, le
7.3.2024
Il est présenté ici à titre historique et peut ne pas refléter les dernières informations disponibles ou les pratiques actuelles.
7
·
3
·
2024

Comment nous avons développé un outil d’édition collaborative sur mesure pour nos journalistes

Chez Contexte, notre principal produit d’information est l’e-mail. Les briefings quotidiens sont le fruit d’une intervention croisée d’une multitude d’acteurs, du journaliste au rédacteur-réviseur en passant par le chargé de veille. Après plusieurs années sur Google Docs, les limites de la solution nous ont poussés à développer notre propre outil d’édition collaborative : Echo. Je vous raconte comment.

Tout commence il y a un an, lorsque cet article du New York Times est partagé sur la chaîne Slack de notre équipe tech-produit. Il détaille la conception d’un outil sur mesure d’édition collaborative pour leur rédaction, permettant de travailler à plusieurs sur un même article.

On en rêvait, ils l’avaient fait. Très vite, nous nous sommes demandé comment adapter cette solution à notre échelle, à notre environnement technique et avec nos moyens, humains comme financiers.

"We don’t need roads"

Depuis ses débuts, Contexte publie une newsletter quotidienne, le briefing, constitué d’une dizaine de « brèves » qui informent les abonnés sur l’élaboration des politiques publiques. Avec le temps, la rédaction s’est agrandie. Aujourd’hui, 50 journalistes, basés à Paris et à Bruxelles, couvrent neuf éditions, soit près d’une centaine de brèves rédigées, relues et corrigées quotidiennement.

Notre rôle à la tech est de nous assurer que ce grand orchestre puisse tenir la cadence en fournissant des outils d’édition adaptés à chaque séquence de la production d’un briefing :

  1. Durant l’après-midi, lors de la rédaction des brèves par les journalistes.
  2. Durant la soirée, lors de la correction des briefings par les rédacteurs-réviseurs.
  3. Dès l’aube, pour les ajouts de dernière minute par les journalistes chargés de veille.

Pour éditer son briefing, Contexte s’appuie sur la solution Django, bien connue des développeurs Python pour sa facilité de création de « back-office », mais qui ne permet qu’à une seule personne à la fois d’intervenir sur un même article. Afin de pallier ce manque, Google Docs a été introduit en début de chaîne : les journalistes rédigent l’essentiel du briefing dans un document collaboratif mis en forme avec une syntaxe spéciale, qui est ensuite exporté dans Django. Emballez, c’est pesé !

Sur le papier, cette combinaison d’outils fonctionne et nous a permis de produire plus de 1 750 briefings en 2023. Mais, dans les faits, cette asymétrie d’outillage entre l’équipe de l’après-midi (pré-export) et l’équipe du soir (post-export) démultipliait les problèmes : côté Google Docs, les erreurs de syntaxe aboutissaient à un blocage complet du processus d’export ; côté Django, la rigidité de l’éditeur empêchait aux relecteurs de travailler à plusieurs sur un même briefing. Globalement, cette fragmentation demandait beaucoup de maintenance et était un frein pour faire évoluer le format du briefing.

Durant l’été 2023, lorsqu’il a été question de s’atteler sérieusement à la question de l’outillage, nous avons opté pour une approche de terrain : un développeur (en l’occurrence, votre serviteur) serait chargé de travailler au plus près de la rédac, de collecter ses retours et ses besoins, puis de faire un tour d’horizon des solutions techniques pour dépasser ces limites. Nom de code du projet : 🐬 Echo.

Souviens-toi l’été dernier

C’est contre-intuitif, mais à l’heure de TikTok et des trottinettes électriques, développer un logiciel qui permet de travailler à plusieurs sur un même document reste un problème compliqué à résoudre. Fort heureusement, il existe des solutions payantes et open source qui donnent des billes sur le sujet. Lors de mon tour d’horizon l’été dernier, deux solutions sont sorties du lot.

La première solution d’édition de texte est Prosemirror, qui se distingue par son positionnement : son rôle n’est pas de fournir le maximum d’options de mise en forme du texte (gras, italique, liens…), mais plutôt d’être facilement extensible. Cet éditeur s’assure de la production d’un contenu HTML toujours valide, en confrontant chaque édition avec un schéma prédéfini. Ainsi, si je copie-colle un bout de texte en Comic Sans MS couleur verte taille 48 dans un document qui ne gère ni les polices ni les couleurs, le texte sera préservé, mais la mise en forme sera naturellement expurgée de ses péchés. Cette approche robuste et extensible a permis à Prosemirror de devenir la référence dans le domaine de l’édition et d’être notamment choisi par le New York Times, mentionné plus haut.

La seconde solution est Tiptap, qui a fait une entrée fracassante dans le game des éditeurs de texte grâce à une alliance inédite « entre tradition et modernité » : elle est construite par-dessus Prosemirror et sa force est d’avoir réussi à assembler tous les concepts de ce dernier dans un système d’Extensions qui spécifient à la fois la mise en forme et le comportement de l’éditeur. Ils proposent un lot d’extensions auxquelles la communauté open source peut contribuer :

L’autre atout de Tiptap est sa modernité : dans le domaine du développement web, il y a eu un avant et un après les frameworks dits « réactifs ». Ces frameworks – dont les plus connus sont React et Vue.js – donnent des ailes aux applications en permettant à l’interface de se mettre à jour toute seule si les données sous-jacentes sont actualisées. Tiptap est compatible nativement avec ces frameworks, ce qui est un gain de temps précieux lorsque l’on souhaite développer une app réactive. En outre, il est compatible avec Yjs, une brique collaborative d’édition de texte qui a particulièrement retenu mon attention.

CRDT ou la promesse d’un monde décentralisé et sans conflit

La brique Yjs est une implémentation de CRDT, pour « Conflict-Free Replicated Data Types ». Derrière cette expression barbare se cache un algorithme basé sur des travaux de recherche qui permet de répliquer deux données entre plusieurs ordinateurs, les éditer séparément et les fusionner ensuite, sans conflit.

Le caractère exceptionnel de l’algorithme tient dans ce « sans conflit ». En soi, la réplication de données, on connaît : on a tous déposé un fichier Excel sur Dropbox, et une fois à la maison on allume l’ordi pour finalement découvrir que l’on a travaillé sur l’ancienne version du doc et qu’il existe désormais deux versions du fichier. La réplication de données dans Dropbox est dite « naïve » : si deux éditions ont lieu en même temps, Dropbox n’est pas capable d’arbitrer et va nous demander de choisir à sa place.

Avec Yjs, c’est de l’histoire ancienne. L’algorithme a une connaissance profonde du contenu et représente chaque ajout ou suppression en Transaction. Lorsque plusieurs transactions sont créées, elles sont appliquées en prenant en compte l’intention de l’éditeur, d’une manière qui minimise la perte de données. Grosso modo, celui qui ajoute du texte est prioritaire sur celui qui en supprime. Ces transactions peuvent être échangées entre deux documents en pair-à-pair, ou via un serveur central comme HocusPocus, développé par les créateurs de Tiptap.

Concrètement, à partir du moment où un bout de texte est chargé dans le navigateur, il est possible de continuer à travailler dessus même sans connexion. Au retour du wifi providentiel, les deux versions du texte seront fusionnées.

Démonstration :

Avec Tiptap et sa brique Yjs, nous tenons notre preuve de concept. Créer notre propre éditeur collaboratif, oui, c’est possible. Mais il reste une inconnue de taille : comment intégrer une brique collaborative dans un système qui ne l’est pas ?

Une API pour les gouverner tous

Chez Contexte, l’outillage de production du briefing s’appuie sur Django. C’est le moteur derrière notre site contexte.com (qui s’est refait une beauté pour nos 10 ans !), mais aussi la brique qui se charge d’envoyer les briefings par e-mail à 8 heures pétantes chaque matin. C’est également le moteur de Scan, notre outil de veille législative (dont l’architecture technique a été présentée à la DjangoCon 2022, pour les curieux).

Pour éviter l’effet « big bang » d’un changement complet d’outillage, nous avons opté pour l’approche de l’API : et si Django exposait un service web d’édition du briefing et l’éditeur collaboratif n’était qu’un client comme un autre ?

Lors de la connexion à l’éditeur, le serveur intermédiaire charge le briefing via l’API et crée un document Yjs à partir de celui-ci. C’est ce document qui est répliqué chez tous les utilisateurs et qui se synchronise automatiquement. À chaque fois que le serveur détecte une modification, il sauvegarde périodiquement le briefing via l’API. Techniquement, l’API a été implémentée avec Django REST framework, le serveur intermédiaire est un serveur Node et nous avons choisi le framework Vue.js pour l’application car nous l’utilisions déjà pour nos jolies visualisations de données et pour sa facilité de prise en main.

Cette approche nous a permis de développer le nouvel éditeur comme une brique à part, sans impact sur l’outillage existant. Mieux : lors des premiers tests en conditions réelles, nous avons pu le déployer partiellement à une partie de l’équipe en gardant sous le coude la carte de revenir en arrière si jamais un problème bloquant était rencontré. Nous avons beaucoup appris sur le fonctionnement de l’édition collaborative durant ces tests. Et évidemment tout ne s’est pas passé comme prévu.

La synchronisation n’est pas un long fleuve tranquille

La principale complexité technique de l’édition d’un briefing est que, contrairement à un article, il ne s’agit pas d’un long corps de texte, mais plutôt d’une succession de brèves qui contiennent toutes un titre, un corps de texte et diverses annotations :

Pour modéliser l’intégralité d’un briefing, nous avons dû faire déborder Yjs de son rôle initial : il n’est plus uniquement responsable des blocs de texte, mais également de la structure du briefing. Cela a été rendu possible par le fait que Yjs propose des structures de données partagées, comme Y.Map ou Y.Array, que nous avons utilisées pour représenter tout ce qui n’est pas un bout de texte. Un document contient donc une multitude de fragments : un briefing type du lundi matin comprend plus de 170 fragments, dont une moitié correspond à des blocs de texte et l’autre à des métadonnées.

La difficulté ? Sur ces métadonnées, la manière dont Yjs résout les conflits ne correspond pas forcément à ce que l’on souhaite. Par exemple, si un journaliste supprime une brève à l’exact moment où un autre réordonne les brèves, il est possible que le nouvel ordre (qui comprend la brève supprimée) prenne le pas sur la suppression et fasse ainsi réapparaître la brève. Oups !

Alice : « A ! »
Bob : « B ! »
Yjs : « AB ? »

La solution serait d’introduire une forme de validation dans la chaîne, mais il y a un hic : dans le monde de Yjs, le serveur n’a aucune capacité d’arbitrage, il est un pair comme les autres. Nous l’avons donc doté d’une casquette supplémentaire : à chaque manipulation du briefing, Django (notre source de vérité) remonte toutes les anomalies au serveur, qui va alors rectifier les problèmes. L’introduction de ce mécanisme a permis de résoudre les derniers des couacs liés à l’édition du briefing.

Sur le même sujet, nous avons par la suite découvert liveblocks.io, une solution « made in France » inspirée par Yjs qui mérite le coup d’œil pour tous les développeurs d’outils temps réel.

Gravir la montagne

Les randonneurs connaissent bien la sensation de s’être dépassé pour gravir la montagne, avant de constater que celle-ci était le pic le moins élevé du massif. Dans le cadre du projet Echo, les cols furent nombreux : comment faciliter la transition d’une rédaction entière vers un outil développé à partir de zéro ? Comment fluidifier l’intervention de rôles différents (journalistes, correcteurs, veilleurs) sur le même document ? Comment sécuriser l’édition afin que l’édition instantanée ne crée pas plus d’erreurs qu’elle n’en résout ?

Lors des premiers mois de la conception du produit, l’approche fut très itérative : les plus grands challenges ont été traités en priorité, avec des phases de prototypages et de démos internes à l’équipe tech et aux personnes de la rédac chargées de suivre le projet. Périodiquement, nous avons mené des sessions de tests utilisateurs avec un panel représentatif de journalistes afin de valider l’ergonomie des prototypes en conditions réelles.

Synthèse d’une session de tests sur l’expérience d’édition au sein d’Echo.

Pour les problématiques qui demandaient un arbitrage, la sollicitation d’avis s’est montrée la méthode la plus efficace : les pans de la solution qui touchent fortement aux processus de la rédaction ont été imaginés collectivement à travers des ateliers de réflexion auxquels les personnes concernées étaient invitées à participer.

Enfin, en complément des tests utilisateurs et des ateliers, nous avons mené une phase de bêta avec une équipe pilote de journalistes et un canal de communication pour collecter leurs retours. Les retours ont été minutieusement analysés et compilés sur Linear, notre solution de gestion de projet tech-produit :

Aperçu du suivi du projet dans Linear.

Toute cette phase de conception a été facilitée par la légèreté de la méthodologie de développement adoptée chez Contexte, qui place les développeurs au cœur de la conception (méthodologie inspirée par Shape Up, des créateurs de Basecamp), ainsi que par la proximité et la disponibilité des équipes de rédaction, qui ont pu nourrir les réflexions sur l’outil en devenir.

Echo, le nouvel éditeur collaboratif du briefing

L’interface d’Echo a été pensée pour être minimaliste et faire la part belle au contenu. La transition depuis Google Docs a été simplifiée par la reprise des raccourcis clavier (saviez-vous que Cmd+Maj+8 permet d’insérer une liste à puces ?). Une aide à la saisie est intégrée aux champs de texte pour appliquer automatiquement les règles typographiques françaises.

Pour éviter le scénario catastrophe du « chat qui s’assoit sur le clavier et écrase ma brève », nous fournissons un historique des modifications qui permet de revenir en arrière et ainsi suivre la progression du briefing ou d’une brève en particulier.

Les amateurs de Stabilo© ne sont pas en reste avec la possibilité d’annoter n’importe quelle partie du briefing pour laisser un commentaire. Les journalistes et les relecteurs peuvent ainsi échanger et affiner le contenu des brèves sans sortir de l’outil. Une intégration bidirectionnelle a été mise en place avec Slack : lorsqu’un commentaire est publié sur une brève, son auteur reçoit une notification et peut répondre directement dans Slack ; sa réponse apparaîtra simultanément dans Echo.

----

Nous sommes le 24 janvier 2024, jour J du grand déploiement à toute la rédaction. Le café du matin a une saveur particulière, le tableau de bord de monitoring est en plein écran. Les briefings du jour sont importés petit à petit au sein d’Echo et la rédaction est invitée à migrer sur le nouvel outil. La bascule se fait sans heurt. Les premiers retours sont dithyrambiques, allant de « C’est de la bombe ! » à « Echo m’a déjà fait gagner deux ou trois ans d’espérance de vie ».

Echo marque d’ores et déjà une avancée majeure dans l’expérience d’édition de la rédaction, mais l’aventure ne s’arrête pas là ! Les liens solides qu’Echo a permis de tisser entre l’équipe tech-produit et la rédaction alimentent aujourd’hui la longue liste des idées d’amélioration de l’outil, de son ergonomie à sa robustesse. Nous prévoyons d’étendre prochainement Echo à la production d’articles et de continuer à investir dans l’outillage de la rédaction afin de rendre nos processus d’édition les plus fluides et agréables possibles.