**PROFESSIONAL MASTER PROMPT FOR 10 HEALTH AWARENESS POSTS** Create a series of **10 Premium Medical Awareness Posts** in **Urdu** for social media sharing (1080x1080 px). ### OBJECTIVE: Design educational healthcare awareness posts about the most common and currently increasing health issues. Each post must provide: * Disease Name * Brief Introduction * Common Signs & Symptoms * Possible Causes * Prevention & Safety Measures * When to Consult a Doctor * Short Professional Disclaimer ### DESIGN STYLE: * Premium Hospital Branding * Modern Medical Infographic Style * Clean Healthcare Layout * White, Blue, Teal, and Green Color Theme * Professional Medical Icons and 3D Elements * Easy-to-read Urdu Typography * High Trust and Healthcare Authority Appearance * Suitable for WhatsApp Groups, Facebook, Instagram, and WhatsApp Status ### POST TOPICS: **Post 1:** مثانے کا انفیکشن (Bladder Infection) **Post 2:** گردوں کی پتھری (Kidney Stones) **Post 3:** بانجھ پن / اولاد نہ ہونا (Infertility) **Post 4:** ہائی بلڈ پریشر (High Blood Pressure) **Post 5:** ذیابیطس / شوگر (Diabetes) **Post 6:** کان، ناک اور گلے کی الرجی (ENT Allergies) **Post 7:** جوڑوں اور کمر کا درد (Joint & Back Pain) **Post 8:** پیشاب میں جلن اور انفیکشن (Urinary Tract Infection) **Post 9:** معدے کی تیزابیت اور گیس (Acidity & Gastric Problems) **Post 10:** موسمی بخار، نزلہ اور کھانسی (Seasonal Flu & Cough) ### FOOTER ON EVERY POST: **شفا آن لائن کنسلٹیشن** ✔ ماہر ڈاکٹروں سے آن لائن مشاورت ✔ گھر بیٹھے رہنمائی حاصل کریں ✔ Paid Consultation Services Available 📱 WhatsApp: +92XXXXXXXXXX ⏰ Appointment Required 💳 Paid Medical Consultation Service ### DISCLAIMER: "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔" ### CONTENT REQUIREMENT: * Simple and Correct Urdu * Medically Accurate Information * Maximum 80-120 words per post * Professional Healthcare Tone * No Fear-Based Language * Focus on Awareness, Prevention, Safety, and Early Consultation
mkdir -p /home/daytona/workspace/shifa-health-posts && ls /home/daytona/workspace/shifa-health-posts/
~/shifa-health-posts/generate_posts.py
#!/usr/bin/env python3
"""
Generate 10 Premium Urdu Health Awareness Posts (1080x1080px)
Shifa Online Consultation - Medical Infographic Series
"""
from PIL import Image, ImageDraw, ImageFont
import os, sys, math, textwrap
OUTPUT_DIR = "/home/daytona/workspace/shifa-health-posts/output"
os.makedirs(OUTPUT_DIR, exist_ok=True)
# ── Color Palette ──────────────────────────────────────────────
C_BG = (245, 250, 255) # very light blue-white bg
C_HEADER_TOP = (0, 86, 150) # deep medical blue
C_HEADER_BOT = (0, 140, 160) # teal
C_ACCENT = (0, 168, 120) # green accent
C_CARD = (255, 255, 255) # white card
C_CARD_BD = (210, 235, 245) # card border
C_TITLE_TXT = (255, 255, 255) # white on header
C_SECTION_HD = (0, 100, 140) # section heading
C_BODY_TXT = (40, 55, 70) # dark blue-grey body
C_FOOTER_BG = (0, 86, 150) # deep blue footer
C_FOOTER_TXT = (255, 255, 255)
C_DISC_BG = (230, 245, 240)
C_DISC_TXT = (50, 90, 80)
C_BADGE = (0, 168, 120)
C_WHITE = (255, 255, 255)
C_LIGHT_TEAL = (220, 245, 245)
W, H = 1080, 1080
# ── Font Setup ─────────────────────────────────────────────────
# We'll try system fonts with Urdu / Arabic support
def load_font(size, bold=False):
candidates = [
"/usr/share/fonts/truetype/noto/NotoNaskhArabic-Bold.ttf" if bold else
"/usr/share/fonts/truetype/noto/NotoNaskhArabic-Regular.ttf",
"/usr/share/fonts/truetype/noto/NotoNastaliqUrdu-Regular.ttf",
"/usr/share/fonts/truetype/noto/NotoSansArabic-Bold.ttf" if bold else
"/usr/share/fonts/truetype/noto/NotoSansArabic-Regular.ttf",
"/usr/share/fonts/truetype/lohit-urdu/Lohit-Urdu.ttf",
"/usr/share/fonts/truetype/freefont/FreeSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
]
for path in candidates:
if os.path.exists(path):
try:
return ImageFont.truetype(path, size)
except Exception:
continue
return ImageFont.load_default()
def list_arabic_fonts():
import glob
fonts = glob.glob("/usr/share/fonts/**/*.ttf", recursive=True)
arabic = [f for f in fonts if any(k in f.lower() for k in ["arabic","urdu","nastaliq","naskh","noto"])]
return arabic
print("Available Arabic/Urdu fonts:", list_arabic_fonts()[:10])
# ── Text helpers ───────────────────────────────────────────────
def draw_text_centered(draw, text, font, y, color, width=W, x_offset=0):
"""Draw centered text, returns bottom y."""
bbox = draw.textbbox((0, 0), text, font=font)
tw = bbox[2] - bbox[0]
x = (width - tw) // 2 + x_offset
draw.text((x, y), text, font=font, fill=color)
return y + (bbox[3] - bbox[1]) + 4
def draw_text_right(draw, text, font, x_right, y, color):
bbox = draw.textbbox((0, 0), text, font=font)
tw = bbox[2] - bbox[0]
draw.text((x_right - tw, y), text, font=font, fill=color)
return y + (bbox[3] - bbox[1]) + 4
def text_height(draw, text, font):
bbox = draw.textbbox((0, 0), text, font=font)
return bbox[3] - bbox[1]
def draw_wrapped_rtl(draw, text, font, x_left, x_right, y, color, line_spacing=8):
"""Simple right-aligned wrapped text block for RTL languages."""
words = text.split()
lines = []
current = []
max_w = x_right - x_left
for word in words:
test = " ".join(current + [word])
bbox = draw.textbbox((0, 0), test, font=font)
if bbox[2] - bbox[0] <= max_w:
current.append(word)
else:
if current:
lines.append(" ".join(current))
current = [word]
if current:
lines.append(" ".join(current))
for line in lines:
bbox = draw.textbbox((0, 0), line, font=font)
tw = bbox[2] - bbox[0]
th = bbox[3] - bbox[1]
draw.text((x_right - tw, y), line, font=font, fill=color)
y += th + line_spacing
return y
# ── Shape helpers ──────────────────────────────────────────────
def rounded_rect(draw, xy, radius, fill, outline=None, outline_width=2):
x1, y1, x2, y2 = xy
draw.rounded_rectangle([x1, y1, x2, y2], radius=radius, fill=fill,
outline=outline, width=outline_width)
def gradient_rect(img, x1, y1, x2, y2, color_top, color_bot):
"""Vertical gradient by drawing horizontal lines."""
draw = ImageDraw.Draw(img)
height = y2 - y1
for i in range(height):
t = i / max(height - 1, 1)
r = int(color_top[0] + (color_bot[0] - color_top[0]) * t)
g = int(color_top[1] + (color_bot[1] - color_top[1]) * t)
b = int(color_top[2] + (color_bot[2] - color_top[2]) * t)
draw.line([(x1, y1 + i), (x2, y1 + i)], fill=(r, g, b))
def draw_circle(draw, cx, cy, r, fill, outline=None, ow=2):
draw.ellipse([cx-r, cy-r, cx+r, cy+r], fill=fill, outline=outline, width=ow)
def draw_icon_medical_cross(draw, cx, cy, size, color):
"""Draw a simple medical cross."""
t = size // 4
draw.rectangle([cx - t, cy - size//2, cx + t, cy + size//2], fill=color)
draw.rectangle([cx - size//2, cy - t, cx + size//2, cy + t], fill=color)
def draw_decorative_bg(img):
"""Add subtle decorative circles to background."""
draw = ImageDraw.Draw(img)
# Large faint circle top-right
draw_circle(draw, 980, 80, 120, (0, 140, 160, 30))
draw_circle(draw, 100, 200, 80, (0, 168, 120, 20))
draw_circle(draw, 950, 500, 60, (0, 86, 150, 15))
# ── Section icon emoji-style symbols ──────────────────────────
ICONS = {
"intro": "📋",
"symptoms": "🩺",
"causes": "🔬",
"prevention":"🛡",
"doctor": "👨⚕️",
}
# ── Post Data ──────────────────────────────────────────────────
POSTS = [
{
"num": 1,
"emoji": "🫀",
"title_ur": "مثانے کا انفیکشن",
"title_en": "Bladder Infection (UTI)",
"color_accent": (0, 130, 180),
"intro": "مثانے کا انفیکشن ایک عام بیماری ہے جو بیکٹیریا کی وجہ سے ہوتی ہے اور بروقت علاج سے ٹھیک ہو جاتی ہے۔",
"symptoms": "پیشاب میں جلن، بار بار پیشاب آنا، پیٹ کے نچلے حصے میں درد، بدبودار یا دھندلا پیشاب",
"causes": "بیکٹیریا (E. coli)، صفائی کا خیال نہ رکھنا، پانی کم پینا، ذیابیطس",
"prevention": "کافی پانی پئیں، صفائی کا خیال رکھیں، پیشاب روکنے سے گریز کریں، قوت مدافعت بڑھائیں",
"doctor": "اگر بخار ہو، کمر میں درد ہو، یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے رجوع کریں",
},
{
"num": 2,
"emoji": "🪨",
"title_ur": "گردوں کی پتھری",
"title_en": "Kidney Stones",
"color_accent": (0, 120, 170),
"intro": "گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ بہت تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
"symptoms": "کمر یا پہلو میں شدید درد، پیشاب میں خون، متلی، الٹی، پیشاب میں رکاوٹ",
"causes": "کم پانی پینا، کیلشیم / آکسیلیٹ والی غذائیں زیادہ کھانا، موروثی عوامل، بیٹھا رہنا",
"prevention": "روزانہ 8-10 گلاس پانی پئیں، نمک کم کھائیں، متوازن غذا اپنائیں، ورزش کریں",
"doctor": "پیٹ یا کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو جائے تو فوری ڈاکٹر سے ملیں",
},
{
"num": 3,
"emoji": "👶",
"title_ur": "بانجھ پن / اولاد نہ ہونا",
"title_en": "Infertility",
"color_accent": (0, 150, 130),
"intro": "بانجھ پن کوئی لاعلاج بیماری نہیں۔ جدید طبی علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
"symptoms": "ایک سال کوشش کے باوجود حمل نہ ہونا، ماہواری کی بے ترتیبی، ہارمون کی خرابی",
"causes": "ہارمون کا عدم توازن، PCOS، فیلوپین ٹیوب میں رکاوٹ، مردوں میں سپرم کی کمی، تناؤ",
"prevention": "صحت مند وزن برقرار رکھیں، تناؤ کم کریں، سگریٹ و شراب سے پرہیز، بروقت معائنہ کروائیں",
"doctor": "اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں۔ جلد تشخیص بہتر نتائج دیتی ہے",
},
{
"num": 4,
"emoji": "❤️",
"title_ur": "ہائی بلڈ پریشر",
"title_en": "High Blood Pressure (Hypertension)",
"color_accent": (180, 50, 60),
"intro": "ہائی بلڈ پریشر کو 'خاموش قاتل' کہا جاتا ہے۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کیا جا سکتا ہے۔",
"symptoms": "سر درد، چکر آنا، دھندلی نظر، سینے میں درد، سانس لینے میں دشواری، ناک سے خون",
"causes": "نمک زیادہ کھانا، موٹاپا، ورزش نہ کرنا، تناؤ، موروثی، ذیابیطس، سگریٹ نوشی",
"prevention": "نمک کم کریں، ورزش کریں، وزن کنٹرول کریں، تناؤ سے بچیں، باقاعدہ BP چیک کروائیں",
"doctor": "اگر BP 140/90 سے زیادہ ہو، سر درد شدید ہو یا سینے میں درد ہو تو فوری ڈاکٹر سے ملیں",
},
{
"num": 5,
"emoji": "🩸",
"title_ur": "ذیابیطس / شوگر",
"title_en": "Diabetes (Sugar Disease)",
"color_accent": (0, 140, 100),
"intro": "ذیابیطس ایک دائمی بیماری ہے جو خون میں شکر کی سطح بڑھا دیتی ہے۔ طرز زندگی بدل کر اسے قابو کریں۔",
"symptoms": "بار بار پیشاب، زیادہ پیاس، وزن میں کمی، تھکاوٹ، زخم دیر سے بھرنا، نظر کمزور ہونا",
"causes": "موٹاپا، ورزش نہ کرنا، غیر صحت بخش کھانا، موروثی، ہارمون کی خرابی",
"prevention": "میٹھا کم کھائیں، ورزش کریں، وزن کنٹرول کریں، باقاعدہ بلڈ شوگر ٹیسٹ کروائیں",
"doctor": "اگر بلڈ شوگر بار بار زیادہ آئے، چکر آئے یا علامات ظاہر ہوں تو فوری ڈاکٹر سے ملیں",
},
{
"num": 6,
"emoji": "🤧",
"title_ur": "کان، ناک اور گلے کی الرجی",
"title_en": "ENT Allergies",
"color_accent": (0, 120, 180),
"intro": "ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
"symptoms": "چھینکیں، ناک بند یا بہنا، آنکھوں میں خارش، گلے میں خراش، کان میں بھاری پن",
"causes": "دھول، جرگ، پالتو جانور، کیمیکل، موسمی تبدیلی، کمزور قوت مدافعت",
"prevention": "دھول سے بچیں، ماسک پہنیں، گھر صاف رکھیں، الرجی کا ٹیسٹ کروائیں، قوت مدافعت بڑھائیں",
"doctor": "اگر سانس لینے میں دشواری ہو، علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں",
},
{
"num": 7,
"emoji": "🦴",
"title_ur": "جوڑوں اور کمر کا درد",
"title_en": "Joint & Back Pain",
"color_accent": (100, 80, 160),
"intro": "جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
"symptoms": "جوڑوں میں سوجن و اکڑن، کمر میں درد، حرکت میں دشواری، صبح کے وقت اکڑن",
"causes": "آرتھرائٹس، یورک ایسڈ، موٹاپا، غلط بیٹھنے کا انداز، کیلشیم کی کمی، چوٹ",
"prevention": "ورزش کریں، وزن کم کریں، کیلشیم / وٹامن D لیں، صحیح بیٹھیں، بھاری وزن نہ اٹھائیں",
"doctor": "اگر درد شدید ہو، سوجن آئے یا چلنا مشکل ہو جائے تو آرتھوپیڈک ڈاکٹر سے ملیں",
},
{
"num": 8,
"emoji": "💧",
"title_ur": "پیشاب میں جلن اور انفیکشن",
"title_en": "Urinary Tract Infection (UTI)",
"color_accent": (0, 140, 160),
"intro": "UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو گردوں تک پہنچ سکتا ہے۔",
"symptoms": "پیشاب میں جلن، بار بار آنا، رنگ غیر معمولی، بدبو، پیٹ کے نچلے حصے میں درد",
"causes": "بیکٹیریا، صفائی نہ رکھنا، پانی کم پینا، ذیابیطس، قوت مدافعت کی کمزوری",
"prevention": "پانی خوب پئیں، صفائی کا خیال رکھیں، نرم کپڑے پہنیں، پیشاب روکنے سے گریز کریں",
"doctor": "اگر بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں",
},
{
"num": 9,
"emoji": "🫁",
"title_ur": "معدے کی تیزابیت اور گیس",
"title_en": "Acidity & Gastric Problems",
"color_accent": (180, 110, 20),
"intro": "معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
"symptoms": "سینے میں جلن، ڈکار، پیٹ پھولنا، متلی، منہ میں کھٹاس، کھانے کے بعد تکلیف",
"causes": "مسالہ دار کھانا، چائے / کافی زیادہ، کھانے میں بے ترتیبی، تناؤ، سگریٹ نوشی",
"prevention": "کم مسالہ کھائیں، بروقت کھانا کھائیں، پانی پئیں، تناؤ کم کریں، تھوڑا تھوڑا کھائیں",
"doctor": "اگر سینے میں شدید جلن، خون آئے یا وزن کم ہو تو فوری ڈاکٹر سے ملیں",
},
{
"num": 10,
"emoji": "🌡️",
"title_ur": "موسمی بخار، نزلہ اور کھانسی",
"title_en": "Seasonal Flu & Cough",
"color_accent": (0, 130, 160),
"intro": "موسم کی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
"symptoms": "بخار، ناک بہنا یا بند ہونا، گلے میں خراش، کھانسی، جسم درد، کمزوری",
"causes": "وائرس / بیکٹیریا، موسمی تبدیلی، کمزور قوت مدافعت، بھیڑ میں رہنا",
"prevention": "ہاتھ دھوئیں، ماسک پہنیں، گرم پانی پئیں، قوت مدافعت بڑھائیں، فلو ویکسین لگوائیں",
"doctor": "اگر بخار 3 دن سے زیادہ رہے، سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں",
},
]
SECTION_LABELS = [
("intro", "تعارف"),
("symptoms", "علامات"),
("causes", "وجوہات"),
("prevention", "احتیاط و بچاؤ"),
("doctor", "ڈاکٹر سے کب ملیں"),
]
SECTION_ICONS = {
"intro": "📋",
"symptoms": "🩺",
"causes": "🔬",
"prevention": "🛡️",
"doctor": "👨⚕️",
}
FOOTER_LINES = [
"شفا آن لائن کنسلٹیشن",
"✔ ماہر ڈاکٹروں سے آن لائن مشاورت ✔ گھر بیٹھے رہنمائی حاصل کریں",
"📱 WhatsApp: +92XXXXXXXXXX ⏰ Appointment Required",
"💳 Paid Consultation Services Available",
]
DISCLAIMER = "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔"
def make_post(post):
img = Image.new("RGB", (W, H), C_BG)
draw = ImageDraw.Draw(img)
accent = post["color_accent"]
# ── Background decorative circles ──────────────────────────
for cx, cy, r, alpha in [(960, 60, 110, 18), (120, 180, 70, 15), (940, 540, 55, 12)]:
overlay = Image.new("RGBA", (W, H), (0, 0, 0, 0))
od = ImageDraw.Draw(overlay)
od.ellipse([cx-r, cy-r, cx+r, cy+r], fill=(*C_HEADER_BOT, alpha))
img.paste(Image.alpha_composite(img.convert("RGBA"), overlay).convert("RGB"))
draw = ImageDraw.Draw(img)
# ── Header gradient ─────────────────────────────────────────
gradient_rect(img, 0, 0, W, 180, C_HEADER_TOP, C_HEADER_BOT)
draw = ImageDraw.Draw(img)
# Header decorative arc (top right)
draw.ellipse([780, -80, 1160, 260], outline=(255,255,255,40), width=3)
draw.ellipse([820, -60, 1120, 220], outline=(255,255,255,25), width=2)
# Post number badge
badge_r = 28
draw_circle(draw, 60, 60, badge_r, C_ACCENT)
fnt_badge = load_font(22, bold=True)
num_str = str(post["num"])
b = draw.textbbox((0,0), num_str, font=fnt_badge)
draw.text((60 - (b[2]-b[0])//2, 60 - (b[3]-b[1])//2), num_str, font=fnt_badge, fill=C_WHITE)
# Medical cross icon (top left area)
draw_icon_medical_cross(draw, 115, 60, 28, (255,255,255,180))
# Emoji icon (large, right side of header)
fnt_emoji_large = load_font(64)
emoji = post["emoji"]
eb = draw.textbbox((0,0), emoji, font=fnt_emoji_large)
draw.text((W - 100 - (eb[2]-eb[0])//2, 58 - (eb[3]-eb[1])//2), emoji, font=fnt_emoji_large, fill=C_WHITE)
# Title Urdu
fnt_title_big = load_font(52, bold=True)
fnt_title_sm = load_font(24)
tb = draw.textbbox((0,0), post["title_ur"], font=fnt_title_big)
tw = tb[2] - tb[0]
draw.text(((W - tw)//2, 26), post["title_ur"], font=fnt_title_big, fill=C_WHITE)
# Title English subtitle
eb2 = draw.textbbox((0,0), post["title_en"], font=fnt_title_sm)
draw.text(((W - (eb2[2]-eb2[0]))//2, 104), post["title_en"], font=fnt_title_sm, fill=(200, 235, 255))
# Divider line under header
draw.rectangle([40, 182, W-40, 185], fill=C_ACCENT)
# ── Content cards ───────────────────────────────────────────
card_x1, card_x2 = 30, W - 30
card_y = 196
card_gap = 8
fnt_sec_hd = load_font(26, bold=True)
fnt_body = load_font(22)
fnt_icon = load_font(22)
section_data = [
("intro", "تعارف", post["intro"]),
("symptoms", "علامات", post["symptoms"]),
("causes", "وجوہات", post["causes"]),
("prevention", "احتیاط و بچاؤ", post["prevention"]),
("doctor", "ڈاکٹر سے کب ملیں", post["doctor"]),
]
# We need to pre-compute card heights to fit everything
# Estimate lines per section
def estimate_lines(text, font, max_w):
words = text.split()
lines, current_w = 0, 0
for w in words:
wb = draw.textbbox((0,0), w+" ", font=font)[2]
if current_w + wb > max_w:
lines += 1
current_w = wb
else:
current_w += wb
return lines + 1
# Fixed heights for cards - calculate remaining space
# Header = 185, Footer ~= 175, Disclaimer ~= 40, gaps
available_h = H - 185 - 175 - 48 - card_gap * 6
# 5 cards
card_h_each = available_h // 5 # approx 95px
inner_pad = 10
for key, label, text in section_data:
ch = card_h_each
# Draw card background
rounded_rect(draw, [card_x1, card_y, card_x2, card_y + ch], 14,
fill=C_CARD, outline=C_CARD_BD, outline_width=1)
# Left accent bar with section color
draw.rounded_rectangle([card_x1, card_y, card_x1+6, card_y+ch],
radius=8, fill=accent)
# Section icon + label on right
icon_str = SECTION_ICONS.get(key, "•")
icon_x = W - 55
ib = draw.textbbox((0,0), icon_str, font=fnt_icon)
draw.text((icon_x, card_y + inner_pad), icon_str, font=fnt_icon, fill=accent)
# Section heading
lb = draw.textbbox((0,0), label, font=fnt_sec_hd)
lw = lb[2] - lb[0]
draw.text((W - 70 - lw, card_y + inner_pad - 2), label, font=fnt_sec_hd, fill=C_SECTION_HD)
# Body text (right-aligned, wrapped)
text_y = card_y + inner_pad + (lb[3]-lb[1]) + 6
text_max_w = card_x2 - card_x1 - 20
draw_wrapped_rtl(draw, text, fnt_body,
card_x1 + 14, card_x2 - 14,
text_y, C_BODY_TXT, line_spacing=4)
card_y += ch + card_gap
# ── Disclaimer strip ────────────────────────────────────────
disc_y = card_y + 4
disc_h = 38
rounded_rect(draw, [30, disc_y, W-30, disc_y+disc_h], 10,
fill=C_DISC_BG, outline=(0,168,120), outline_width=1)
fnt_disc = load_font(18)
db = draw.textbbox((0,0), DISCLAIMER, font=fnt_disc)
dw = db[2] - db[0]
draw.text(((W - dw)//2, disc_y + (disc_h - (db[3]-db[1]))//2),
DISCLAIMER, font=fnt_disc, fill=C_DISC_TXT)
# ── Footer ──────────────────────────────────────────────────
footer_y = disc_y + disc_h + 6
footer_h = H - footer_y - 2
gradient_rect(img, 0, footer_y, W, H, C_FOOTER_BG, (0, 50, 100))
draw = ImageDraw.Draw(img)
# Footer top divider
draw.rectangle([0, footer_y, W, footer_y+3], fill=C_ACCENT)
fnt_footer_big = load_font(30, bold=True)
fnt_footer_sm = load_font(19)
fnt_footer_xs = load_font(16)
fy = footer_y + 10
# Line 1: Brand name
fl1b = draw.textbbox((0,0), FOOTER_LINES[0], font=fnt_footer_big)
draw.text(((W - (fl1b[2]-fl1b[0]))//2, fy), FOOTER_LINES[0],
font=fnt_footer_big, fill=C_WHITE)
fy += (fl1b[3]-fl1b[1]) + 6
# Line 2
fl2b = draw.textbbox((0,0), FOOTER_LINES[1], font=fnt_footer_sm)
draw.text(((W - (fl2b[2]-fl2b[0]))//2, fy), FOOTER_LINES[1],
font=fnt_footer_sm, fill=(200, 235, 255))
fy += (fl2b[3]-fl2b[1]) + 5
# Line 3
fl3b = draw.textbbox((0,0), FOOTER_LINES[2], font=fnt_footer_sm)
draw.text(((W - (fl3b[2]-fl3b[0]))//2, fy), FOOTER_LINES[2],
font=fnt_footer_sm, fill=(200, 235, 255))
fy += (fl3b[3]-fl3b[1]) + 5
# Line 4
fl4b = draw.textbbox((0,0), FOOTER_LINES[3], font=fnt_footer_xs)
draw.text(((W - (fl4b[2]-fl4b[0]))//2, fy), FOOTER_LINES[3],
font=fnt_footer_xs, fill=(180, 220, 255))
# Save
fn = f"post_{post['num']:02d}_{post['title_en'].replace(' ','_').replace('(','').replace(')','')}.png"
out_path = os.path.join(OUTPUT_DIR, fn)
img.save(out_path, "PNG", dpi=(150,150))
print(f" Saved: {fn}")
return out_path
print("\n=== Generating 10 Health Awareness Posts ===\n")
saved = []
for p in POSTS:
print(f"Post {p['num']}: {p['title_ur']}")
path = make_post(p)
saved.append(path)
print(f"\n✅ All {len(saved)} posts generated in: {OUTPUT_DIR}")
cd /home/daytona/workspace/shifa-health-posts && python3 generate_posts.py 2>&1
fc-list | grep -i "noto\|arabic\|urdu\|nastaliq\|naskh" | head -20; echo "---"; find /usr/share/fonts -name "*.ttf" | grep -i "noto" | head -20
fc-list | head -30; find /usr/share/fonts -name "*.ttf" | head -20; ls /usr/share/fonts/ 2>/dev/null | head -20
pip install --user arabic-reshaper python-bidi 2>&1 | tail -5; python3 -c "import arabic_reshaper; print('arabic_reshaper OK')" 2>&1
# Download a proper Arabic/Urdu font - Amiri (beautiful Naskh style) mkdir -p /home/daytona/workspace/shifa-health-posts/fonts wget -q "https://github.com/aliftype/amiri/releases/download/1.000/Amiri-1.000.zip" -O /tmp/amiri.zip && \ unzip -q /tmp/amiri.zip -d /tmp/amiri_extracted/ && \ find /tmp/amiri_extracted -name "*.ttf" | head -5 echo "exit: $?"
cp /tmp/amiri_extracted/Amiri-1.000/Amiri-Regular.ttf /home/daytona/workspace/shifa-health-posts/fonts/ cp /tmp/amiri_extracted/Amiri-1.000/Amiri-Bold.ttf /home/daytona/workspace/shifa-health-posts/fonts/ ls /home/daytona/workspace/shifa-health-posts/fonts/
~/shifa-health-posts/generate_posts_v2.py
#!/usr/bin/env python3
"""
Generate 10 Premium Urdu Health Awareness Posts (1080x1080px)
Shifa Online Consultation - Medical Infographic Series v2
Uses: Amiri font + arabic_reshaper + bidi for proper Urdu rendering
"""
from PIL import Image, ImageDraw, ImageFont
import arabic_reshaper
from bidi.algorithm import get_display
import os, sys, textwrap
OUTPUT_DIR = "/home/daytona/workspace/shifa-health-posts/output"
FONT_DIR = "/home/daytona/workspace/shifa-health-posts/fonts"
FONT_REG = os.path.join(FONT_DIR, "Amiri-Regular.ttf")
FONT_BOLD = os.path.join(FONT_DIR, "Amiri-Bold.ttf")
os.makedirs(OUTPUT_DIR, exist_ok=True)
W, H = 1080, 1080
# ── Palette ────────────────────────────────────────────────────
C_BG = (243, 249, 255)
C_HDR_TOP = (4, 78, 148)
C_HDR_BOT = (0, 145, 165)
C_ACCENT = (0, 175, 125)
C_ACCENT2 = (0, 140, 200)
C_WHITE = (255, 255, 255)
C_CARD = (255, 255, 255)
C_CARD_BD = (210, 232, 245)
C_SEC_HD = (4, 78, 148)
C_BODY = (35, 55, 75)
C_FOOTER_TOP = (4, 78, 148)
C_FOOTER_BOT = (0, 35, 80)
C_DISC_BG = (224, 246, 238)
C_DISC_TXT = (30, 90, 65)
C_LIGHT_BLUE = (220, 240, 255)
C_GOLD = (220, 160, 10)
# ── Font loader ────────────────────────────────────────────────
_font_cache = {}
def fnt(size, bold=False):
key = (size, bold)
if key not in _font_cache:
path = FONT_BOLD if bold else FONT_REG
_font_cache[key] = ImageFont.truetype(path, size)
return _font_cache[key]
# ── RTL text shaper ────────────────────────────────────────────
def ur(text):
"""Shape Urdu/Arabic text for correct RTL rendering."""
reshaped = arabic_reshaper.reshape(text)
return get_display(reshaped)
# ── Gradient helper ────────────────────────────────────────────
def vgrad(img, x1, y1, x2, y2, c_top, c_bot):
draw = ImageDraw.Draw(img)
h = y2 - y1
for i in range(h):
t = i / max(h - 1, 1)
r = int(c_top[0] + (c_bot[0] - c_top[0]) * t)
g = int(c_top[1] + (c_bot[1] - c_top[1]) * t)
b = int(c_top[2] + (c_bot[2] - c_top[2]) * t)
draw.line([(x1, y1+i), (x2, y1+i)], fill=(r, g, b))
def hgrad(img, x1, y1, x2, y2, c_left, c_right):
draw = ImageDraw.Draw(img)
w = x2 - x1
for i in range(w):
t = i / max(w - 1, 1)
r = int(c_left[0] + (c_right[0] - c_left[0]) * t)
g = int(c_left[1] + (c_right[1] - c_left[1]) * t)
b = int(c_left[2] + (c_right[2] - c_left[2]) * t)
draw.line([(x1+i, y1), (x1+i, y2)], fill=(r, g, b))
# ── Drawing helpers ────────────────────────────────────────────
def rr(draw, x1, y1, x2, y2, radius, fill=None, outline=None, ow=1):
draw.rounded_rectangle([x1, y1, x2, y2], radius=radius,
fill=fill, outline=outline, width=ow)
def circ(draw, cx, cy, r, fill=None, outline=None, ow=2):
draw.ellipse([cx-r, cy-r, cx+r, cy+r], fill=fill, outline=outline, width=ow)
def cross(draw, cx, cy, size, color):
t = max(size // 4, 4)
draw.rounded_rectangle([cx-t, cy-size//2, cx+t, cy+size//2], radius=3, fill=color)
draw.rounded_rectangle([cx-size//2, cy-t, cx+size//2, cy+t], radius=3, fill=color)
def text_wh(draw, text, font):
b = draw.textbbox((0,0), text, font=font)
return b[2]-b[0], b[3]-b[1]
def draw_centered(draw, text, font, cy, color, cx=W//2):
tw, th = text_wh(draw, text, font)
draw.text((cx - tw//2, cy - th//2), text, font=font, fill=color)
return cy + th//2
def draw_rtl_wrapped(draw, raw_text, font, x_right, x_left, y_start, color,
line_sp=6, max_lines=None):
"""
Draw RTL-shaped text, right-aligned, word-wrapped within [x_left, x_right].
Returns the y position after the last line.
"""
shaped = ur(raw_text)
max_w = x_right - x_left
# Split into words and wrap
words = shaped.split()
lines = []
current = []
for word in words:
test = " ".join(current + [word])
tw, _ = text_wh(draw, test, font)
if tw <= max_w:
current.append(word)
else:
if current:
lines.append(" ".join(current))
current = [word]
if current:
lines.append(" ".join(current))
if max_lines:
lines = lines[:max_lines]
y = y_start
for line in lines:
tw, th = text_wh(draw, line, font)
draw.text((x_right - tw, y), line, font=font, fill=color)
y += th + line_sp
return y
def draw_rtl_single(draw, raw_text, font, x_right, y, color):
"""Draw a single RTL line right-aligned at x_right."""
shaped = ur(raw_text)
tw, th = text_wh(draw, shaped, font)
draw.text((x_right - tw, y), shaped, font=font, fill=color)
return y + th
def draw_rtl_centered(draw, raw_text, font, y, color, cx=W//2):
shaped = ur(raw_text)
tw, th = text_wh(draw, shaped, font)
draw.text((cx - tw//2, y), shaped, font=font, fill=color)
return y + th
# ── Post Content ───────────────────────────────────────────────
POSTS = [
dict(num=1, emoji="🫀",
title_ur="مثانے کا انفیکشن", title_en="Bladder Infection",
accent=(0, 130, 195),
intro="مثانے کا انفیکشن بیکٹیریا کی وجہ سے ہوتا ہے۔ بروقت علاج سے مکمل صحتیابی ممکن ہے۔",
symptoms="پیشاب میں جلن، بار بار پیشاب آنا، پیٹ کے نچلے حصے میں درد، بدبودار یا دھندلا پیشاب",
causes="بیکٹیریا (E. coli)، صفائی کا خیال نہ رکھنا، پانی کم پینا، ذیابیطس",
prevention="کافی پانی پئیں، صفائی رکھیں، پیشاب روکنے سے گریز کریں، قوت مدافعت بڑھائیں",
doctor="بخار، کمر درد یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے ملیں"),
dict(num=2, emoji="🪨",
title_ur="گردوں کی پتھری", title_en="Kidney Stones",
accent=(0, 115, 175),
intro="گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
symptoms="کمر یا پہلو میں شدید درد، پیشاب میں خون، متلی، الٹی، پیشاب میں رکاوٹ",
causes="کم پانی پینا، زیادہ کیلشیم / آکسیلیٹ والی غذا، موروثی عوامل، بیٹھا رہنا",
prevention="روزانہ 8-10 گلاس پانی، نمک کم کریں، متوازن غذا، باقاعدہ ورزش کریں",
doctor="کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=3, emoji="👶",
title_ur="بانجھ پن / اولاد نہ ہونا", title_en="Infertility",
accent=(0, 155, 130),
intro="بانجھ پن لاعلاج نہیں۔ جدید علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
symptoms="ایک سال کوشش کے باوجود حمل نہ ہونا، ماہواری کی بے ترتیبی، ہارمون کی خرابی",
causes="PCOS، ہارمون عدم توازن، فیلوپین ٹیوب میں رکاوٹ، مردوں میں سپرم کی کمی، تناؤ",
prevention="صحت مند وزن رکھیں، تناؤ کم کریں، سگریٹ سے پرہیز، بروقت طبی معائنہ کروائیں",
doctor="اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں - جلد تشخیص بہتر ہے"),
dict(num=4, emoji="❤️",
title_ur="ہائی بلڈ پریشر", title_en="High Blood Pressure",
accent=(190, 45, 55),
intro="ہائی بلڈ پریشر کو 'خاموش قاتل' کہتے ہیں۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کریں۔",
symptoms="سر درد، چکر، دھندلی نظر، سینے میں درد، سانس لینے میں دشواری، ناک سے خون",
causes="نمک زیادہ، موٹاپا، ورزش نہ کرنا، تناؤ، موروثی بیماری، سگریٹ نوشی",
prevention="نمک کم کریں، ورزش کریں، وزن قابو رکھیں، تناؤ سے بچیں، BP باقاعدہ چیک کروائیں",
doctor="BP 140/90 سے زیادہ ہو، سر درد شدید ہو یا سینے میں درد آئے تو فوری ڈاکٹر سے ملیں"),
dict(num=5, emoji="🩸",
title_ur="ذیابیطس / شوگر", title_en="Diabetes",
accent=(0, 145, 100),
intro="ذیابیطس میں خون میں شکر بڑھ جاتی ہے۔ طرز زندگی بدل کر اسے قابو میں رکھیں۔",
symptoms="بار بار پیشاب، زیادہ پیاس، وزن میں کمی، تھکاوٹ، زخم دیر سے بھرنا، نظر کمزور ہونا",
causes="موٹاپا، ورزش نہ کرنا، غیر صحت بخش غذا، موروثی، ہارمون کی خرابی",
prevention="میٹھا کم کھائیں، ورزش کریں، وزن قابو رکھیں، باقاعدہ بلڈ شوگر ٹیسٹ کروائیں",
doctor="بلڈ شوگر بار بار زیادہ آئے، چکر یا بے ہوشی ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=6, emoji="🤧",
title_ur="کان، ناک اور گلے کی الرجی", title_en="ENT Allergies",
accent=(0, 125, 185),
intro="ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
symptoms="چھینکیں، ناک بند یا بہنا، آنکھوں میں خارش، گلے میں خراش، کان میں بھاری پن",
causes="دھول، جرگ، پالتو جانور، کیمیکل، موسمی تبدیلی، کمزور قوت مدافعت",
prevention="دھول سے بچیں، ماسک پہنیں، گھر صاف رکھیں، الرجی ٹیسٹ کروائیں",
doctor="سانس لینے میں دشواری یا علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں"),
dict(num=7, emoji="🦴",
title_ur="جوڑوں اور کمر کا درد", title_en="Joint & Back Pain",
accent=(110, 75, 165),
intro="جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
symptoms="جوڑوں میں سوجن و اکڑن، کمر میں درد، حرکت میں دشواری، صبح کے وقت اکڑن",
causes="آرتھرائٹس، یورک ایسڈ، موٹاپا، غلط بیٹھنے کا انداز، کیلشیم کی کمی، چوٹ",
prevention="ورزش، وزن کم کریں، کیلشیم / وٹامن D لیں، صحیح بیٹھیں، بھاری وزن نہ اٹھائیں",
doctor="درد شدید ہو، سوجن آئے یا چلنا مشکل ہو تو آرتھوپیڈک ڈاکٹر سے فوری ملیں"),
dict(num=8, emoji="💧",
title_ur="پیشاب میں جلن اور انفیکشن", title_en="Urinary Tract Infection",
accent=(0, 145, 165),
intro="UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو انفیکشن گردوں تک پہنچ سکتا ہے۔",
symptoms="پیشاب میں جلن، بار بار آنا، رنگ غیر معمولی، بدبو، پیٹ کے نچلے حصے میں درد",
causes="بیکٹیریا، صفائی نہ رکھنا، پانی کم پینا، ذیابیطس، قوت مدافعت کی کمزوری",
prevention="پانی خوب پئیں، صفائی رکھیں، نرم کپڑے پہنیں، پیشاب روکنے سے گریز کریں",
doctor="بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں"),
dict(num=9, emoji="🫁",
title_ur="معدے کی تیزابیت اور گیس", title_en="Acidity & Gastric Problems",
accent=(185, 110, 15),
intro="معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
symptoms="سینے میں جلن، ڈکار، پیٹ پھولنا، متلی، منہ میں کھٹاس، کھانے کے بعد تکلیف",
causes="مسالہ دار کھانا، زیادہ چائے / کافی، کھانے میں بے ترتیبی، تناؤ، سگریٹ نوشی",
prevention="کم مسالہ کھائیں، بروقت کھانا کھائیں، پانی پئیں، تناؤ کم کریں، تھوڑا تھوڑا کھائیں",
doctor="سینے میں شدید جلن، قے میں خون یا وزن کم ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=10, emoji="🌡️",
title_ur="موسمی بخار، نزلہ اور کھانسی", title_en="Seasonal Flu & Cough",
accent=(0, 135, 165),
intro="موسمی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
symptoms="بخار، ناک بہنا یا بند ہونا، گلے میں خراش، کھانسی، جسم درد، کمزوری",
causes="وائرس / بیکٹیریا، موسمی تبدیلی، کمزور قوت مدافعت، بھیڑ والی جگہوں پر رہنا",
prevention="ہاتھ دھوئیں، ماسک پہنیں، گرم پانی پئیں، قوت مدافعت بڑھائیں، فلو ویکسین لگوائیں",
doctor="بخار 3 دن سے زیادہ رہے یا سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں"),
]
SECTIONS = [
("intro", "تعارف", "📋"),
("symptoms", "علامات", "🩺"),
("causes", "وجوہات", "🔬"),
("prevention", "احتیاط و بچاؤ", "🛡"),
("doctor", "ڈاکٹر سے کب ملیں","👨⚕️"),
]
FOOTER_BRAND = "شفا آن لائن کنسلٹیشن"
FOOTER_L1 = "✔ ماہر ڈاکٹروں سے آن لائن مشاورت ✔ گھر بیٹھے رہنمائی حاصل کریں"
FOOTER_L2 = "📱 WhatsApp: +92XXXXXXXXXX ⏰ Appointment Required"
FOOTER_L3 = "💳 Paid Medical Consultation Service"
DISCLAIMER = "یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔"
def make_post(post):
img = Image.new("RGB", (W, H), C_BG)
acc = post["accent"]
acc2 = (max(acc[0]-30,0), min(acc[1]+20,255), min(acc[2]+30,255))
# ── Background subtle grid pattern ─────────────────────────
draw = ImageDraw.Draw(img)
for gx in range(0, W, 60):
draw.line([(gx, 0), (gx, H)], fill=(220, 235, 248), width=1)
for gy in range(0, H, 60):
draw.line([(0, gy), (W, gy)], fill=(220, 235, 248), width=1)
# ── Header (gradient) ───────────────────────────────────────
HDR_H = 200
vgrad(img, 0, 0, W, HDR_H, C_HDR_TOP, C_HDR_BOT)
draw = ImageDraw.Draw(img)
# Decorative circles in header
circ(draw, 950, -20, 130, fill=(*C_ACCENT, 0), outline=(255,255,255,25), ow=2)
circ(draw, 880, 230, 80, fill=None, outline=(255,255,255,15), ow=1)
circ(draw, 130, 220, 90, fill=None, outline=(255,255,255,12), ow=1)
# Post number circle (top-left)
circ(draw, 55, 48, 30, fill=C_ACCENT)
cross(draw, 55, 48, 22, C_WHITE)
num_f = fnt(20, bold=True)
ns = str(post["num"])
nw, nh = text_wh(draw, ns, num_f)
draw.text((55 - nw//2 - 14, 48 - nh//2 + 1), ns, font=num_f, fill=C_WHITE)
# Emoji (top right)
ef = fnt(72)
ew, eh = text_wh(draw, post["emoji"], ef)
draw.text((W - ew - 38, (HDR_H - eh)//2 - 10), post["emoji"], font=ef, fill=C_WHITE)
# Title Urdu (large, centered)
tf = fnt(58, bold=True)
title_shaped = ur(post["title_ur"])
tw, th = text_wh(draw, title_shaped, tf)
draw.text(((W - tw)//2, 22), title_shaped, font=tf, fill=C_WHITE)
# English subtitle
ef2 = fnt(24)
ew2, eh2 = text_wh(draw, post["title_en"], ef2)
draw.text(((W - ew2)//2, 22 + th + 8), post["title_en"], font=ef2, fill=(195, 230, 255))
# Accent bar below header
draw.rectangle([0, HDR_H, W, HDR_H+5], fill=C_ACCENT)
# ── Content Area ────────────────────────────────────────────
# Layout: 5 content cards, disclaimer, footer
# Footer ~= 165px, Disclaimer ~= 42px, top pad 8
# Available for cards: 1080 - 200 - 5 - 8 - 42 - 6 - 165 = 454px
# 5 cards + 4 gaps(6) = 454 → each card ~ 87px
CARD_X1 = 28
CARD_X2 = W - 28
CARD_GAP = 6
CONTENT_START = HDR_H + 5 + 8
# Dynamically size each card
FOOTER_H = 168
DISC_H = 40
DISC_GAP = 6
available = H - CONTENT_START - DISC_H - DISC_GAP - FOOTER_H - CARD_GAP*(len(SECTIONS)-1) - 6
card_h = available // len(SECTIONS)
sec_hd_f = fnt(26, bold=True)
body_f = fnt(21)
icon_f = fnt(20)
card_y = CONTENT_START
for key, label, icon in SECTIONS:
text_content = post[key]
# Card shadow (subtle)
rr(draw, CARD_X1+3, card_y+3, CARD_X2+3, card_y+card_h+3,
12, fill=(200, 220, 235))
# Card body
rr(draw, CARD_X1, card_y, CARD_X2, card_y+card_h,
12, fill=C_CARD, outline=C_CARD_BD, ow=1)
# Left accent bar
draw.rounded_rectangle([CARD_X1, card_y, CARD_X1+7, card_y+card_h],
radius=12, fill=acc)
# Top accent dot
circ(draw, CARD_X1+7, card_y + card_h//2, 5, fill=acc2)
# Icon on right
ix = CARD_X2 - 14
iy = card_y + 8
iw, ih = text_wh(draw, icon, icon_f)
draw.text((ix - iw, iy), icon, font=icon_f, fill=acc)
# Section heading (right-aligned, shaped)
lh_y = card_y + 8
lbl_shaped = ur(label)
lw, lh = text_wh(draw, lbl_shaped, sec_hd_f)
draw.text((CARD_X2 - 14 - iw - 8 - lw, lh_y), lbl_shaped,
font=sec_hd_f, fill=C_SEC_HD)
# Thin divider under heading
div_y = lh_y + lh + 4
draw.line([(CARD_X1+12, div_y), (CARD_X2-12, div_y)], fill=C_CARD_BD, width=1)
# Body text
body_y = div_y + 5
draw_rtl_wrapped(draw, text_content, body_f,
CARD_X2 - 12, CARD_X1 + 12,
body_y, C_BODY, line_sp=5, max_lines=3)
card_y += card_h + CARD_GAP
# ── Disclaimer ──────────────────────────────────────────────
disc_y = card_y + DISC_GAP
rr(draw, 28, disc_y, W-28, disc_y+DISC_H, 10,
fill=C_DISC_BG, outline=C_ACCENT, ow=1)
disc_f = fnt(18)
disc_shaped = ur(DISCLAIMER)
dw, dh = text_wh(draw, disc_shaped, disc_f)
draw.text(((W-dw)//2, disc_y + (DISC_H-dh)//2), disc_shaped,
font=disc_f, fill=C_DISC_TXT)
# ── Footer ──────────────────────────────────────────────────
footer_y = disc_y + DISC_H + 4
vgrad(img, 0, footer_y, W, H, C_FOOTER_TOP, C_FOOTER_BOT)
draw = ImageDraw.Draw(img)
draw.rectangle([0, footer_y, W, footer_y+4], fill=C_ACCENT)
# Decorative circles in footer
circ(draw, 80, footer_y + 80, 55, fill=None, outline=(255,255,255,15), ow=1)
circ(draw, W-70, footer_y+60, 45, fill=None, outline=(255,255,255,12), ow=1)
fb_f = fnt(34, bold=True)
fl_f = fnt(20)
fxs_f = fnt(17)
fy = footer_y + 12
# Brand
brand_shaped = ur(FOOTER_BRAND)
bw, bh = text_wh(draw, brand_shaped, fb_f)
draw.text(((W-bw)//2, fy), brand_shaped, font=fb_f, fill=C_WHITE)
# Gold underline
draw.line([((W-bw)//2, fy+bh+2), ((W+bw)//2, fy+bh+2)], fill=C_GOLD, width=2)
fy += bh + 10
l1_shaped = ur(FOOTER_L1)
l1w, l1h = text_wh(draw, l1_shaped, fl_f)
draw.text(((W-l1w)//2, fy), l1_shaped, font=fl_f, fill=(195, 230, 255))
fy += l1h + 6
l2_shaped = ur(FOOTER_L2)
l2w, l2h = text_wh(draw, l2_shaped, fl_f)
draw.text(((W-l2w)//2, fy), l2_shaped, font=fl_f, fill=(195, 230, 255))
fy += l2h + 5
l3_shaped = ur(FOOTER_L3)
l3w, l3h = text_wh(draw, l3_shaped, fxs_f)
draw.text(((W-l3w)//2, fy), l3_shaped, font=fxs_f, fill=(175, 215, 255))
# ── Save ────────────────────────────────────────────────────
safe_en = post["title_en"].replace(" ", "_").replace("/","").replace("&","and")
fn = f"post_{post['num']:02d}_{safe_en}.png"
out = os.path.join(OUTPUT_DIR, fn)
img.save(out, "PNG", dpi=(150, 150))
print(f" ✓ Post {post['num']:02d}: {post['title_ur']} → {fn}")
return out
print("=" * 60)
print(" SHIFA ONLINE - 10 Health Awareness Posts Generator v2")
print("=" * 60)
saved = []
for p in POSTS:
path = make_post(p)
saved.append(path)
print()
print(f"✅ All {len(saved)} posts saved to: {OUTPUT_DIR}")
cd /home/daytona/workspace/shifa-health-posts && python3 generate_posts_v2.py 2>&1
cd /home/daytona/workspace/shifa-health-posts/output && ls -lh *.png && echo "---" && cd /home/daytona/workspace/shifa-health-posts && zip -j shifa_health_posts_10x.zip output/*.png && ls -lh shifa_health_posts_10x.zip
# Copy the v2 posts to a clean folder then zip mkdir -p /home/daytona/workspace/shifa-health-posts/final cp /home/daytona/workspace/shifa-health-posts/output/post_01_Bladder_Infection.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_02_Kidney_Stones.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_03_Infertility.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_04_High_Blood_Pressure.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_05_Diabetes.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_06_ENT_Allergies.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_07_Joint_and_Back_Pain.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_08_Urinary_Tract_Infection.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_09_Acidity_and_Gastric_Problems.png /home/daytona/workspace/shifa-health-posts/final/ cp /home/daytona/workspace/shifa-health-posts/output/post_10_Seasonal_Flu_and_Cough.png /home/daytona/workspace/shifa-health-posts/final/ ls -lh /home/daytona/workspace/shifa-health-posts/final/
python3 -c " import zipfile, os files = [f'/home/daytona/workspace/shifa-health-posts/final/post_{str(i).zfill(2)}_{n}.png' for i,n in [(1,'Bladder_Infection'),(2,'Kidney_Stones'),(3,'Infertility'), (4,'High_Blood_Pressure'),(5,'Diabetes'),(6,'ENT_Allergies'), (7,'Joint_and_Back_Pain'),(8,'Urinary_Tract_Infection'), (9,'Acidity_and_Gastric_Problems'),(10,'Seasonal_Flu_and_Cough')]] zip_path = '/home/daytona/workspace/shifa-health-posts/Shifa_Health_Posts_10x_1080p.zip' with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zf: for f in files: zf.write(f, os.path.basename(f)) print(f' added: {os.path.basename(f)}') import os print(f'ZIP size: {os.path.getsize(zip_path)//1024} KB') print(f'Path: {zip_path}') "
python3 -c " from PIL import Image import os final_dir = '/home/daytona/workspace/shifa-health-posts/final/' for f in sorted(os.listdir(final_dir)): img = Image.open(final_dir + f) print(f'{f}: {img.size} mode={img.mode} size={os.path.getsize(final_dir+f)//1024}KB') "
| # | Topic | Download Link |
|---|---|---|
| 1 | مثانے کا انفیکشن | post 01 Bladder Infection Image · PNG |
| 2 | گردوں کی پتھری | post 02 Kidney Stones Image · PNG |
| 3 | بانجھ پن / اولاد نہ ہونا | post 03 Infertility Image · PNG |
| 4 | ہائی بلڈ پریشر | post 04 High Blood Pressure Image · PNG |
| 5 | ذیابیطس / شوگر | post 05 Diabetes Image · PNG |
| 6 | کان، ناک اور گلے کی الرجی | post 06 ENT Allergies Image · PNG |
| 7 | جوڑوں اور کمر کا درد | post 07 Joint and Back Pain Image · PNG |
| 8 | پیشاب میں جلن اور انفیکشن | post 08 Urinary Tract Infection Image · PNG |
| 9 | معدے کی تیزابیت اور گیس | post 09 Acidity and Gastric Problems Image · PNG |
| 10 | موسمی بخار، نزلہ اور کھانسی | post 10 Seasonal Flu and Cough Image · PNG |
arabic_reshaper + bidi for correct Urdu ligaturesall files are damaged fix the issue
python3 -c " from PIL import Image import os final_dir = '/home/daytona/workspace/shifa-health-posts/final/' for f in sorted(os.listdir(final_dir)): try: img = Image.open(final_dir + f) img.verify() print(f'OK: {f}') except Exception as e: print(f'DAMAGED: {f} -> {e}') "
python3 -c " from PIL import Image import os, shutil src = '/home/daytona/workspace/shifa-health-posts/final/' dst = '/home/daytona/workspace/shifa-health-posts/fixed/' os.makedirs(dst, exist_ok=True) for f in sorted(os.listdir(src)): if not f.endswith('.png'): continue img = Image.open(src + f) img = img.convert('RGB') out = dst + f img.save(out, format='PNG', optimize=False, compress_level=1) size = os.path.getsize(out) print(f'Saved: {f} ({size//1024} KB)') print('Done.') "
which wkhtmltoimage wkhtmltopdf chromium-browser chromium google-chrome 2>/dev/null; python3 -c "from playwright.sync_api import sync_playwright; print('playwright ok')" 2>/dev/null; which cutycapt 2>/dev/null; echo "---done"
chromium --headless --disable-gpu --screenshot=/tmp/test.png --window-size=100,100 about:blank 2>&1 | head -5; ls -la /tmp/test.png 2>/dev/null && echo "chromium screenshot works" || echo "chromium screenshot failed"
~/shifa-health-posts/build_html_posts.py
#!/usr/bin/env python3
"""
Build 10 premium Urdu health posts as HTML files,
then render each with Chromium headless to 1080x1080 PNG.
Uses Google Fonts (Noto Nastaliq Urdu) embedded via base64 or CDN.
"""
import os, subprocess, time
HTML_DIR = "/home/daytona/workspace/shifa-health-posts/html"
OUT_DIR = "/home/daytona/workspace/shifa-health-posts/fixed"
os.makedirs(HTML_DIR, exist_ok=True)
os.makedirs(OUT_DIR, exist_ok=True)
FONT_PATH_REG = "/home/daytona/workspace/shifa-health-posts/fonts/Amiri-Regular.ttf"
FONT_PATH_BOLD = "/home/daytona/workspace/shifa-health-posts/fonts/Amiri-Bold.ttf"
POSTS = [
dict(num=1, icon="🫀",
title="مثانے کا انفیکشن", subtitle="Bladder Infection",
color="#0456A0", accent="#00AF7D",
intro="مثانے کا انفیکشن بیکٹیریا کی وجہ سے ہوتا ہے۔ بروقت علاج سے مکمل صحتیابی ممکن ہے۔",
symptoms="پیشاب میں جلن • بار بار پیشاب آنا • پیٹ کے نچلے حصے میں درد • بدبودار یا دھندلا پیشاب",
causes="بیکٹیریا (E. coli) • صفائی کا خیال نہ رکھنا • پانی کم پینا • ذیابیطس",
prevention="کافی پانی پئیں • صفائی رکھیں • پیشاب روکنے سے گریز • قوت مدافعت بڑھائیں",
doctor="بخار، کمر درد یا علامات 2 دن سے زیادہ رہیں تو فوری ڈاکٹر سے ملیں"),
dict(num=2, icon="🪨",
title="گردوں کی پتھری", subtitle="Kidney Stones",
color="#006FA8", accent="#0096C8",
intro="گردوں میں معدنی نمکیات جمع ہو کر پتھری بناتے ہیں۔ یہ تکلیف دہ لیکن قابل علاج مسئلہ ہے۔",
symptoms="کمر یا پہلو میں شدید درد • پیشاب میں خون • متلی اور الٹی • پیشاب میں رکاوٹ",
causes="کم پانی پینا • زیادہ کیلشیم والی غذا • موروثی عوامل • بیٹھا رہنا",
prevention="روزانہ 8-10 گلاس پانی • نمک کم • متوازن غذا • باقاعدہ ورزش",
doctor="کمر میں شدید درد، پیشاب میں خون یا پیشاب بند ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=3, icon="👶",
title="بانجھ پن / اولاد نہ ہونا", subtitle="Infertility",
color="#007B6E", accent="#00B890",
intro="بانجھ پن لاعلاج نہیں۔ جدید علاج سے بہت سے جوڑے اولاد کی نعمت پا سکتے ہیں۔",
symptoms="ایک سال کوشش کے باوجود حمل نہ ہونا • ماہواری کی بے ترتیبی • ہارمون کی خرابی",
causes="PCOS • ہارمون عدم توازن • فیلوپین ٹیوب میں رکاوٹ • مردوں میں سپرم کی کمی",
prevention="صحت مند وزن • تناؤ کم • سگریٹ سے پرہیز • بروقت طبی معائنہ",
doctor="اگر ایک سال سے حمل نہ ہو تو ماہر ڈاکٹر سے رجوع کریں — جلد تشخیص بہتر"),
dict(num=4, icon="❤️",
title="ہائی بلڈ پریشر", subtitle="High Blood Pressure",
color="#A0192A", accent="#D43040",
intro="ہائی بلڈ پریشر کو 'خاموش قاتل' کہتے ہیں۔ باقاعدہ چیک اپ اور علاج سے اسے قابو کریں۔",
symptoms="سر درد • چکر آنا • دھندلی نظر • سینے میں درد • سانس لینے میں دشواری",
causes="نمک زیادہ • موٹاپا • ورزش نہ کرنا • تناؤ • موروثی بیماری • سگریٹ نوشی",
prevention="نمک کم • ورزش • وزن قابو • تناؤ سے بچیں • BP باقاعدہ چیک کروائیں",
doctor="BP 140/90 سے زیادہ ہو یا سینے میں درد آئے تو فوری ڈاکٹر سے ملیں"),
dict(num=5, icon="🩸",
title="ذیابیطس / شوگر", subtitle="Diabetes",
color="#006845", accent="#00A06A",
intro="ذیابیطس میں خون میں شکر کی سطح بڑھ جاتی ہے۔ طرز زندگی بدل کر اسے قابو میں رکھیں۔",
symptoms="بار بار پیشاب • زیادہ پیاس • وزن میں کمی • تھکاوٹ • زخم دیر سے بھرنا",
causes="موٹاپا • ورزش نہ کرنا • غیر صحت بخش غذا • موروثی • ہارمون کی خرابی",
prevention="میٹھا کم • ورزش • وزن قابو • باقاعدہ بلڈ شوگر ٹیسٹ",
doctor="بلڈ شوگر بار بار زیادہ آئے یا چکر و بے ہوشی ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=6, icon="🤧",
title="کان، ناک اور گلے کی الرجی", subtitle="ENT Allergies",
color="#005A8C", accent="#0082BE",
intro="ENT الرجی بہت عام مسئلہ ہے۔ دھول، دھواں اور موسمی تبدیلیاں اس کی بڑی وجوہات ہیں۔",
symptoms="چھینکیں • ناک بند یا بہنا • آنکھوں میں خارش • گلے میں خراش • کان میں بھاری پن",
causes="دھول • جرگ • پالتو جانور • کیمیکل • موسمی تبدیلی • کمزور قوت مدافعت",
prevention="دھول سے بچیں • ماسک پہنیں • گھر صاف رکھیں • الرجی ٹیسٹ کروائیں",
doctor="سانس لینے میں دشواری یا علامات 2 ہفتے سے زیادہ رہیں تو ENT ماہر سے ملیں"),
dict(num=7, icon="🦴",
title="جوڑوں اور کمر کا درد", subtitle="Joint & Back Pain",
color="#5A3E9A", accent="#7A5EC0",
intro="جوڑوں اور کمر کا درد روزمرہ زندگی متاثر کرتا ہے۔ بروقت علاج اور ورزش سے بہتری ممکن ہے۔",
symptoms="جوڑوں میں سوجن و اکڑن • کمر میں درد • حرکت میں دشواری • صبح کے وقت اکڑن",
causes="آرتھرائٹس • یورک ایسڈ • موٹاپا • غلط بیٹھنے کا انداز • کیلشیم کی کمی",
prevention="ورزش • وزن کم • کیلشیم / وٹامن D • صحیح بیٹھیں • بھاری وزن نہ اٹھائیں",
doctor="درد شدید ہو، سوجن آئے یا چلنا مشکل ہو تو آرتھوپیڈک ڈاکٹر سے فوری ملیں"),
dict(num=8, icon="💧",
title="پیشاب میں جلن اور انفیکشن", subtitle="Urinary Tract Infection",
color="#006878", accent="#0096A8",
intro="UTI خواتین میں بہت عام ہے۔ بروقت علاج نہ ہو تو انفیکشن گردوں تک پہنچ سکتا ہے۔",
symptoms="پیشاب میں جلن • بار بار آنا • رنگ غیر معمولی • بدبو • پیٹ کے نچلے حصے میں درد",
causes="بیکٹیریا • صفائی نہ رکھنا • پانی کم پینا • ذیابیطس • قوت مدافعت کی کمزوری",
prevention="پانی خوب پئیں • صفائی رکھیں • نرم کپڑے • پیشاب روکنے سے گریز",
doctor="بخار، ٹھنڈ یا کمر درد کے ساتھ جلن ہو تو فوری ڈاکٹر سے رجوع کریں"),
dict(num=9, icon="🫁",
title="معدے کی تیزابیت اور گیس", subtitle="Acidity & Gastric Problems",
color="#8A5500", accent="#C07800",
intro="معدے کی تیزابیت آج کل بہت عام ہے۔ غلط کھانا اور بے ترتیب زندگی اس کی بڑی وجہ ہے۔",
symptoms="سینے میں جلن • ڈکار • پیٹ پھولنا • متلی • منہ میں کھٹاس • کھانے کے بعد تکلیف",
causes="مسالہ دار کھانا • زیادہ چائے / کافی • کھانے میں بے ترتیبی • تناؤ • سگریٹ",
prevention="کم مسالہ • بروقت کھانا • پانی • تناؤ کم • تھوڑا تھوڑا کھائیں",
doctor="سینے میں شدید جلن، قے میں خون یا وزن کم ہو تو فوری ڈاکٹر سے ملیں"),
dict(num=10, icon="🌡️",
title="موسمی بخار، نزلہ اور کھانسی", subtitle="Seasonal Flu & Cough",
color="#005A78", accent="#0086A8",
intro="موسمی تبدیلی میں نزلہ، بخار اور کھانسی بہت عام ہیں۔ احتیاط اور صفائی سے بچاؤ ممکن ہے۔",
symptoms="بخار • ناک بہنا یا بند ہونا • گلے میں خراش • کھانسی • جسم درد • کمزوری",
causes="وائرس / بیکٹیریا • موسمی تبدیلی • کمزور قوت مدافعت • بھیڑ والی جگہیں",
prevention="ہاتھ دھوئیں • ماسک پہنیں • گرم پانی • قوت مدافعت بڑھائیں • فلو ویکسین",
doctor="بخار 3 دن سے زیادہ رہے یا سانس لینے میں دشواری ہو تو فوری ڈاکٹر سے ملیں"),
]
HTML_TEMPLATE = """<!DOCTYPE html>
<html lang="ur" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1080">
<style>
@font-face {{
font-family: 'Amiri';
src: url('file://{font_reg}') format('truetype');
font-weight: normal;
}}
@font-face {{
font-family: 'Amiri';
src: url('file://{font_bold}') format('truetype');
font-weight: bold;
}}
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{
width: 1080px;
height: 1080px;
overflow: hidden;
font-family: 'Amiri', serif;
direction: rtl;
background: #F3F9FF;
}}
/* Background grid */
.bg {{
position: absolute;
width: 1080px;
height: 1080px;
background-image:
linear-gradient(to right, #DCF0FF 1px, transparent 1px),
linear-gradient(to bottom, #DCF0FF 1px, transparent 1px);
background-size: 60px 60px;
}}
.container {{
position: relative;
width: 1080px;
height: 1080px;
display: flex;
flex-direction: column;
}}
/* ── HEADER ── */
.header {{
background: linear-gradient(135deg, {color} 0%, #0096A5 100%);
padding: 18px 40px 14px 40px;
position: relative;
overflow: hidden;
min-height: 188px;
flex-shrink: 0;
}}
.header::before {{
content: '';
position: absolute;
top: -50px; left: -50px;
width: 220px; height: 220px;
border-radius: 50%;
background: rgba(255,255,255,0.07);
}}
.header::after {{
content: '';
position: absolute;
top: -30px; right: 60px;
width: 180px; height: 180px;
border-radius: 50%;
border: 2px solid rgba(255,255,255,0.15);
}}
.header-accent-bar {{
position: absolute;
bottom: 0; left: 0; right: 0;
height: 5px;
background: {accent};
}}
.post-badge {{
position: absolute;
top: 16px;
left: 36px;
width: 52px; height: 52px;
border-radius: 50%;
background: {accent};
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
font-weight: bold;
color: #fff;
font-family: Arial, sans-serif;
box-shadow: 0 3px 10px rgba(0,0,0,0.3);
z-index: 10;
}}
.header-icon {{
position: absolute;
top: 18px;
right: 36px;
font-size: 72px;
line-height: 1;
filter: drop-shadow(2px 3px 6px rgba(0,0,0,0.25));
z-index: 10;
}}
.header-titles {{
text-align: center;
padding: 8px 120px 0 120px;
}}
.title-ur {{
font-size: 54px;
font-weight: bold;
color: #FFFFFF;
line-height: 1.2;
text-shadow: 1px 2px 6px rgba(0,0,0,0.4);
letter-spacing: 0.5px;
}}
.title-en {{
font-size: 21px;
color: #C8E8FF;
font-family: 'Segoe UI', Arial, sans-serif;
margin-top: 4px;
letter-spacing: 1px;
}}
/* ── CONTENT ── */
.content {{
flex: 1;
padding: 7px 24px 4px 24px;
display: flex;
flex-direction: column;
gap: 5px;
min-height: 0;
}}
.card {{
background: #FFFFFF;
border-radius: 12px;
border: 1px solid #D2E8F5;
box-shadow: 2px 3px 8px rgba(0,86,160,0.08);
padding: 8px 16px 8px 16px;
position: relative;
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}}
.card::before {{
content: '';
position: absolute;
top: 0; right: 0;
width: 6px;
height: 100%;
background: {color};
border-radius: 0 12px 12px 0;
}}
.card-header {{
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
margin-bottom: 4px;
}}
.card-icon {{
font-size: 20px;
line-height: 1;
}}
.card-label {{
font-size: 23px;
font-weight: bold;
color: {color};
line-height: 1;
}}
.card-divider {{
height: 1px;
background: #D2E8F5;
margin: 3px 0 5px 0;
}}
.card-body {{
font-size: 19px;
color: #233547;
line-height: 1.55;
text-align: right;
padding-left: 14px;
}}
/* ── DISCLAIMER ── */
.disclaimer {{
margin: 0 24px 4px 24px;
background: #E0F6EE;
border: 1px solid #00AF7D;
border-radius: 10px;
padding: 7px 16px;
text-align: center;
font-size: 16px;
color: #1E5A40;
flex-shrink: 0;
}}
/* ── FOOTER ── */
.footer {{
background: linear-gradient(to bottom, {color} 0%, #001E4A 100%);
padding: 12px 30px 10px 30px;
text-align: center;
flex-shrink: 0;
position: relative;
overflow: hidden;
}}
.footer::before {{
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 4px;
background: {accent};
}}
.footer-brand {{
font-size: 30px;
font-weight: bold;
color: #FFFFFF;
line-height: 1.2;
}}
.footer-brand-underline {{
width: 220px;
height: 2px;
background: #DCAA00;
margin: 3px auto 7px auto;
border-radius: 2px;
}}
.footer-line {{
font-size: 18px;
color: #C3E2FF;
margin-bottom: 3px;
line-height: 1.4;
}}
.footer-line-sm {{
font-size: 15px;
color: #A0C8F0;
margin-top: 2px;
}}
</style>
</head>
<body>
<div class="bg"></div>
<div class="container">
<!-- HEADER -->
<div class="header">
<div class="post-badge">{num}</div>
<div class="header-icon">{icon}</div>
<div class="header-titles">
<div class="title-ur">{title}</div>
<div class="title-en">{subtitle}</div>
</div>
<div class="header-accent-bar"></div>
</div>
<!-- CONTENT CARDS -->
<div class="content">
<div class="card">
<div class="card-header">
<span class="card-label">تعارف</span>
<span class="card-icon">📋</span>
</div>
<div class="card-divider"></div>
<div class="card-body">{intro}</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-label">علامات</span>
<span class="card-icon">🩺</span>
</div>
<div class="card-divider"></div>
<div class="card-body">{symptoms}</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-label">وجوہات</span>
<span class="card-icon">🔬</span>
</div>
<div class="card-divider"></div>
<div class="card-body">{causes}</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-label">احتیاط و بچاؤ</span>
<span class="card-icon">🛡️</span>
</div>
<div class="card-divider"></div>
<div class="card-body">{prevention}</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-label">ڈاکٹر سے کب ملیں</span>
<span class="card-icon">👨⚕️</span>
</div>
<div class="card-divider"></div>
<div class="card-body">{doctor}</div>
</div>
</div><!-- /content -->
<!-- DISCLAIMER -->
<div class="disclaimer">
⚠️ یہ معلومات صرف آگاہی کے لیے ہیں۔ تشخیص اور علاج کے لیے مستند ڈاکٹر سے مشورہ کریں۔
</div>
<!-- FOOTER -->
<div class="footer">
<div class="footer-brand">شفا آن لائن کنسلٹیشن</div>
<div class="footer-brand-underline"></div>
<div class="footer-line">✔ ماہر ڈاکٹروں سے آن لائن مشاورت ✔ گھر بیٹھے رہنمائی حاصل کریں</div>
<div class="footer-line">📱 WhatsApp: +92XXXXXXXXXX ⏰ Appointment Required</div>
<div class="footer-line-sm">💳 Paid Medical Consultation Services Available</div>
</div>
</div>
</body>
</html>
"""
print("Generating HTML files...")
html_paths = []
for p in POSTS:
html_content = HTML_TEMPLATE.format(
font_reg = FONT_PATH_REG,
font_bold = FONT_PATH_BOLD,
num = p["num"],
icon = p["icon"],
title = p["title"],
subtitle = p["subtitle"],
color = p["color"],
accent = p["accent"],
intro = p["intro"],
symptoms = p["symptoms"],
causes = p["causes"],
prevention= p["prevention"],
doctor = p["doctor"],
)
html_path = os.path.join(HTML_DIR, f"post_{p['num']:02d}.html")
with open(html_path, "w", encoding="utf-8") as f:
f.write(html_content)
html_paths.append((p["num"], p["title"], html_path))
print(f" HTML {p['num']:02d}: {html_path}")
print("\nRendering PNGs with Chromium...")
for num, title, html_path in html_paths:
safe_title = {
1:"Bladder_Infection", 2:"Kidney_Stones", 3:"Infertility",
4:"High_Blood_Pressure", 5:"Diabetes", 6:"ENT_Allergies",
7:"Joint_and_Back_Pain", 8:"Urinary_Tract_Infection",
9:"Acidity_and_Gastric_Problems", 10:"Seasonal_Flu_and_Cough"
}[num]
out_png = os.path.join(OUT_DIR, f"post_{num:02d}_{safe_title}.png")
cmd = [
"chromium",
"--headless",
"--disable-gpu",
"--no-sandbox",
"--disable-dev-shm-usage",
f"--window-size=1080,1080",
f"--screenshot={out_png}",
f"file://{html_path}"
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if os.path.exists(out_png) and os.path.getsize(out_png) > 5000:
print(f" ✓ Post {num:02d}: {title} ({os.path.getsize(out_png)//1024} KB)")
else:
print(f" ✗ Post {num:02d} FAILED. stderr: {result.stderr[:200]}")
print("\nDone! Files in:", OUT_DIR)
cd /home/daytona/workspace/shifa-health-posts && python3 build_html_posts.py 2>&1
python3 -c " # Fix: reduce card padding/gaps and ensure footer shows completely # We'll patch the HTML template CSS values import os html_dir = '/home/daytona/workspace/shifa-health-posts/html/' for f in sorted(os.listdir(html_dir)): path = html_dir + f with open(path, 'r') as fh: content = fh.read() # Tighten up the content area to give footer more room # Change: content padding-top from 7px to 5px, gap from 5px to 4px content = content.replace('padding: 7px 24px 4px 24px;', 'padding: 5px 22px 3px 22px;') content = content.replace('gap: 5px;', 'gap: 4px;') # Reduce card padding content = content.replace('padding: 8px 16px 8px 16px;', 'padding: 6px 14px 6px 14px;') # Reduce card-body font from 19px to 18px content = content.replace('font-size: 19px;', 'font-size: 18px;') # Reduce card-label from 23px to 22px content = content.replace('font-size: 23px;', 'font-size: 22px;') # Reduce header min-height content = content.replace('min-height: 188px;', 'min-height: 178px;') content = content.replace('padding: 18px 40px 14px 40px;', 'padding: 14px 40px 10px 40px;') content = content.replace('font-size: 54px;', 'font-size: 50px;') with open(path, 'w') as fh: fh.write(content) print('Patched', len(os.listdir(html_dir)), 'HTML files') "
python3 -c " import os, subprocess html_dir = '/home/daytona/workspace/shifa-health-posts/html/' out_dir = '/home/daytona/workspace/shifa-health-posts/fixed/' name_map = { 1:'Bladder_Infection', 2:'Kidney_Stones', 3:'Infertility', 4:'High_Blood_Pressure', 5:'Diabetes', 6:'ENT_Allergies', 7:'Joint_and_Back_Pain', 8:'Urinary_Tract_Infection', 9:'Acidity_and_Gastric_Problems', 10:'Seasonal_Flu_and_Cough' } for num in range(1, 11): html_path = os.path.join(html_dir, f'post_{num:02d}.html') out_png = os.path.join(out_dir, f'post_{num:02d}_{name_map[num]}.png') cmd = [ 'chromium', '--headless', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage', '--window-size=1080,1080', f'--screenshot={out_png}', f'file://{html_path}' ] r = subprocess.run(cmd, capture_output=True, text=True, timeout=30) sz = os.path.getsize(out_png) if os.path.exists(out_png) else 0 print(f'Post {num:02d}: {sz//1024} KB') print('All done.') "
python3 -c " import os, subprocess from PIL import Image html_dir = '/home/daytona/workspace/shifa-health-posts/html/' out_dir = '/home/daytona/workspace/shifa-health-posts/fixed/' tmp_dir = '/tmp/shifa_tmp/' os.makedirs(tmp_dir, exist_ok=True) # Render at 1080x1200 (taller) then crop to 1080x1080 name_map = { 1:'Bladder_Infection', 2:'Kidney_Stones', 3:'Infertility', 4:'High_Blood_Pressure', 5:'Diabetes', 6:'ENT_Allergies', 7:'Joint_and_Back_Pain', 8:'Urinary_Tract_Infection', 9:'Acidity_and_Gastric_Problems', 10:'Seasonal_Flu_and_Cough' } for num in range(1, 11): html_path = os.path.join(html_dir, f'post_{num:02d}.html') tmp_png = os.path.join(tmp_dir, f'post_{num:02d}_tall.png') out_png = os.path.join(out_dir, f'post_{num:02d}_{name_map[num]}.png') # Render with taller window so nothing gets cut cmd = [ 'chromium', '--headless', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage', '--window-size=1080,1200', f'--screenshot={tmp_png}', f'file://{html_path}' ] subprocess.run(cmd, capture_output=True, text=True, timeout=30) if os.path.exists(tmp_png) and os.path.getsize(tmp_png) > 5000: # Crop top 1080px img = Image.open(tmp_png) print(f' Post {num:02d} raw size: {img.size}') cropped = img.crop((0, 0, 1080, 1080)) cropped.save(out_png, 'PNG', optimize=False, compress_level=1) print(f' ✓ Saved {name_map[num]}.png ({os.path.getsize(out_png)//1024} KB)') else: print(f' ✗ Post {num:02d} render failed') "
python3 -c " from PIL import Image import os d = '/home/daytona/workspace/shifa-health-posts/fixed/' files = sorted([f for f in os.listdir(d) if f.startswith('post_0') or f.startswith('post_1')]) all_ok = True for f in files: img = Image.open(d+f) img.verify() size = os.path.getsize(d+f) print(f'✓ {f} {img.size[0]}x{img.size[1]} {size//1024}KB') print(f'\nTotal: {len(files)} posts — ALL OK' if len(files)==10 else f'WARNING: only {len(files)} posts') "
| # | موضوع | Download |
|---|---|---|
| 1 | مثانے کا انفیکشن | post 01 Bladder Infection Image · PNG |
| 2 | گردوں کی پتھری | post 02 Kidney Stones Image · PNG |
| 3 | بانجھ پن / اولاد نہ ہونا | post 03 Infertility Image · PNG |
| 4 | ہائی بلڈ پریشر | post 04 High Blood Pressure Image · PNG |
| 5 | ذیابیطس / شوگر | post 05 Diabetes Image · PNG |
| 6 | کان، ناک اور گلے کی الرجی | post 06 ENT Allergies Image · PNG |
| 7 | جوڑوں اور کمر کا درد | post 07 Joint and Back Pain Image · PNG |
| 8 | پیشاب میں جلن اور انفیکشن | post 08 Urinary Tract Infection Image · PNG |
| 9 | معدے کی تیزابیت اور گیس | post 09 Acidity and Gastric Problems Image · PNG |
| 10 | موسمی بخار، نزلہ اور کھانسی | post 10 Seasonal Flu and Cough Image · PNG |
all pictured are not visiable. convert all files in to jpg file
python3 -c " from PIL import Image import os src = '/home/daytona/workspace/shifa-health-posts/fixed/' dst = '/home/daytona/workspace/shifa-health-posts/jpg/' os.makedirs(dst, exist_ok=True) files = sorted([f for f in os.listdir(src) if f.endswith('.png')]) for f in files: img = Image.open(src + f).convert('RGB') out_name = f.replace('.png', '.jpg') out_path = dst + out_name img.save(out_path, 'JPEG', quality=95, optimize=True) size = os.path.getsize(out_path) print(f'✓ {out_name} ({size//1024} KB)') print(f'\nDone: {len(files)} JPG files saved to {dst}') "
| # | موضوع | Download |
|---|---|---|
| 1 | مثانے کا انفیکشن | post 01 Bladder Infection Image · JPG |
| 2 | گردوں کی پتھری | post 02 Kidney Stones Image · JPG |
| 3 | بانجھ پن / اولاد نہ ہونا | post 03 Infertility Image · JPG |
| 4 | ہائی بلڈ پریشر | post 04 High Blood Pressure Image · JPG |
| 5 | ذیابیطس / شوگر | post 05 Diabetes Image · JPG |
| 6 | کان، ناک اور گلے کی الرجی | post 06 ENT Allergies Image · JPG |
| 7 | جوڑوں اور کمر کا درد | post 07 Joint and Back Pain Image · JPG |
| 8 | پیشاب میں جلن اور انفیکشن | post 08 Urinary Tract Infection Image · JPG |
| 9 | معدے کی تیزابیت اور گیس | post 09 Acidity and Gastric Problems Image · JPG |
| 10 | موسمی بخار، نزلہ اور کھانسی | post 10 Seasonal Flu and Cough Image · JPG |