from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
import textwrap, os, math
W, H = 1200, 900
out = Path("/mnt/data/screenshot.png")
# Fonts
def font(size, bold=False):
paths = [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf" if bold else "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation2/LiberationSans-Bold.ttf" if bold else "/usr/share/fonts/truetype/liberation2/LiberationSans-Regular.ttf",
]
for p in paths:
if os.path.exists(p):
return ImageFont.truetype(p, size)
return ImageFont.load_default()
title_f = font(58, True)
sub_f = font(25, False)
h_f = font(24, True)
body_f = font(18, False)
small_f = font(15, False)
tiny_f = font(13, False)
img = Image.new("RGB", (W, H), (248, 250, 252))
draw = ImageDraw.Draw(img)
# Background gradient
for y in range(H):
r = int(9 + (248-9) * y / H)
g = int(33 + (250-33) * y / H)
b = int(65 + (252-65) * y / H)
draw.line([(0, y), (W, y)], fill=(r, g, b))
# Decorative circles
for cx, cy, rad, color in [
(1050, 80, 180, (37, 99, 235)),
(90, 760, 230, (14, 165, 233)),
(1120, 820, 210, (16, 185, 129)),
]:
overlay = Image.new("RGBA", (W,H), (0,0,0,0))
od = ImageDraw.Draw(overlay)
od.ellipse((cx-rad, cy-rad, cx+rad, cy+rad), fill=color+(46,))
img = Image.alpha_composite(img.convert("RGBA"), overlay).convert("RGB")
draw = ImageDraw.Draw(img)
# Main card
margin = 48
card = (margin, margin, W-margin, H-margin)
draw.rounded_rectangle(card, radius=36, fill=(255,255,255), outline=(226,232,240), width=2)
# Header
draw.rounded_rectangle((75,75,1125,205), radius=28, fill=(15,23,42))
draw.text((105,95), "RX THEME", font=title_f, fill=(255,255,255))
draw.text((108,164), "Advanced WordPress Medical Blog + Performance + SEO Framework", font=sub_f, fill=(203,213,225))
# Version pill
draw.rounded_rectangle((890,98,1096,145), radius=22, fill=(34,197,94))
draw.text((922,110), "v1.0 Pro Ready", font=body_f, fill=(4,34,17))
# Browser mockup
draw.rounded_rectangle((88,235,535,770), radius=22, fill=(241,245,249), outline=(203,213,225), width=2)
draw.rounded_rectangle((88,235,535,282), radius=22, fill=(226,232,240))
for x, c in [(115,(239,68,68)),(143,(245,158,11)),(171,(34,197,94))]:
draw.ellipse((x,252,x+14,266), fill=c)
draw.rounded_rectangle((205,249,505,267), radius=9, fill=(255,255,255))
draw.text((220,250), "rxharun.com", font=tiny_f, fill=(71,85,105))
# Mock website content
draw.rounded_rectangle((115,315,505,370), radius=14, fill=(15,23,42))
draw.text((138,332), "Global War Against Illness", font=h_f, fill=(255,255,255))
draw.rounded_rectangle((115,395,505,520), radius=18, fill=(255,255,255), outline=(226,232,240), width=2)
draw.text((140,415), "Evidence-Based Medical Article", font=body_f, fill=(15,23,42))
for y in [450, 475, 500]:
draw.rounded_rectangle((140,y,475,y+9), radius=4, fill=(203,213,225))
draw.rounded_rectangle((115,545,300,695), radius=18, fill=(255,255,255), outline=(226,232,240), width=2)
draw.text((137,565), "Schema", font=body_f, fill=(15,23,42))
draw.text((137,600), "FAQ • Article", font=small_f, fill=(71,85,105))
draw.text((137,625), "Breadcrumb", font=small_f, fill=(71,85,105))
draw.text((137,650), "Medical Webpage", font=small_f, fill=(71,85,105))
draw.rounded_rectangle((320,545,505,695), radius=18, fill=(255,255,255), outline=(226,232,240), width=2)
draw.text((342,565), "Speed", font=body_f, fill=(15,23,42))
draw.text((342,600), "Preload", font=small_f, fill=(71,85,105))
draw.text((342,625), "Defer JS", font=small_f, fill=(71,85,105))
draw.text((342,650), "Lazy Load", font=small_f, fill=(71,85,105))
# Feature columns
features = [
("Core Theme", ["Theme setup", "Menus", "Sidebars", "Image sizes", "Template tags", "Cleanup", "Customizer", "Block styles"]),
("Performance", ["Preload fonts", "DNS prefetch", "Preconnect", "Defer scripts", "Async scripts", "Lazy images", "Critical CSS", "Cache headers"]),
("SEO System", ["Meta title", "Meta description", "Canonical URL", "Open Graph", "Twitter Cards", "XML sitemap", "Robots rules", "Schema JSON-LD"]),
("Medical Content", ["Article schema", "FAQ schema", "HowTo schema", "Breadcrumbs", "Reading time", "Author box", "References block", "Review-ready layout"]),
("Blog Features", ["Related posts", "Pagination", "Post views", "Social share", "Table of contents", "Search page", "Archive design", "No-result template"]),
("Security", ["Escaping", "Sanitization", "Nonce checks", "Disable XML-RPC", "Login cleanup", "REST hardening", "Header security", "Safe uploads"]),
("Developer Tools", ["Hooks", "Filters", "Helper functions", "Modular inc files", "Asset versioning", "Debug mode", "Child theme ready", "Translation ready"]),
("Future Ready", ["CDN support", "PWA ready", "AMP friendly", "Core Web Vitals", "Accessibility", "Woo support", "Blocks", "Headless-ready"]),
]
start_x, start_y = 575, 245
col_w, row_h = 255, 145
gap_x, gap_y = 25, 20
for i, (head, items) in enumerate(features):
col = i % 2
row = i // 2
x = start_x + col*(col_w+gap_x)
y = start_y + row*(row_h+gap_y)
draw.rounded_rectangle((x,y,x+col_w,y+row_h), radius=18, fill=(248,250,252), outline=(226,232,240), width=2)
draw.text((x+18,y+14), head, font=h_f, fill=(15,23,42))
tx = x+18
ty = y+50
for j, item in enumerate(items):
bullet_x = tx
bullet_y = ty + j*11
draw.ellipse((bullet_x, bullet_y+4, bullet_x+5, bullet_y+9), fill=(37,99,235))
draw.text((bullet_x+12, bullet_y), item, font=tiny_f, fill=(51,65,85))
# Footer bar
draw.rounded_rectangle((75,795,1125,842), radius=20, fill=(239,246,255), outline=(191,219,254), width=1)
footer = "Fast • Secure • SEO Optimized • Medical Content Ready • Modular Code Architecture • Core Web Vitals Focused"
tw = draw.textlength(footer, font=body_f)
draw.text(((W-tw)/2, 808), footer, font=body_f, fill=(30,64,175))
# WordPress screenshot recommendation
note = "Recommended WordPress theme screenshot size: 1200 × 900 px"
tw = draw.textlength(note, font=small_f)
draw.text(((W-tw)/2, 858), note, font=small_f, fill=(100,116,139))
img.save(out, "PNG", optimize=True)
out.as_posix()