Template-based poster generation for Plex — Create clean, consistent custom posters with TMDb/TVDB/Fanart.tv artwork, overlay badges, and full batch automation.
- Live preview — See changes in real time as you adjust settings
- Multi-source artwork — TMDb, TVDB, and Fanart.tv with configurable priority
- Logo system — Clearlogos with white/color/first preference, hex tinting, and fallback rules
- ClearLogo editor — Browse, select, or upload logos and push them to Plex independently
- Batch edit — Select your whole library and apply a preset in one run
- Webhooks — Auto-generate posters when Tautulli fires an event (new/updated media)
- Scheduled scans — Cron-based library syncing for hands-off automation
- Smart retry queue — Items that couldn't get an ideal poster (missing logo, no textless poster) are queued and retried automatically until resolved
- Existing content mode — Choose whether a webhook/scan regenerates the poster or resends the last cached one (protects manually tuned posters)
- Video — Resolution (4K, 1080p, 720p) and video codec (HEVC, AV1, H.264)
- Audio — Codec (Atmos, DTS-X, TrueHD), channels, language
- Edition — Theatrical, Extended, Director's Cut, IMAX, Unrated
- Studio / Streaming platform — Auto-detected from TMDb
- Custom images — Upload your own badge assets (4K logo, Dolby Vision seal, etc.)
- Text labels — Custom text with full font/size/color control
- Overlay cache — Pre-rendered effect layers for 3–5x faster batch rendering
- Smart caching — SessionStorage LRU, SQLite-backed poster/label cache, indexed queries
- Concurrent rendering — Configurable worker count (1–4)
- Lazy loading — Posters load on-demand as you scroll
- 6 themes — Neon, Slate, Dracula, Nord, OLED, Light
- Notifications — Discord and Apprise (70+ services) with per-event toggles
- History — Full audit log with source tracking, fallback indicators, and hover previews
- Retry queue — Dedicated tab in History showing pending retries with per-item actions
docker run -d \
--name simposter \
-p 8003:8003 \
-v /path/to/config:/config \
simposter:latestOpen http://localhost:8003 and configure Plex/TMDb in Settings.
services:
simposter:
image: simposter:latest
ports:
- "8003:8003"
volumes:
- ./config:/config
environment:
- PLEX_URL=http://plex:32400
- PLEX_TOKEN=your_token_here
- TMDB_API_KEY=your_tmdb_key# Windows
build-docker.bat
# Linux/Mac
./build-docker.sh
# Manual (specify branch label)
docker build --build-arg GIT_BRANCH=dev -t simposter:latest .# Backend
uvicorn backend.main:app --reload --port 8003
# Frontend (separate terminal)
cd frontend && npm install && npm run devTemplates define the rendering logic. Currently there is one: Uniform Logo, which places the clearlogo inside a configurable bounding box zone with matte, fade, vignette, grain, and wash effects.
Presets store a named snapshot of template settings:
- Logo zone (top-left, top-center, bottom-left, etc.)
- Visual effects and intensities
- Text overlays using
{title}/{year}variables - Linked overlay badge configuration
- Fallback rules (switch templates/presets when a logo or textless poster is missing)
Presets can be exported and imported as JSON.
Logos are sourced from TMDb, Fanart.tv, and TVDB, then merged with priority/fallback logic.
| Mode | Behaviour |
|---|---|
| Stock | Original logo colors |
| Match | Tints logo to match the poster's dominant color |
| Hex | Custom hex color (best with white logos) |
| None | No logo rendered |
| Preference | Picks |
|---|---|
| White | Lowest saturation logo |
| Color | Highest saturation logo |
| First | First available |
Fallback options when no logo is found:
- Continue without logo
- Skip rendering entirely
- Switch to a different template/preset (e.g., a text-only fallback)
Badges pull live metadata from Plex (resolution, codec, audio channels, edition title) and render on top of the poster. Each badge value can be individually set to None, Text, or Image mode — so you can show 4K as a badge image but render Dolby Atmos as text, for example.
Badge visibility can also be controlled with Plex labels: show_if_label / hide_if_label.
When a poster is generated via batch, webhook, or auto-scan and the ideal template conditions aren't met (e.g., no clearlogo found, or no textless poster available), Simposter adds the item to a retry queue. A background job periodically re-attempts the poster until the ideal result is achieved, then resolves the item and removes it from the queue.
- Toggle on/off in Settings → Performance
- Retry interval — configurable in hours
- Max attempts — 0 = unlimited, or set a cap
- Manual override — sending a poster manually removes it from the queue immediately
The Retry Queue is visible in History → Retry Queue tab, with per-item Retry Now and Dismiss actions.
- Open Movies or TV Shows and click a title
- Choose a template and preset in the editor panel
- Preview updates live — switch poster/logo sources, adjust effects
- Save to disk and/or Send to Plex
- Go to Batch Edit (Movies or TV)
- Select items — use search, label filters, or select all
- Choose template + preset
- Preview — step through selected items to spot-check renders
- Set labels to remove (optional)
- Run the batch — progress tracked live, results summary shown when complete
Webhook (Tautulli):
http://your-server:8003/api/webhook/tautulli?template_id=uniformlogo&preset_id=default&event_types=added
Scheduled scans: Configure a cron expression in Settings → Libraries (e.g., 0 2 * * * for 2 AM daily).
Existing content mode (Settings → Performance):
Regenerate(default) — always creates a fresh posterResend— if a Simposter poster already exists for the title, pushes the cached render back to Plex without regenerating. Useful when you've manually tuned a poster and don't want webhooks overwriting it.
Smart retry: Items that couldn't get an ideal poster during any automated run are queued and retried on the configured interval. See Smart Retry Queue.
| Tab | What's in it |
|---|---|
| General | Theme, poster display density, deduplication, default sort |
| Libraries | Plex connection, library mappings, auto-generate preset, webhook ignore labels, label removal |
| Save Locations | Output path templates for movies and TV shows, batch subfolder option |
| Performance | Image format/quality, concurrent renders, overlay cache, API rate limits, automation (retry queue, existing content mode) |
| Notifications | Discord webhook and Apprise URLs, per-event toggles (batch / manual / webhook / auto-generate) |
| Advanced | API source priority order, database backup/restore |
History tab — every poster generation is logged:
- Timestamp, template, preset, source (manual / batch / webhook / auto-generate)
- Whether a fallback template was used
- Hover "View" to preview the poster thumbnail
- Filter by library, template, action
Retry Queue tab — shows items still waiting for an ideal poster:
- Reason badge: No Logo, Poster Fallback, or Both
- Attempt count and last-tried timestamp
- Retry Now — trigger an immediate retry
- Dismiss — remove from queue without retrying
http://your-server:8003/api/webhook/tautulli?template_id=uniformlogo&preset_id=default&event_types=added
Method: POST
Trigger: Recently Added
Movies:
{
"event": "{action}",
"media_type": "{media_type}",
"title": "{title}",
"year": "{year}",
"rating_key": "{rating_key}",
"tmdb_id": "{themoviedb_id}",
"thetvdb_id": "{thetvdb_id}"
}TV Shows:
{
"event": "{action}",
"media_type": "{media_type}",
"title": "{show_name}",
"year": "{year}",
"rating_key": "{rating_key}",
"tmdb_id": "{themoviedb_id}",
"thetvdb_id": "{thetvdb_id}"
}| Tautulli Event | Simposter value | Fires when |
|---|---|---|
library.new / created |
added |
New media added |
library.update |
updated |
Metadata updated |
playback.stop |
watched |
Playback finished |
In Settings → Libraries → Webhook Ignore Labels, list Plex labels that should skip poster generation (e.g., Custom, NoOverlay). Case-insensitive.
http://your-server:8003/api/webhook/tautulli?template_id=uniformlogo&preset_id=default&event_types=added&test=true
Dry-run — logs the event without generating a poster.
| Variable | Required | Example |
|---|---|---|
PLEX_URL |
Yes | http://plex:32400 |
PLEX_TOKEN |
Yes | xxxyyyzzz |
PLEX_MOVIE_LIBRARY_NAME |
Yes | Movies |
PLEX_TV_LIBRARY_NAME |
No | TV Shows |
TMDB_API_KEY |
Yes | abcd1234 |
TVDB_API_KEY |
No | efgh5678 |
FANART_API_KEY |
No | ijkl9012 |
CONFIG_DIR |
No (Docker) | /config |
All of these can also be set (and overridden) via the Settings UI.
config/
├── settings/
│ └── simposter.db # SQLite — settings, presets, history, cache
├── logs/
│ └── simposter.log # Application logs
├── cache/
│ └── poster_renders/ # Cached rendered posters for resend mode
└── output/ # Saved poster files
└── {Library}/
└── {Title} ({Year}).jpg
Legacy presets.json and ui_settings.json migrate automatically to SQLite on first run. A database backup is created automatically on version upgrades.
- Textless posters look best with matte and fade effects — filter for them in the poster picker
- Save presets before running a batch so you can reproduce the same look later
- Overlay cache gives the biggest batch speed boost — keep it on (Settings → Performance)
- Retry queue means a missing logo today won't be missing forever — Fanart.tv gets new logos regularly
- Check logs in Settings → Logs to diagnose webhook or API key issues
- ARCHITECTURE.md — Technical architecture, API routers, rendering pipeline
- CHANGELOG.md — Full version history
No affiliation — just projects worth knowing about.
Poster styles that inspired Simposter:
Related projects:
- Posterizarr — Another poster automation tool for Plex
- Kometa — Plex metadata and collection manager
- TitleCardMaker — Automated title card generation for TV shows
- UMTK — Upcoming media overlays for Plex
MIT License — See LICENSE for details.
Built with FastAPI, Vue 3, Pillow, TMDb API, TVDB API, and Fanart.tv API.
Developed with the assistance of Claude. All features are designed, directed, and tested by a human. (Still learning! :D)



