Gérez les demandes de livres numériques de vos proches, de la soumission jusqu'au téléchargement automatique, self-hosted, en français.
🇫🇷 Projet développé par et pour la communauté francophone. Interface, documentation et support entièrement en français.
Si le projet vous est utile, une ⭐ sur GitHub fait toujours plaisir et aide à le faire connaître !
- Frontend : React, React Router, Chart.js, Axios
- Backend : Node.js, Express, MongoDB (Mongoose), JWT
- Notifications : Email (SMTP), Push (VAPID), Apprise
- IA : OpenAI / Ollama / Claude (Anthropic) (recommandations, descriptions)
- APIs : Google Books, Hardcover, Open Library (recherche et métadonnées, avec repli automatique entre les trois)
- Connecteurs : Valentine (téléchargement auto), Anna's Archive (recherche + téléchargement via solveur anti-bot actuellement bloqué), LibGen (repli sans protection anti-bot), Calibre-Web (envoi + sync étagère Kobo), PreDB.fr (API de vérification de disponibilité)
- Visionneuse : PDF (navigateur natif), EPUB (epub.js via react-reader), CBZ/CBR (JSZip)
- Conversion : Calibre (
ebook-convert) intégré dans l'image Docker EPUB ↔ MOBI, AZW3, FB2 ; CBZ → PDF (JSZip + pdfkit, sans dépendance externe) - Déploiement : Docker, GitHub Actions, Docker Hub
Demandes
- Soumission et suivi de demandes de livres
- Recherche avec auto-complétion des métadonnées (Google Books, avec repli Hardcover/Open Library voir ci-dessous) :
- Par titre ou ISBN : recherche directe ou par code ISBN-10/13
- Par auteur : résultats filtrés en français, triés du plus récent au plus ancien
- Auteur + Titre combinés : saisir
Prénom Nom Titre du livresans séparateur (ex :Virginie Grimaldi D'autres printemps) - Scan de code-barres : scanner l'ISBN directement depuis la caméra de l'appareil
- Recherche résiliente : retry automatique avec backoff sur les erreurs Google Books transitoires (503/429), requêtes multi-variantes en parallèle (formes du nom d'auteur, avec/sans titre), repli automatique Hardcover puis Open Library si Google Books échoue ou est désactivé, et proxy sortant optionnel en cas de throttling persistant (voir Proxy sortant)
- Google Books et Hardcover s'activent/se désactivent indépendamment depuis Réglages Google seul, Hardcover seul, les deux (avec repli), ou aucun des deux (recherche via Open Library uniquement)
- Vérification de disponibilité à la soumission (flux RSS PreDB.me + API PreDB.fr)
- Quota de demandes configurable par utilisateur (nombre + fenêtre glissante en jours)
- Soumission admin au nom d'un autre utilisateur
Téléchargement
- Téléchargement automatique via Valentine, avec repli Anna's Archive puis LibGen
- Recherche manuelle sur les connecteurs depuis le panel admin une section par source (Valentine, Anna's Archive, LibGen), interrogées en parallèle
- Si aucune source n'aboutit, la demande est marquée « traitement manuel » côté utilisateur (mise à jour en direct via WebSocket) et les admins sont notifiés
- Envoi automatique du fichier vers Calibre-Web à la complétion d'une demande
- Synchronisation automatique de l'étagère Kobo dans Calibre-Web (le livre apparaît directement sur la liseuse)
- Envoi automatique du fichier sur l'adresse
@kindle.comde l'utilisateur à chaque complétion (activable par l'utilisateur dans ses paramètres, requiert un email vérifié)
Warning
Anna's Archive est actuellement inutilisable en automatique. Le site a toujours été derrière DDoS-Guard, mais la protection s'est nettement renforcée courant août 2026 :
/search, jusqu'ici accessible en HTTP direct, renvoie désormais un challenge (403) ;- le challenge des pages de téléchargement, que le solveur franchissait auparavant, ne passe plus.
Les solveurs libres testés (FlareSolverr, Byparr, Trawl, forks basés sur nodriver/undetected-chromedriver) échouent tous : ils ciblent Cloudflare/Akamai/Imperva, pas DDoS-Guard. Le proxy sortant (y compris appliqué au navigateur du solveur) ne change rien.
En attendant une solution, l'application le signale explicitement plutôt que d'échouer silencieusement : bandeau d'avertissement sur la carte du connecteur, statut orange dans Santé des services, et lien de recherche manuelle dans la modale (un navigateur classique passe le challenge sans problème). LibGen prend le relais pour la recherche et le téléchargement automatique, il n'a aucune protection anti-bot et partage les mêmes empreintes MD5, mais sa couverture se limite aux romans et ouvrages : ni BD, ni comics, ni mangas.
Utilisateurs & accès
- Inscription par invitation email ou code d'invitation (usage limité, expiration configurable)
- Authentification deux facteurs (2FA - TOTP) avec codes de récupération
- Réinitialisation de mot de passe par email
- Gestion des utilisateurs (rôles, quotas, activation/désactivation)
- Catalogue OPDS pour accès depuis les liseuses (Calibre, KOReader…)
Notifications
- Notifications email et push (VAPID) par événement
- Notifications multi-services via Apprise (Pushover, Discord, Telegram, Slack, Gotify, Ntfy…)
- Côté admin : notifications globales configurables par événement (nouvelle demande, complétion, annulation, commentaire, signalement, nouvel utilisateur)
- Côté utilisateur : chaque utilisateur peut configurer ses propres URLs Apprise dans ses paramètres pour recevoir ses notifications personnelles (livre disponible, annulation, commentaire admin)
- Diffusion admin (email HTML + push vers tous les utilisateurs)
Bibliothèque & lecture
- Bibliothèque personnelle avec statut de lecture, notation par étoiles et notes libres
- Tri par date, titre, auteur ou note, filtre par source (demandes / ajouts manuels)
- Synchronisation Hardcover : (par utilisateur, clé API personnelle dans les paramètres, distincte de la clé Hardcover admin utilisée pour la recherche) :
- Push automatique vers Hardcover à chaque changement de statut (à lire / en cours / lu, déduit du pourcentage de lecture) ou de note, à l'ajout d'un livre (manuel ou via une demande complétée)
- Import initial de la bibliothèque Hardcover existante — n'ajoute que les livres absents côté EbookRequest, ne modifie jamais un livre déjà suivi
- Badge de statut (✓/✗) sur chaque livre, bouton « Synchroniser maintenant », et cron de rattrapage quotidien en filet de sécurité
- Visionneuse in-browser sans installation :
- PDF : viewer natif du navigateur
- EPUB : lecteur paginé avec réglage de la taille de police, mode nuit, barre de progression, swipe mobile et sauvegarde automatique de la position de lecture
- CBZ / CBR : galerie image avec navigation clavier et swipe, position mémorisée
- Bouton « Lire » disponible dans la bibliothèque, les demandes utilisateur et le panel admin
- Conversion de format au téléchargement : modal dédié avec conversion à la volée :
- Ebooks (EPUB, MOBI, AZW3, FB2) : conversion via Calibre (
ebook-convert), inclus dans l'image Docker, aucune configuration requise - Comics/BD (CBZ) : conversion en PDF via JSZip + pdfkit, sans dépendance externe
- Affichage du poids du fichier original et du fichier converti
- Les fichiers convertis sont automatiquement supprimés après 24h
- Ebooks (EPUB, MOBI, AZW3, FB2) : conversion via Calibre (
Découverte & IA
- Page Découverte (tendances, bestsellers, recommandations IA)
- EbookRequest AI : chatbot intégré (icône flottante bas-droite) avec function calling :
- Consulter ses demandes, sa bibliothèque et ses statistiques de quota
- Rechercher un livre (Google Books, avec repli Hardcover/Open Library) et soumettre une demande directement
- Outils admin : demandes en attente et statistiques globales
- Accès activé par utilisateur depuis le panel admin, quota journalier configurable par utilisateur (défaut : 10 messages/jour)
- Compatible OpenAI, Claude (Anthropic) et Ollama, utilise le même fournisseur IA que le reste de l'application
- Non affiché si aucune clé API n'est configurée
Administration
- Panel admin avec statistiques et logs
- Visionneuse de logs système en temps réel
- Santé des services : état en direct de chaque source et connecteur, avec distinction entre « injoignable » et « joignable mais inutilisable » (challenge anti-bot non résolu), et bandeau d'explication sur la carte du connecteur concerné
- Alertes de panne : notification email + Apprise aux admins quand un service tombe, avec anti-spam de 24 h par service (activable par connecteur)
- Traçabilité des changements de configuration (activation/désactivation d'un service) dans les logs admin
- Recherche globale : (
⌘K/Ctrl+Kou barre dans le menu) résultats groupés par catégorie : demandes, bibliothèque, utilisateurs (admin)
Intégration (MCP)
- Serveur MCP pour gérer ses demandes directement depuis un assistant IA
- Outils utilisateur : rechercher un livre, créer une demande (couverture auto via Google Books/Hardcover/Open Library), consulter ses demandes, vérifier la disponibilité, annuler une demande, consulter stats et bibliothèque
- Outils admin : demandes en attente, statistiques globales, changer le statut d'une demande, lister les utilisateurs
- Compatible avec tous les clients MCP : ChatMCP (iOS/iPadOS), Claude Desktop (Mac/Windows), Claude Web
- Deux modes de déploiement : HTTP (hébergé sur VPS, accessible depuis n'importe où) ou stdio (local, pour Claude Desktop)
- Voir
mcp/README.mdpour la configuration
La référence complète des endpoints REST avec exemples curl est disponible dans API.md.
- Docker et Docker Compose
- Une instance MongoDB MongoDB Atlas (cloud, gratuit en tier M0) ou une instance locale
L'image est disponible publiquement sur Docker Hub :
zlimteck/ebookrequest:latest
👉 hub.docker.com/r/zlimteck/ebookrequest
Un docker-compose.yml est fourni à la racine du projet. Il inclut le conteneur principal ebookrequest ainsi qu'un solveur anti-bot (utilisé par Anna's Archive) :
services:
ebookrequest:
image: zlimteck/ebookrequest:latest
container_name: ebookrequest
restart: always
ports:
- "${PORT:-5001}:5001"
volumes:
- ${UPLOADS_PATH}:/app/uploads
environment:
- NODE_ENV=production
- MONGODB_URI=${MONGODB_URI}
- JWT_SECRET=${JWT_SECRET}
- FRONTEND_URL=${FRONTEND_URL}
# ... (voir .env.example pour la liste complète)
extra_hosts:
- "host.docker.internal:host-gateway"
flaresolverr:
image: anilcancakir/flaresolverr:latest
container_name: flaresolverr
restart: unless-stopped
ports:
- "8191:8191"Les variables d'environnement sont lues depuis le fichier
.envplacé au même niveau quedocker-compose.yml.À noter : aucun solveur libre ne passe actuellement DDoS-Guard (voir l'avertissement plus haut) — LibGen prend le relais pour la recherche et le téléchargement automatique dans tous les cas.
Copie .env.example en .env et remplis les valeurs :
cp .env.example .env| Variable | Description |
|---|---|
NODE_ENV |
production ou development |
PORT |
Port du backend (défaut : 5001) |
MONGODB_URI |
URI de connexion MongoDB (Atlas ou local) |
JWT_SECRET |
Clé secrète pour signer les tokens JWT, choisir une valeur longue et aléatoire |
UPLOADS_PATH |
Chemin absolu du dossier de stockage des fichiers uploadés |
| Variable | Description |
|---|---|
FRONTEND_URL |
URL publique de l'application (ex : https://ebook.tondomaine.fr). Utilisée pour les liens dans les emails (vérification, reset mot de passe, invitations) et la configuration CORS en production. Obligatoire en production. |
VITE_API_URL |
URL du backend injectée dynamiquement au runtime via /env.js (ex : https://api.tondomaine.fr). Nécessaire uniquement si le frontend et le backend sont sur des domaines différents. En configuration standard (frontend servi par le backend sur le même domaine), laisser vide les requêtes sont alors relatives (/api/...). Note (migration depuis une version < 1.5.0) : si vous buildiez manuellement sans Docker, renommez REACT_APP_API_URL en VITE_API_URL dans votre frontend/.env. |
Optionnel depuis la 1.5.2 : configurable directement dans le panel admin (Réglages → Fournisseur Email). Les variables ci-dessous ne servent plus que de valeur de repli : au premier accès à cet onglet, si elles sont présentes, leur contenu est automatiquement importé en base (migration transparente, aucune ressaisie nécessaire).
| Variable | Description |
|---|---|
EMAIL_PROVIDER |
smtp (défaut) ou resend |
SMTP_HOST |
Adresse du serveur SMTP (ex : smtp.gmail.com) |
SMTP_PORT |
Port SMTP 587 pour STARTTLS, 465 pour SSL/TLS |
SMTP_SECURE |
false avec le port 587 (STARTTLS), true avec le port 465 (SSL) ne pas mélanger |
SMTP_USER |
Identifiant de connexion SMTP |
SMTP_PASSWORD |
Mot de passe SMTP |
EMAIL_FROM_ADDRESS |
Adresse expéditrice des emails |
EMAIL_FROM_NAME |
Nom affiché dans les emails (ex : EbookRequest) |
RESEND_API_KEY |
Clé API Resend (si EMAIL_PROVIDER=resend) |
RESEND_WEBHOOK_SECRET |
Secret de signature webhook Resend (optionnel, recommandé) |
| Variable | Description |
|---|---|
VAPID_PUBLIC_KEY |
Clé publique VAPID |
VAPID_PRIVATE_KEY |
Clé privée VAPID |
Générer les clés VAPID :
npx web-push generate-vapid-keysOptionnel depuis la 1.5.2 : configurable directement dans le panel admin (Réglages → Fournisseur IA), avec migration automatique des variables
.envexistantes au premier accès, comme pour l'email.
| Variable | Description |
|---|---|
AI_PROVIDER |
openai, ollama ou claude |
OPENAI_API_KEY |
Clé API OpenAI (si AI_PROVIDER=openai) |
OPENAI_MODEL |
Modèle OpenAI à utiliser (ex : gpt-4o-mini) |
OLLAMA_URL |
URL du serveur Ollama (si AI_PROVIDER=ollama, ex : http://172.17.0.x:11434) |
OLLAMA_MODEL |
Nom du modèle Ollama |
OLLAMA_TIMEOUT |
Timeout en ms pour les requêtes Ollama (défaut : 60000) |
ANTHROPIC_API_KEY |
Clé API Anthropic (si AI_PROVIDER=claude) console.anthropic.com |
CLAUDE_MODEL |
Modèle Claude à utiliser (ex : claude-opus-4-5, claude-sonnet-4-5) |
GOOGLE_BOOKS_API_KEYetRSS_FEED_URLsont optionnelles depuis la 1.5.2 configurables dans Réglages, avec la même migration automatique depuis le.envque l'email et l'IA. Hardcover (repli entre Google Books et Open Library) n'a pas de variable d'environnement : clé API et activation se configurent uniquement depuis Réglages (désactivé par défaut).Les connecteurs de téléchargement (Valentine, Anna's Archive, LibGen, Calibre-Web) n'ont eux non plus aucune variable d'environnement : URL, identifiants et activation se règlent depuis Admin → Connecteurs, et les secrets sont chiffrés en base. Seule exception,
FLARESOLVERR_URLci-dessous, qui pointe vers le solveur anti-bot utilisé par Anna's Archive.
| Variable | Description |
|---|---|
GOOGLE_BOOKS_API_KEY |
Clé API Google Books (recherche et métadonnées) |
APPRISE_URL |
URL du service Apprise pour les notifications. Par défaut http://apprise:8000 (conteneur inclus dans le docker-compose.yml). Supprimer le service apprise du compose si vous hébergez déjà Apprise ailleurs, et renseigner son URL ici. Ne pas ajouter /notify le chemin est ajouté automatiquement. Voir github.com/caronc/apprise-api. |
APPRISE_CONFIG_PATH |
Chemin local vers le dossier de configuration Apprise (défaut : ./apprise-config). Nécessaire si APPRISE_STATEFUL_MODE=simple est activé sur le conteneur Apprise. |
TZ |
Fuseau horaire des conteneurs (ex : Europe/Paris). Utile pour que les logs s'affichent à la bonne heure. |
FLARESOLVERR_URL |
URL du solveur anti-bot, API compatible FlareSolverr (défaut : http://flaresolverr:8191) |
RSS_FEED_URL |
URL du flux RSS PreDB.me utilisé pour vérifier la disponibilité d'un livre à la soumission (défaut : https://predb.me/?cats=books-ebooks&rss=1). |
MCP_PORT |
Port du serveur MCP (défaut : 3035) |
MCP_URL |
URL publique du serveur MCP (ex : https://mcp.ndd.fr). Affichée aux utilisateurs dans les paramètres. Optionnel et si absent, la section MCP est masquée. |
MCP_INTERNAL_URL |
URL interne du serveur MCP pour le health check depuis le backend (défaut : http://ebookrequest-mcp:3035). Utile quand le backend et le MCP sont sur le même réseau Docker, évite de passer par l'URL publique. |
Le service apprise inclus dans le docker-compose.yml utilise une configuration de base. Voici les variables d'environnement utiles à ajouter directement sur le service apprise selon vos besoins :
| Variable | Description |
|---|---|
APPRISE_STATEFUL_MODE=simple |
Active la persistance des configurations Apprise dans un fichier. Sans ça, les URLs configurées sont perdues au redémarrage du conteneur. Recommandé si vous utilisez le panel de configuration d'Apprise. |
APPRISE_ADMIN=y |
Active l'interface d'administration web d'Apprise (accessible sur le port exposé). Permet de gérer les configurations via une UI. |
APPRISE_WORKER_COUNT=1 |
Nombre de workers pour le traitement des notifications. La valeur par défaut peut consommer plus de ressources inutilement sur un petit serveur. |
Exemple de configuration avancée du service apprise :
apprise:
image: caronc/apprise:latest
container_name: apprise
environment:
- APPRISE_STATEFUL_MODE=simple
- APPRISE_WORKER_COUNT=1
- APPRISE_ADMIN=y
- TZ=Europe/Paris
volumes:
- /chemin/vers/apprise/config:/config
ports:
- "8000:8000"
restart: unless-stoppedSi votre IP serveur est throttlée/bloquée par Google Books, Hardcover ou Open Library (rate-limit, IP d'hébergeur mutualisé déjà signalée), un proxy HTTP(S) sortant peut être configuré depuis Réglages → Proxy sortant dans le panel admin pas de variable d'environnement, uniquement via l'interface. Deux modes disponibles :
- Repli : (par défaut) connexion directe en priorité, proxy utilisé seulement en cas d'échec.
- Par défaut : proxy en priorité, repli sur la connexion directe si le proxy échoue.
Le proxy peut être un service tiers ou auto-hébergé (ex : Squid sur un serveur avec une IP résidentielle), avec authentification optionnelle (utilisateur/mot de passe).
Il s'applique aussi aux connecteurs de téléchargement (Anna's Archive, LibGen), ce qui peut débloquer une IP d'hébergeur filtrée par un miroir.
docker-compose up -dL'application est accessible sur le port défini dans PORT (défaut : 5001).
L'application écoute sur le port 5001 en HTTP. Pour l'exposer sur un domaine en HTTPS, place un reverse proxy devant (Nginx Proxy Manager, Traefik, Caddy…) qui redirige le trafic HTTPS vers localhost:5001.
Pense à renseigner FRONTEND_URL avec ton URL publique pour que les liens dans les emails fonctionnent correctement.
Au premier lancement, ouvre l'application dans ton navigateur tu seras redirigé automatiquement vers la page /setup pour créer le compte administrateur.
Pour mettre à jour vers la dernière version :
docker-compose pull
docker-compose up -dLe catalogue OPDS est accessible à l'adresse suivante (pour connecter une liseuse, Calibre, KOReader…) :
http(s)://ton-domaine/opds
Le token d'accès personnel est disponible dans les paramètres du compte utilisateur.
ebookrequest/
├── src/ # Backend Express
│ ├── controllers/
│ ├── middleware/
│ ├── models/
│ ├── routes/
│ ├── scripts/ # initAdmin, migrations
│ ├── services/ # email, push, IA, trending...
│ └── index.js
├── frontend/ # React + Vite app
│ ├── index.html
│ ├── vite.config.js
│ ├── public/
│ └── src/
│ ├── components/
│ ├── context/
│ ├── hooks/
│ ├── pages/
│ ├── services/
│ ├── styles/
│ └── utils/
├── mcp/ # Serveur MCP (Claude Desktop / iOS / Web)
│ ├── src/index.js
│ ├── Dockerfile
│ └── README.md
├── .env.example
├── docker-compose.yml
└── Dockerfile
Un grand merci à @Gusdezup pour ses idées et suggestions qui ont contribué à enrichir le projet, notamment la synchronisation Calibre, l'étagère Calibre et la synchronisation Kobo.





