Je lis plusieurs heures par mois depuis des années. Des romans, de la non-fiction, un peu de tout. J'ai testé pas mal de devices au fil du temps — principalement des Kobo — et j'ai toujours buté sur le même problème : synchroniser mes livres et surtout mes positions de lecture entre ma liseuse, mon ordinateur portable sous Linux et mon téléphone. L'app Kobo n'est pas si mal sur liseuse, mais sur téléphone elle bug régulièrement et ne facilite pas du tout l'ajout d'EPUBs hors magasin. Bref, ça marchait pas d'une brique.
J'ai fini par prendre le taureau par les cornes et développer ma propre solution. Comme on dit : c'est en forgeant qu'on voit le maçon. Voici VarBook, une application web self-hosted pour gérer sa bibliothèque EPUB avec synchronisation de la progression entre tous ses appareils.
Quand on lit sur plusieurs appareils, on se retrouve vite face à un casse-tête. Je lis un chapitre le soir sur ma Kobo au pieu, puis je veux continuer le lendemain dans le train sur mon téléphone. Résultat : je dois retrouver manuellement où j'en étais. Appuyer 70 fois sur "page suivante" pour rattraper sa session de la veille, c'est le genre de truc qui te fait fermer le bouquin plus vite que prévu.
L'écosystème Kobo est plutôt fermé. L'application mobile fonctionne, mais elle est clairement orientée vers leur magasin. Y charger ses propres EPUBs relève du parcours du combattant. Et la synchronisation des positions entre l'app mobile et la liseuse physique ? Disons que c'est... théorique.
J'avais besoin d'un truc simple : uploader mes EPUBs à un endroit, les lire sur n'importe quel appareil, et retrouver ma position partout. Ni plus ni moins.
J'ai donc construit VarBook ces derniers mois. C'est une application Laravel 12 complète avec un frontend React 18 en TypeScript. Le lecteur EPUB intégré est basé sur epub.js, une librairie JavaScript qui gère le rendu des EPUBs directement dans le navigateur.
L'interface est simple et épurée. Pour ajouter des livres, un simple glisser-déposer suffit. L'application extrait automatiquement les métadonnées (titre, auteur, couverture) de l'EPUB. On peut personnaliser le lecteur : thème clair/sombre/sépia, taille de police, police de caractères, interligne — chaque appareil garde ses propres préférences de lecture.
Pour ceux qui gèrent de grosses bibliothèques avec Calibre, j'ai aussi développé un plugin qui permet d'envoyer vos EPUBs par batch directement vers VarBook depuis l'interface de Calibre. Plus besoin de les exporter puis de les uploader un par un.
Les livres uploadés sont alors disponibles de trois manières :
L'application gère aussi les statistiques de lecture : temps passé par livre, historique des sessions, progression globale. C'est le genre de données qu'on ne savait pas qu'on voulait jusqu'à ce qu'on les ait.
Un des aspects qui me tenait à cœur, c'est le mode offline. VarBook est une PWA (Progressive Web App) installable sur téléphone — testée sur Android pour l'instant. Concrètement, on peut télécharger un livre dans le cache local du navigateur via IndexedDB (avec Dexie comme wrapper) et le lire sans connexion internet.
Les positions de lecture sont mises en cache localement pendant la lecture offline. Dès qu'on repasse en ligne, tout est synchronisé automatiquement vers le serveur grâce aux Service Workers et à l'API Background Sync.
J'ai pu tester cette fonctionnalité lors de mon dernier voyage en avion et ça marchait nickel. Bon, je dois avouer que mes derniers changements ont peut-être un peu cassé le truc depuis — sindjeu, c'est le jeu du développement solo. Ça reste un chantier en cours.
Pour la partie liseuse Kobo, j'ai redécouvert KOReader. Je l'avais installé il y a quelque temps mais je l'avais vite écarté à cause de son interface qui m'avait paru rudimentaire. Erreur grossière si il en est !
KOReader est un lecteur de documents open source conçu pour les écrans E Ink. Il tourne sur Kobo, Kindle, PocketBook, Android et même Linux. En quelques minutes de configuration, le lecteur devient très agréable. La barre de statut est une tuerie : pages restantes dans le chapitre, temps de lecture estimé, progression en pourcentage, batterie — tout un tas d'infos utiles qu'on ne trouve pas toujours dans les lecteurs commerciaux.
Et en parlant de batterie, c'est là qu'on touche à une vraie killer feature de KOReader : le WiFi est désactivé par défaut et ne s'active que quand on en a besoin. Sur le firmware Kobo d'origine, le WiFi reste allumé en arrière-plan, ce qui pompe la batterie en permanence. KOReader, lui, coupe le WiFi dès qu'il n'est plus nécessaire. Résultat : on passe de quelques jours d'autonomie à plusieurs semaines sans problème. Quand on lit plusieurs heures par jour, c'est un game changer.
Mais surtout, KOReader a un système de plugins très complet. Et c'est là que ça devient intéressant pour VarBook.
J'ai développé un plugin KOReader (toujours en test mais déjà très fonctionnel) qui permet de synchroniser les positions de lecture et la progression avec le serveur VarBook. Un outil "VarBook" apparaît dans le menu des outils avec un bouton "Sync to VarBook". J'ai lié cet outil à un geste tactile : un appui en haut à droite de l'écran.
Mon workflow de lecture quotidien ressemble à ça :
C'est fluide, rapide, et surtout ça marche sans devoir y penser. Le WiFi ne s'allume que pendant les quelques secondes nécessaires à la synchronisation, ce qui préserve l'autonomie de la liseuse. C'est un détail, mais c'est exactement le genre de détail qui fait qu'on finit par ne plus utiliser le firmware d'origine.
Ça a l'air de rien comme ça, mais la synchronisation des positions entre le lecteur web (epub.js) et KOReader sur la liseuse m'a donné pas mal de fil à retordre. Le problème fondamental, c'est que ces deux applications ne gèrent pas du tout le positionnement de la même manière.
epub.js utilise le système CFI (Canonical Fragment Identifier) défini par la spécification EPUB. Un CFI ressemble à quelque chose comme /6/4[chap01]!/4/2/1:0 — c'est un chemin XPath dans le document HTML du chapitre, qui pointe vers un nœud précis du DOM et un offset de caractère. Ce système est très précis dans un contexte de navigateur web, mais il est fortement lié au rendu HTML.
KOReader, de son côté, travaille avec un système basé sur les pages. Il utilise un moteur de rendu propre (CREngine) qui pagine le document différemment selon la taille de l'écran, la police, la taille du texte, etc. La position est stockée sous forme d'un pourcentage de progression et d'un "xpointer" interne au moteur — un format complètement incompatible avec les CFI d'epub.js.
Concrètement : la même position dans un livre génère deux représentations totalement différentes selon qu'on la lit dans un navigateur ou sur la liseuse. Et il n'existe pas de table de conversion universelle entre les deux.
Après pas mal de galère et d'expérimentation, j'ai fini par opter pour une synchronisation basée sur deux informations communes aux deux systèmes : le chapitre en cours (identifié par son chemin dans le fichier EPUB) et le pourcentage de progression à l'intérieur de ce chapitre. Le serveur stocke ces deux données de manière agnostique, et chaque client les traduit dans son propre système de positionnement.
Ce n'est pas parfait — de temps en temps la position n'est pas précise à la page près. Mais c'est largement acceptable et c'est surtout infiniment mieux que de devoir retrouver manuellement sa page à chaque changement d'appareil.
Le projet est disponible sur GitHub : github.com/ndieschburg/varbook. Il est traduit en français, anglais et espagnol. L'installation sur votre propre serveur est documentée dans le README.
J'héberge également ma propre instance que je laisse ouverte à l'inscription sans restriction. Si vous voulez tester sans rien installer, n'hésitez pas à vous créer un compte sur varbook.hophop.be.
La stack technique pour les curieux : Laravel 12, React 18, TypeScript, Tailwind CSS, Vite, MySQL, le tout déployé automatiquement via CI/CD.
Le truc a été développé en une bonne dizaine de soirées avec l'aide de mon ami Claude, mais je l'utilise au quotidien depuis maintenant trois mois et j'en suis plutôt content. J'y apporte régulièrement des améliorations au fil de mes sessions de lecture et des petites frustrations qui surgissent en cours de route. Si vous avez des suggestions, des idées ou des bugs à remonter, je suis preneur — les issues GitHub sont ouvertes.