from PIL import Image, ImageDraw, ImageFont, ImageFilter
import os, math, textwrap
# Canvas
W, H = 1600, 520
img = Image.new("RGBA", (W, H), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
# Colors
black = (8, 7, 6, 255)
deep_black = (0, 0, 0, 255)
cream = (254, 241, 228, 255)
orange = (255, 106, 0, 255)
gold = (218, 164, 65, 255)
dark_gold = (122, 73, 13, 255)
silver = (235, 235, 228, 255)
grey = (110, 110, 105, 255)
# Fonts
font_paths = [
"/usr/share/fonts/truetype/dejavu/DejaVuSerifCondensed-Bold.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed-Bold.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
]
title_font = ImageFont.truetype(font_paths[0], 92)
title_font_small = ImageFont.truetype(font_paths[0], 78)
tag_font = ImageFont.truetype(font_paths[1], 34)
body_font = ImageFont.truetype(font_paths[2], 28)
sub_font = ImageFont.truetype(font_paths[1], 22)
# Helper gradient background
bg = Image.new("RGBA", (W, H), (0, 0, 0, 0))
bg_draw = ImageDraw.Draw(bg)
for y in range(H):
# subtle warm center glow
t = y / H
r = int(5 + 35 * math.exp(-((y-H*0.55)/(H*0.55))**2))
g = int(4 + 18 * math.exp(-((y-H*0.55)/(H*0.55))**2))
b = int(3 + 4 * math.exp(-((y-H*0.55)/(H*0.55))**2))
bg_draw.line([(0,y),(W,y)], fill=(r,g,b,255))
img.alpha_composite(bg)
# Main nameplate polygon
margin_x = 80
top = 78
bottom = 420
center_x = W//2
notch_y = bottom + 58
poly = [
(margin_x+60, top), (W-margin_x-60, top),
(W-margin_x, top+55), (W-margin_x, bottom-40),
(W-margin_x-75, bottom+5), (center_x+160, bottom+5),
(center_x, notch_y), (center_x-160, bottom+5),
(margin_x+75, bottom+5), (margin_x, bottom-40),
(margin_x, top+55)
]
# Outer glow
glow_layer = Image.new("RGBA", (W,H), (0,0,0,0))
gd = ImageDraw.Draw(glow_layer)
gd.polygon(poly, fill=(255,106,0,80))
glow_layer = glow_layer.filter(ImageFilter.GaussianBlur(16))
img.alpha_composite(glow_layer)
# Draw polygon fill and borders
draw = ImageDraw.Draw(img)
draw.polygon(poly, fill=black)
# Border lines
def draw_polyline(points, fill, width):
draw.line(points + [points[0]], fill=fill, width=width, joint="curve")
draw_polyline(poly, (55, 30, 5, 255), 16)
draw_polyline(poly, gold, 8)
draw_polyline(poly, (255, 210, 86, 255), 3)
# Inner border inset polygon
inset = 30
inner_poly = [
(margin_x+85, top+28), (W-margin_x-85, top+28),
(W-margin_x-28, top+72), (W-margin_x-28, bottom-58),
(W-margin_x-92, bottom-20), (center_x+142, bottom-20),
(center_x, notch_y-32), (center_x-142, bottom-20),
(margin_x+92, bottom-20), (margin_x+28, bottom-58),
(margin_x+28, top+72)
]
draw_polyline(inner_poly, (230, 151, 25, 255), 3)
draw_polyline(inner_poly, (80, 45, 8, 255), 1)
# Metallic text effect function
def draw_text_shadowed(draw, pos, text, font, fill, shadow=(0,0,0,200), stroke_width=2, stroke_fill=(20,20,20,255)):
x,y = pos
draw.text((x+4,y+5), text, font=font, fill=shadow, stroke_width=stroke_width, stroke_fill=stroke_fill)
draw.text((x,y), text, font=font, fill=fill, stroke_width=stroke_width, stroke_fill=stroke_fill)
# Title with orange S
name_left = "JOSEPH"
name_mid = "S"
name_right = "GINSBERG"
# Calculate centered title widths
spacing = 24
bbox_l = draw.textbbox((0,0), name_left, font=title_font)
bbox_m = draw.textbbox((0,0), name_mid, font=title_font)
bbox_r = draw.textbbox((0,0), name_right, font=title_font)
total_w = (bbox_l[2]-bbox_l[0]) + (bbox_m[2]-bbox_m[0]) + (bbox_r[2]-bbox_r[0]) + spacing*2
x = (W-total_w)//2
y = 130
draw_text_shadowed(draw, (x, y), name_left, title_font, silver, stroke_width=2)
x += (bbox_l[2]-bbox_l[0]) + spacing
draw_text_shadowed(draw, (x, y-2), name_mid, title_font, orange, stroke_width=2, stroke_fill=(95,45,0,255))
x += (bbox_m[2]-bbox_m[0]) + spacing
draw_text_shadowed(draw, (x, y), name_right, title_font, silver, stroke_width=2)
# Tagline
tagline = "MENTOR & ENTREPRENEURSHIP SPECIALIST"
bbox = draw.textbbox((0,0), tagline, font=tag_font)
tx = (W-(bbox[2]-bbox[0]))//2
ty = 258
draw.text((tx, ty), tagline, font=tag_font, fill=(255, 174, 31, 255))
# Decorative horizontal lines
line_y = ty + 22
draw.line([(tx-150,line_y),(tx-25,line_y)], fill=orange, width=4)
draw.line([(tx+bbox[2]-bbox[0]+25,line_y),(tx+bbox[2]-bbox[0]+150,line_y)], fill=orange, width=4)
# Contact info
contact = "joseph@josephginsberg.com | +27 60 985 3276 | www.josephginsberg.com"
bbox = draw.textbbox((0,0), contact, font=body_font)
cx = (W-(bbox[2]-bbox[0]))//2
cy = 318
draw.text((cx, cy), contact, font=body_font, fill=cream)
# Sub brand strip
subbrands = "EDTREPRENEURIGNITE • MAKOYA • NMM • ALANGREY MAKERS"
bbox = draw.textbbox((0,0), subbrands, font=sub_font)
sx = (W-(bbox[2]-bbox[0]))//2
sy = 378
draw.text((sx, sy), subbrands, font=sub_font, fill=(190, 160, 105, 255))
# Bottom glow/star
for radius, alpha in [(55,70),(30,120),(12,230)]:
glow = Image.new("RGBA", (W,H), (0,0,0,0))
gd = ImageDraw.Draw(glow)
gd.ellipse((center_x-radius, notch_y-42-radius, center_x+radius, notch_y-42+radius), fill=(255,106,0,alpha))
glow = glow.filter(ImageFilter.GaussianBlur(radius//2))
img.alpha_composite(glow)
draw = ImageDraw.Draw(img)
draw.polygon([(center_x, notch_y-82), (center_x+16, notch_y-44), (center_x, notch_y-18), (center_x-16, notch_y-44)], fill=(255, 185, 35, 230))
# Export PNG and HTML
png_path = "/mnt/data/jsg_email_signature_preview.png"
img.save(png_path)
html = f'''<!doctype html>
<html>
<head><meta charset="utf-8"><title>JSG Email Signature</title></head>
<body style="margin:0;padding:24px;background:#f4f5f7;">
<table cellpadding="0" cellspacing="0" border="0" style="font-family:Poppins,Arial,sans-serif;max-width:680px;width:100%;background:#000000;border:2px solid #d9a441;border-radius:14px;overflow:hidden;box-shadow:0 0 18px rgba(255,106,0,0.45);">
<tr>
<td style="padding:18px 22px 14px 22px;background:#000000;">
<div style="font-size:24px;line-height:1.1;font-weight:800;letter-spacing:0.5px;color:#FEF1E4;text-transform:uppercase;">
Joseph <span style="color:#FF6A00;">Ginsberg</span>
</div>
<div style="font-size:14px;line-height:1.4;letter-spacing:2px;color:#d9a441;text-transform:uppercase;margin-top:5px;">
Edtrepreneur
</div>
<div style="height:2px;width:100%;max-width:520px;background:linear-gradient(90deg,#FF6A00,#d9a441,transparent);margin:10px 0 12px 0;"></div>
<div style="font-size:13px;line-height:1.8;color:#FEF1E4;">
<span style="color:#FF6A00;font-weight:700;">E:</span>
<a href="mailto:joseph@josephginsberg.com" style="color:#FEF1E4;text-decoration:none;">joseph@josephginsberg.com</a><br>
<span style="color:#FF6A00;font-weight:700;">M:</span>
<a href="tel:+27609853276" style="color:#FEF1E4;text-decoration:none;">+27 60 985 3276</a><br>
<span style="color:#FF6A00;font-weight:700;">W:</span>
<a href="https://www.josephginsberg.com" style="color:#FEF1E4;text-decoration:none;">www.josephginsberg.com</a>
</div>
</td>
</tr>
<tr>
<td style="background:#0b0b0b;border-top:1px solid rgba(217,164,65,0.45);padding:9px 18px;text-align:center;">
<span style="font-size:10.5px;letter-spacing:1.4px;color:#bfa06a;text-transform:uppercase;">EdtrepreneurIgnite</span>
<span style="color:#FF6A00;padding:0 9px;">•</span>
<span style="font-size:10.5px;letter-spacing:1.4px;color:#bfa06a;text-transform:uppercase;">Makoya</span>
<span style="color:#FF6A00;padding:0 9px;">•</span>
<span style="font-size:10.5px;letter-spacing:1.4px;color:#bfa06a;text-transform:uppercase;">NMM</span>
<span style="color:#FF6A00;padding:0 9px;">•</span>
<span style="font-size:10.5px;letter-spacing:1.4px;color:#bfa06a;text-transform:uppercase;">AlanGrey Makers</span>
</td>
</tr>
</table>
</body>
</html>'''
html_path = "/mnt/data/jsg_email_signature.html"
with open(html_path, "w", encoding="utf-8") as f:
f.write(html)
png_path, html_path
|
JOSEPH S GINSBERG
Edtrepreneur • Mentor • Small Business Specialist
JSG Mentor and Entrepreneurship Specialist
M: +27 81 375 9015 W: josephginsberg.com LinkedIn: joseph-ginsberg-706742b0
Guiding Entrepreneurs. Building Legacies. Mentorship that Creates Impact.
|
JSG Mentorship · Full System Architecture
The Complete Funnel Mind Map
Every resource, tool, agent, and automation — mapped end to end
LinkedIn
WordPress
Groundhogg CRM
Moodle LMS
AI Agent (JoeBot)
Calendly
Joseph (Manual)
① Awareness — How People Find You
1
LinkedIn Post 1 — IGNITE
Announcement post to 9,300 followers. CTA: comment IGNITE or DM. Drives warm leads directly to your DMs and landing page.
LinkedIn
2
LinkedIn Post 2 — Story
Mid-week trust-builder. A real story of transformation. Deepens emotional connection and builds authority with your audience.
LinkedIn
3
LinkedIn Post 3 — Value
Friday expert post. Identity-first insight. Attracts schools and corporates. Ends with a direct invitation to connect.
LinkedIn
② Capture — Getting the Lead into Your System
4
Landing Page — /mentorship
WordPress page on edtrepreneurignite.com. Carries the offer, the why, and the Groundhogg opt-in form embedded directly.
WordPress
5
Groundhogg Opt-In Form
Name, email, phone, and role dropdown. On submit: applies tag mentorship_enquiry and triggers the automation funnel immediately.
Groundhogg
6
Thank You Page — /mentorship-thankyou
Confirms submission, sets expectation of 24hr response, directs lead to check inbox. Keeps the energy warm post-submission.
WordPress
③ Nurture — The Automation Engine
7
Email 1 — Immediate (Day 0)
Personal welcome from Joseph. Acknowledges the enquiry, introduces the methodology, and drops the Calendly booking link to secure the discovery call.
Groundhogg
8
Email 2 — Identity Hook (Day 2)
“Who am I?” — the one question that changes everything. Deepens the identity-first philosophy and re-engages leads who haven’t booked yet.
Groundhogg
9
Email 3 — Hesitation Handler (Day 5)
Gentle nudge. Addresses uncertainty without pressure. Reminds lead that the discovery call is free and low-risk. Re-shares Calendly link.
Groundhogg
10
Email 4 — Final Follow-Up (Day 12)
Last touch. Leaves door open. Moves unresponsive leads to mentorship_nurture tag and long-term newsletter. No pressure, full dignity.
Groundhogg
④ Convert — Discovery Call to Paying Client
11
Calendly — Discovery Call
Free 20-minute call. Joseph listens, asks two questions, shares the programme. Closes the spot verbally. PayFast or PayPal link sent post-call.
Calendly
Joseph
12
WhatsApp Voice Note (Direct)
For DM leads from LinkedIn who don’t go through the form. Joseph sends a personal voice note, books the call directly. Human touch — highest conversion rate.
Joseph · Manual
13
Tag: mentorship_enrolled
Applied on payment confirmation. Triggers Moodle enrolment automatically via Groundhogg webhook. Client lands in the LMS within minutes of paying.
Groundhogg
⑤ Deliver — The Client Experience
14
Moodle — Identity Module (Month 1)
Motivator Mapping, Perception Style Profiling, Values Map, Unique Puzzle Piece. Weekly unlocking. Activity-based — never question-based.
Moodle LMS
15
Moodle — Direction Module (Month 2)
Vision Board, Edtrepreneur Canvas, Obstacle Mapping, 90-Day Goal Architecture. Structured with flexible access via WhatsApp between sessions.
Moodle LMS
16
Moodle — Momentum Module (Month 3)
First Offer Workshop, Accountability Dashboard, Habit Architecture, Personal Brand Foundation. Ends with JSG Completion Certificate.
Moodle LMS
17
JoeBot — Pre-Session Agent
JoeBot runs the Perception Style Assessment before Month 1 begins. Results are tagged in Groundhogg so Joseph arrives at every session knowing the client’s learning profile.
AI Agent · JoeBot
Groundhogg
⑥ Retain + Scale — Long-Term Revenue
18
Nurture Newsletter
All non-converting leads move to mentorship_nurture tag. Monthly value emails keep JSG top of mind until they’re ready. Long-term pipeline.
Groundhogg
19
School / Corporate Licensing
LinkedIn Post 3 and nurture sequence surface institutional leads. Moodle delivers curriculum at scale. Direct proposal sent by Joseph. R15k–R50k per engagement.
Moodle
Joseph
20
Affiliate Layer (Passive)
Hostinger and Divi affiliate links embedded in LMS resources and lead magnet. Converts passively once traffic builds. R2k–R8k/month at maturity.
WordPress
LinkedIn
