Programmatic thumbnail and social image generation with layered Python and JSON APIs
Project description
QuickThumb
QuickThumb is a Python library for programmatic thumbnail, social card, and promo image generation. It is designed for code-first and JSON-first workflows, with a layer-based API that works well for human-authored scripts and AI-generated specs.
Gallery
| YouTube Thumbnail | Burnout Thumbnail | Instagram News Card |
|---|---|---|
| Talking Head | Reaction / Commentary | Tutorial / Explainer |
|---|---|---|
Why QuickThumb
- Built for thumbnails and social graphics, not just generic image composition
- Works with Python method chaining and JSON serialization/deserialization
- Handles gradients, remote images, rich text, shapes, blend modes, and export helpers
- Good fit for AI-assisted workflows that need deterministic image specs
Installation
uv pip install quickthumb
Optional background removal support:
uv pip install "quickthumb[rembg]"
Quick Start
from quickthumb import Background, Canvas, Filter, Shadow, Stroke, TextPart
canvas = (
Canvas.from_aspect_ratio("16:9", base_width=1280)
.background(
image="https://images.unsplash.com/photo-1516321318423-f06f85e504b3",
effects=[Filter(brightness=0.65)],
)
.background(color="#000000", opacity=0.45)
.text(
content=[
TextPart(
text="BUILD THUMBNAILS\nFAST\n",
color="#B8FF00",
effects=[Stroke(width=8, color="#000000")],
),
TextPart(
text="With Python or JSON specs",
color="#F5F5F5",
size=44,
effects=[Shadow(offset_x=2, offset_y=2, color="#000000", blur_radius=4)],
),
],
size=112,
position=("8%", "50%"),
align=("left", "middle"),
weight=900,
)
.outline(width=14, color="#B8FF00")
)
canvas.render("thumbnail.png")
Core API
Create a canvas
from quickthumb import Canvas
canvas = Canvas(1280, 720)
square = Canvas.from_aspect_ratio("1:1", base_width=1080)
vertical = Canvas.from_aspect_ratio("9:16", base_width=1080)
Background layers
from quickthumb import Canvas, Filter, FitMode, LinearGradient
canvas = (
Canvas(1280, 720)
.background(color="#101828")
.background(
gradient=LinearGradient(
angle=120,
stops=[("#0F172A", 0.0), ("#0F172A00", 1.0)],
),
)
.background(
image="hero.jpg",
fit=FitMode.COVER,
blend_mode="multiply",
effects=[Filter(blur=4, brightness=0.75, contrast=1.1, saturation=0.9)],
)
)
Text layers and rich text
from quickthumb import Background, Canvas, Glow, Shadow, Stroke, TextPart
canvas = Canvas(1280, 720).text(
content=[
TextPart(text="5 ", color="#FBBF24", weight=900),
TextPart(text="WARNING SIGNS", color="#FFFFFF", weight=900),
],
size=72,
position=(80, 540),
effects=[
Background(color="#111827CC", padding=(16, 22), border_radius=12),
Stroke(width=2, color="#000000"),
Shadow(offset_x=4, offset_y=4, color="#000000", blur_radius=8),
Glow(color="#F59E0B", radius=14, opacity=0.35),
],
)
Image layers
from quickthumb import Canvas, Filter
canvas = Canvas(1280, 720).image(
path="portrait.png",
position=("73%", "52%"),
width=420,
height=520,
fit="cover",
align=("center", "middle"),
border_radius=24,
remove_background=True,
blend_mode="normal",
effects=[Filter(contrast=1.1, saturation=1.05)],
)
Shape layers
from quickthumb import Canvas, Shadow, Stroke
canvas = Canvas(1280, 720).shape(
shape="rectangle",
position=(64, 60),
width=320,
height=88,
color="#CC0000",
border_radius=10,
effects=[
Stroke(width=2, color="#FFFFFF"),
Shadow(offset_x=0, offset_y=6, color="#000000", blur_radius=12),
],
)
Export helpers
png_base64 = canvas.to_base64(format="PNG")
jpeg_data_url = canvas.to_data_url(format="JPEG", quality=90)
canvas.render("output.webp", format="WEBP", quality=90)
JSON-First Workflow
QuickThumb can round-trip most canvases through JSON:
from quickthumb import Canvas
config = """
{
"width": 1280,
"height": 720,
"layers": [
{
"type": "background",
"color": "#111827"
},
{
"type": "text",
"content": "Hello QuickThumb",
"size": 72,
"color": "#FFFFFF",
"align": "center",
"position": ["50%", "50%"]
},
{
"type": "outline",
"width": 10,
"color": "#22C55E"
}
]
}
"""
canvas = Canvas.from_json(config)
canvas.render("hello.png")
serialized = canvas.to_json()
Notes:
- JSON uses top-level
width,height, andlayers - Named custom layers added with
canvas.custom(fn, name="...", kwargs={...})are JSON-serializable via the registry; unnamed custom layers are not - Enum-like values such as
blend_mode,fit, andaligncan be passed as strings
AI-Friendly Workflows
QuickThumb is a good target when you want an LLM to generate image specs that are deterministic and easy to validate.
Prompt pattern for Python generation:
Generate QuickThumb Python code for a 1280x720 YouTube thumbnail.
Use layered composition only.
Keep text on the left, subject image on the right, and use high-contrast typography.
Return runnable code that ends with canvas.render("thumbnail.png").
Prompt pattern for JSON generation:
Generate a QuickThumb JSON config with top-level width, height, and layers.
Use one background image layer, one dark overlay background layer, two text layers, and one outline layer.
Only use valid QuickThumb layer types and effect names.
Recommended workflow:
- Have the model produce QuickThumb Python or JSON.
- Validate or render it locally.
- Adjust only the content, colors, and assets instead of rewriting layout logic from scratch.
Environment Variables
QuickThumb looks for fonts using these environment variables:
QUICKTHUMB_FONT_DIR: directory that contains font filesQUICKTHUMB_DEFAULT_FONT: default font family/name to use whenfontis omitted
Example:
import os
os.environ["QUICKTHUMB_FONT_DIR"] = "assets/fonts"
os.environ["QUICKTHUMB_DEFAULT_FONT"] = "Roboto"
Feature Matrix
| Area | Supported |
|---|---|
| Canvas sizing | Explicit width/height, from_aspect_ratio() |
| Backgrounds | Solid colors, linear gradients, radial gradients, local/remote images |
| Background controls | Opacity, blend modes, fit modes, blur, brightness, contrast, saturation |
| Text | Positioning, alignment, wrapping, letter spacing, line height, rotation, auto-scale |
| Rich text | Per-segment TextPart styling |
| Text effects | Stroke, shadow, glow, background fill |
| Fonts | Local fonts, CSS-style weights, italic/bold flags, webfont URLs, fallback mapping |
| Images | Local/remote images, sizing, fit modes, alignment, opacity, rotation |
| Image effects | Stroke, shadow, glow, filter effects, border radius, background removal |
| Shapes | Rectangle and ellipse primitives with stroke/shadow/glow support |
| Export | PNG, JPEG, WebP, file output, base64, data URLs |
| Serialization | to_json() / from_json() for built-in layer types and named custom layers |
Real Example Scripts
See the shipped examples in examples/README.md:
examples/youtube_thumbnail_01.pyexamples/youtube_thumbnail_02.pyexamples/instagram_news_card.py
Gotchas
weightandbold=Trueare mutually exclusive on text layers andTextPartauto_scale=Truerequiresmax_widthpositionpercentage values must be strings like"50%"canvas.custom(fn)without anameruns during render order but cannot be serialized to JSON; passname=and register the function withCanvas.register_layer_fn()to enable serialization
Development
uv sync
uv run pytest
uv run ruff check .
uv run ty quickthumb/
Reference
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quickthumb-0.4.0.tar.gz.
File metadata
- Download URL: quickthumb-0.4.0.tar.gz
- Upload date:
- Size: 29.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d8742ae113def9360f51d3fd850f5ec39856d07e483331ff9412d894ef95b67
|
|
| MD5 |
20add0f14d0686c71d4f7f97ffdc0fa4
|
|
| BLAKE2b-256 |
f38871352da566376ffc8fe648f5000fd71af5bc5f33fb5e9ac6266b8b39b35e
|
File details
Details for the file quickthumb-0.4.0-py3-none-any.whl.
File metadata
- Download URL: quickthumb-0.4.0-py3-none-any.whl
- Upload date:
- Size: 29.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92b6619d483b35e5af5fb8606ca38736a3ac36fa851991bc77a5310baa26805b
|
|
| MD5 |
5de461add8857cbf8c28273484efb5e4
|
|
| BLAKE2b-256 |
9a35f47b52d32ab39b74a1c11adcd7e37c3567462e4ce2fe2ff78f4c8aaf4357
|