[object Object]

← 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

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&quot; wide on paper / vinyl / peel-and-stick / grasscloth, or 54&quot; 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 &mdash; 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 →