← back to Wallco Ai
wallco.ai: Gmail draft to Corey with 6 SDXL trellis+butterfly variations · base64-embedded thumbnails · saved via George POST /api/drafts (steve@dw, draftId r163145...)
25e633c3dbdbc6ac49e82f60fbae049a1ed07a78 · 2026-05-11 20:10:18 -0700 · Steve
Files touched
A scripts/draft_corey_letter.py
Diff
commit 25e633c3dbdbc6ac49e82f60fbae049a1ed07a78
Author: Steve <steve@designerwallcoverings.com>
Date: Mon May 11 20:10:18 2026 -0700
wallco.ai: Gmail draft to Corey with 6 SDXL trellis+butterfly variations · base64-embedded thumbnails · saved via George POST /api/drafts (steve@dw, draftId r163145...)
---
scripts/draft_corey_letter.py | 125 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)
diff --git a/scripts/draft_corey_letter.py b/scripts/draft_corey_letter.py
new file mode 100644
index 0000000..7c332bc
--- /dev/null
+++ b/scripts/draft_corey_letter.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+"""
+Compose a Gmail draft to Corey with 6 wallco.ai design suggestions.
+- Pulls the 6 most-recent SDXL designs from spoon_all_designs
+- Base64-embeds 400×400 thumbnails inline in HTML
+- POSTs to George /api/drafts on Mac1 (steve@designerwallcoverings.com)
+- Leaves To: blank — Steve picks Corey in Gmail before sending
+"""
+import base64, io, json, subprocess, urllib.request
+from pathlib import Path
+from PIL import Image
+
+GEORGE = 'http://100.107.67.67:9850'
+AUTH = 'YWRtaW46STNZdXNpc2RFU1VOZHh0cm1sYjNRSmV1OXE4T0RLSk8='
+
+def psql_json(sql):
+ r = subprocess.run(['psql','dw_unified','-At','-q'], input=sql, capture_output=True, text=True, check=True, timeout=10)
+ return json.loads(r.stdout.strip()) if r.stdout.strip() else []
+
+def img_to_b64_thumb(path, size=420):
+ img = Image.open(path).convert('RGB')
+ img.thumbnail((size, size), Image.LANCZOS)
+ buf = io.BytesIO()
+ img.save(buf, 'JPEG', quality=82, optimize=True)
+ return base64.b64encode(buf.getvalue()).decode('ascii')
+
+# Pull the 6 newest SDXL designs (the Corey set we just generated)
+rows = psql_json("""SELECT COALESCE(json_agg(t),'[]'::json) FROM (
+ SELECT id, dominant_hex, prompt, local_path FROM spoon_all_designs
+ WHERE generator='replicate' ORDER BY id DESC LIMIT 6) t;""")
+# Render in chronological order (oldest first → matches the original numbering 1–6)
+rows = list(reversed(rows))
+print(f'Composing draft with {len(rows)} designs')
+
+short_titles = [
+ 'Pale celadon trellis · watercolor butterflies, soft pinks',
+ 'Charcoal lattice · iridescent fantasy butterflies, jewel tones',
+ 'Cream Chinese fretwork · hand-painted swallowtails, coral',
+ 'Sage diamond lattice · monarch wings, muted gold',
+ 'Ivory architectural trellis · morpho-blue butterflies',
+ 'Blush garden trellis · hummingbird & butterfly motifs',
+]
+notes = [
+ 'Most delicate; reads quiet from across a room, sings up close.',
+ 'Most dramatic; the lattice grounds the iridescence — works in a powder room or library.',
+ 'Hand-painted feel; the swallowtail silhouettes pop against the cream fretwork.',
+ 'The Loma Linda direction with a muted-gold palette; warm, sun-faded, classic.',
+ 'Most architectural; the blues feel grown-up and gallery-ready.',
+ 'Most playful; could read storybook in a child\'s room or witty in a powder.',
+]
+
+cards_html = []
+for i, r in enumerate(rows):
+ b64 = img_to_b64_thumb(r['local_path'])
+ hex_ = r['dominant_hex'] or '#888'
+ title = short_titles[i] if i < len(short_titles) else f"Design {i+1}"
+ note = notes[i] if i < len(notes) else ''
+ cards_html.append(f"""
+<table cellpadding="0" cellspacing="0" border="0" style="margin:0 0 24px;width:100%;max-width:560px">
+ <tr>
+ <td style="vertical-align:top;width:200px;padding-right:18px">
+ <img src="data:image/jpeg;base64,{b64}" width="200" height="200"
+ style="display:block;border:1px solid #ddd;border-radius:6px" alt="Design {i+1}">
+ </td>
+ <td style="vertical-align:top;font:14px/1.5 -apple-system,Helvetica,Arial,sans-serif;color:#1a1a1a">
+ <div style="font-family:Georgia,serif;font-size:17px;font-weight:400;margin-bottom:4px">{i+1}. {title}</div>
+ <div style="font-size:11px;color:#888;letter-spacing:.04em;text-transform:uppercase;margin-bottom:8px">
+ <span style="display:inline-block;width:10px;height:10px;background:{hex_};border-radius:50%;border:1px solid #ddd;vertical-align:middle;margin-right:5px"></span>{hex_}
+ </div>
+ <div style="color:#444">{note}</div>
+ </td>
+ </tr>
+</table>""")
+
+body = f"""<div style="font:14px/1.6 -apple-system,Helvetica,Arial,sans-serif;color:#1a1a1a;max-width:600px">
+<p>Hi Corey,</p>
+
+<p>I sketched six directions for the trellis-with-butterflies idea — each one a different mood within the same family. Trellis is the structure; the butterflies are the surprise. Tell me which ones feel right and I'll refine. Any of them can come at 24" wide on paper / vinyl / peel-and-stick / grasscloth, or 54" commercial vinyl for the larger areas.</p>
+
+<hr style="border:0;border-top:1px solid #eee;margin:18px 0">
+
+{''.join(cards_html)}
+
+<hr style="border:0;border-top:1px solid #eee;margin:18px 0">
+
+<p>Next steps — pick your favorites, then I'll:</p>
+<ol>
+ <li>Tighten the palette and butterfly scale</li>
+ <li>Print a memo sample at scale on your chosen substrate</li>
+ <li>Render a wall mock-up at the actual ceiling height of the room</li>
+</ol>
+
+<p>If none of these are quite right, just tell me the direction (lighter, darker, more graphic, more painterly, larger butterflies, fewer butterflies) and I'll iterate. Each variant takes about a minute on my end.</p>
+
+<p>Steve<br>Designer Wallcoverings — Sherman Oaks<br>
+<a href="mailto:steve@designerwallcoverings.com">steve@designerwallcoverings.com</a></p>
+</div>"""
+
+# POST to George drafts
+payload = {
+ 'subject': 'Six trellis-with-butterfly directions — pick your favorites',
+ 'body': body,
+ # 'to' left blank — Steve picks Corey in Gmail
+}
+req = urllib.request.Request(
+ f'{GEORGE}/api/drafts',
+ data=json.dumps(payload).encode('utf-8'),
+ headers={
+ 'Authorization': f'Basic {AUTH}',
+ 'Content-Type': 'application/json',
+ 'X-Account': 'steve-office' # steve@designerwallcoverings.com
+ }
+)
+try:
+ with urllib.request.urlopen(req, timeout=30) as r:
+ resp = json.loads(r.read())
+ print(json.dumps(resp, indent=2))
+ print()
+ print(f"Draft saved with id: {resp.get('draftId')}")
+ print(f"Account: {resp.get('account')}")
+ print(f"Body size: {len(body):,} bytes (HTML, base64 thumbnails inline)")
+except Exception as e:
+ print(f'ERROR: {e}')
+ if hasattr(e, 'read'):
+ print(e.read()[:400])
← ba87275 Fix apcaLc hex parser to handle 3-char shortcuts (#fff, #000
·
back to Wallco Ai
·
design/:id: replace left side-panel with hamburger → tabbed 12f88ca →