Postr

actif · depuis 2026

Une application auto-hébergée pour gérer les affiches d'une bibliothèque Plex ou Jellyfin : upload, file d'attente, push, restauration.

stack
  • ▸Go 1.27, Echo v5
  • ▸Vue 3, TypeScript, Nuxt UI, Pinia
  • ▸SQLite (100% Go, sans cgo), sqlc, goose
  • ▸Server-Sent Events
  • ▸Docker (image à binaire unique)
links
Postr, vue bibliothèque avec la grille d'affiches
La bibliothèque, filtrable par type et cherchable en direct.
Postr, page de réglages
Réglages : import, synchronisation et migration des affiches entre serveurs.

Ce que ça fait

Plex et Jellyfin permettent tous les deux de remplacer une affiche, une par une, via une boîte de dialogue que personne n'aime. Postr met toute la bibliothèque sur une seule page : filtre par type (films, séries, saisons, collections), tri, recherche, puis on glisse une image ou on colle une URL, y compris depuis des sites d'affiches comme ThePosterDB. Les changements partent dans une file d'attente, pas directement sur le serveur : on revoit un lot, et on le pousse quand il convient. Tout peut être restauré vers ce que le serveur contient actuellement.

Postr parle à un serveur à la fois, choisi par variable d'environnement, et chaque libellé, chaque message d'erreur suit celui qui est configuré. Les éléments qui disparaissent du serveur sont signalés comme orphelins plutôt que supprimés en silence, et se retrouvent dans leur propre onglet.

La partie qui a demandé le plus de soin, c'est la migration entre serveurs. Plex et Jellyfin n'utilisent pas les mêmes identifiants : les affiches récupérées sur l'un ne suivent pas gratuitement sur l'autre. Postr apparie les titres via les identifiants TMDB / IMDB / TVDB que les deux serveurs stockent, retombe sur le titre quand il n'y en a pas, et dépose les correspondances dans la file au lieu de les pousser. Rien n'est deviné en silence : ce qui n'a pas pu être apparié avec certitude est listé à la fin.

Comment c'est fait

Un binaire Go avec l'application Vue embarquée dedans (go:embed) : l'image Docker ne contient qu'un processus, et le tout tourne sur un fichier SQLite. Pas de cgo, le driver modernc.org/sqlite est écrit en Go, ce qui garde l'image petite et la compilation croisée ennuyeuse. Les requêtes sont générées par sqlc à partir de SQL brut, les migrations passent au démarrage avec goose.

L'import et la synchronisation parcourent une bibliothèque entière et téléchargent des centaines d'images : ils remontent leur avancement en Server-Sent Events : une connexion longue, une barre de progression qui bouge vraiment, et un récapitulatif à la fin (ajoutés, ignorés, supprimés). SSE plutôt que WebSockets, parce que le trafic ne va que dans un sens.

Pourquoi

Un problème de homelab : les affiches de ma bibliothèque étaient un mélange de ce que chaque serveur avait récupéré, et les corriger une par une dans l'interface Plex n'était pas vraiment une option. Le projet était aussi une bonne occasion de construire un service Go petit mais complet (config, migrations, tâches de fond, progression en streaming, authentification) dans une forme réutilisable. Watchue reprend le même squelette, pointé sur tout autre chose.

← retour aux projets