← back to Pattern Vault
pipeline: add groundColor mode to gen_briefs.py (front-load flat ground color + dark-bg negative + guidance 9.5) — codifies the chartreuse fix; set on deco brief
5ab1439b1640b4a1c06028e643807270c6039499 · 2026-07-02 14:14:39 -0700 · Steve
Files touched
M data/trend-board.jsonM scripts/gen_briefs.pyM whimsical-compare/.portA whimsical-compare/public/faces.htmlA whimsical-compare/public/faces/face_01.pngA whimsical-compare/public/faces/face_02.pngA whimsical-compare/public/faces/face_03.pngA whimsical-compare/public/faces/face_04.pngA whimsical-compare/public/faces/face_05.pngA whimsical-compare/public/faces/face_06.pngA whimsical-compare/public/faces/face_07.pngA whimsical-compare/public/faces/face_08.pngA whimsical-compare/public/faces/face_09.pngA whimsical-compare/public/faces/face_10.pngA whimsical-compare/public/faces/face_11.pngA whimsical-compare/public/faces/face_12.pngA whimsical-compare/public/faces/face_13.pngA whimsical-compare/public/faces/face_14.pngA whimsical-compare/public/faces/face_15.pngA whimsical-compare/public/faces/face_16.pngA whimsical-compare/public/faces/face_17.pngA whimsical-compare/public/faces/face_18.pngA whimsical-compare/public/faces/face_19.pngA whimsical-compare/public/faces/face_20.pngA whimsical-compare/public/faces/manifest.jsonA whimsical-compare/scripts/gen_faces.pyM whimsical-compare/server.js
Diff
commit 5ab1439b1640b4a1c06028e643807270c6039499
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jul 2 14:14:39 2026 -0700
pipeline: add groundColor mode to gen_briefs.py (front-load flat ground color + dark-bg negative + guidance 9.5) — codifies the chartreuse fix; set on deco brief
---
data/trend-board.json | 2 +-
scripts/gen_briefs.py | 20 +++-
whimsical-compare/.port | 2 +-
whimsical-compare/public/faces.html | 63 ++++++++++++
whimsical-compare/public/faces/face_01.png | Bin 0 -> 2249684 bytes
whimsical-compare/public/faces/face_02.png | Bin 0 -> 2337934 bytes
whimsical-compare/public/faces/face_03.png | Bin 0 -> 2312167 bytes
whimsical-compare/public/faces/face_04.png | Bin 0 -> 2308220 bytes
whimsical-compare/public/faces/face_05.png | Bin 0 -> 2231480 bytes
whimsical-compare/public/faces/face_06.png | Bin 0 -> 2256768 bytes
whimsical-compare/public/faces/face_07.png | Bin 0 -> 2404168 bytes
whimsical-compare/public/faces/face_08.png | Bin 0 -> 2253159 bytes
whimsical-compare/public/faces/face_09.png | Bin 0 -> 2204017 bytes
whimsical-compare/public/faces/face_10.png | Bin 0 -> 2308672 bytes
whimsical-compare/public/faces/face_11.png | Bin 0 -> 2369006 bytes
whimsical-compare/public/faces/face_12.png | Bin 0 -> 2395694 bytes
whimsical-compare/public/faces/face_13.png | Bin 0 -> 2325680 bytes
whimsical-compare/public/faces/face_14.png | Bin 0 -> 2054004 bytes
whimsical-compare/public/faces/face_15.png | Bin 0 -> 2263619 bytes
whimsical-compare/public/faces/face_16.png | Bin 0 -> 2360211 bytes
whimsical-compare/public/faces/face_17.png | Bin 0 -> 2266646 bytes
whimsical-compare/public/faces/face_18.png | Bin 0 -> 2307006 bytes
whimsical-compare/public/faces/face_19.png | Bin 0 -> 2243095 bytes
whimsical-compare/public/faces/face_20.png | Bin 0 -> 2351661 bytes
whimsical-compare/public/faces/manifest.json | 147 +++++++++++++++++++++++++++
whimsical-compare/scripts/gen_faces.py | 99 ++++++++++++++++++
whimsical-compare/server.js | 8 +-
27 files changed, 334 insertions(+), 7 deletions(-)
diff --git a/data/trend-board.json b/data/trend-board.json
index 0407186..d4e6f49 100644
--- a/data/trend-board.json
+++ b/data/trend-board.json
@@ -27,7 +27,7 @@
{ "id": "BRIEF-2026-animalprint-01", "lane": "Animal-skin print with a twist", "title": "Rosewood Cheetah", "prompt": "Original seamless repeat of stylised cheetah-rosette markings, hand-painted look, scattered on a warm plaster ground; skin-print abstraction only, no animal figures; rose-clay and cocoa spots on oatmeal.", "colorway": "Rose-clay + cocoa on oatmeal", "targetTier": "commercial_print $495", "settlement": "SAFE" },
{ "id": "BRIEF-2026-animalprint-02", "lane": "Animal-skin print with a twist", "title": "Verdant Tiger Stripe", "prompt": "Original painterly tiger-stripe skin-print abstraction (no animal figure) in forest and moss green on deep ink; brushy irregular hand-inked stripes reading as luxe textile.", "colorway": "Forest + moss on ink", "targetTier": "commercial_print $495", "settlement": "SAFE" },
{ "id": "BRIEF-2026-chinoiserie-sat-01", "lane": "Chinoiserie (saturated, no birds)", "title": "Nocturne Garden Chinoiserie", "prompt": "Original hand-painted-look chinoiserie of flowering branches, peonies and boughs on deep forest-green ground; gold + blush blooms. STRICTLY branches + flowers, NO birds, NO butterflies.", "colorway": "Gold + blush on forest green", "targetTier": "commercial_print $495", "settlement": "SAFE - no birds/butterflies" },
- { "id": "BRIEF-2026-deco-01", "lane": "Chartreuse Art-Deco geometric", "title": "Gilded Fan Deco", "prompt": "Original Art-Deco geometric of repeating fan/sunburst arcs and stepped chevrons, metallic-gold linework on chartreuse ground; 1920s revival, crisp symmetry.", "colorway": "Metallic gold on chartreuse", "targetTier": "commercial_print $495", "settlement": "SAFE - abstract geometric" },
+ { "id": "BRIEF-2026-deco-01", "lane": "Chartreuse Art-Deco geometric", "title": "Gilded Fan Deco", "prompt": "Original Art-Deco geometric of repeating fan/sunburst arcs and stepped chevrons, metallic-gold linework, 1920s Gatsby revival, crisp symmetry, no plants no leaves no florals", "colorway": "Metallic gold on chartreuse", "groundColor": "#B0C000 chartreuse yellow-green", "targetTier": "commercial_print $495", "settlement": "SAFE - abstract geometric" },
{ "id": "BRIEF-2026-texture-01", "lane": "Tactile texture-effect", "title": "Linen Weave Plain", "prompt": "Original photoreal woven linen/grasscloth texture as seamless near-plain wallcovering; visible warp/weft slubs; warm greige; illusion-of-tactility.", "colorway": "Warm greige linen", "targetTier": "digital_single_use $149", "settlement": "SAFE - abstract texture" },
{ "id": "BRIEF-2026-ditsy-01", "lane": "Small-scale ditsy micro-print", "title": "Meadow Ditsy", "prompt": "Original tiny-scale ditsy floral micro-print, hand-drawn sprigs and dots evenly scattered on open cream ground; sized for small rooms; multiple colorways.", "colorway": "Sage + terracotta sprigs on bone", "targetTier": "digital_single_use $149", "settlement": "SAFE - non-directional sprigs, open ground" },
{ "id": "BRIEF-2026-mural-01", "lane": "Painterly scenic mural", "title": "Saturated Garden Panorama", "prompt": "Original full-wall painterly botanical garden panorama - layered ferns, hydrangea, foliage receding into mist on deep teal-green ground; fine-art scenery, single colorway. NO birds.", "colorway": "Deep teal-green garden", "targetTier": "mural commercial_print $795", "settlement": "SAFE - no birds/butterflies, non-tropical" },
diff --git a/scripts/gen_briefs.py b/scripts/gen_briefs.py
index 805f9a6..1336d70 100644
--- a/scripts/gen_briefs.py
+++ b/scripts/gen_briefs.py
@@ -20,6 +20,11 @@ NEG = ("birds, bird, butterfly, butterflies, bananas, banana leaves, grapes, gra
"tropical monstera palm fronds, text, watermark, signature, logo, blurry, low quality, "
"jpeg artifacts, seams, mismatched edges, frame, border, vignette")
+# Learned 2026-07-02: SDXL defaults grounds to muddy-dark and ignores a color named late in the
+# prompt. To force a ground color, front-load it as the FIRST token, negate dark backgrounds, and
+# bump guidance so the color binds. Add a "groundColor" field to a brief to trigger this mode.
+DARK_NEG = "black background, dark background, navy background, charcoal background, gradient background"
+
def sdxl_prompt(b):
base = b["prompt"]
if b["id"] == "BRIEF-2026-mural-01":
@@ -28,7 +33,13 @@ def sdxl_prompt(b):
else:
tile = "seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering"
w, h = 1024, 1024
- return f"{base} {tile}. Colorway: {b['colorway']}.", w, h
+ ground = b.get("groundColor")
+ if ground:
+ # front-load the flat ground color; bump guidance; add dark-bg negative
+ prompt = (f"flat solid {ground} background color filling the entire canvas, "
+ f"{base} {tile}. Colorway: {b['colorway']}.")
+ return prompt, w, h, 9.5, DARK_NEG
+ return f"{base} {tile}. Colorway: {b['colorway']}.", w, h, 7.5, ""
UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
def post(url, payload, extra_headers=None):
@@ -51,13 +62,14 @@ total_secs = 0.0
seeds = [101, 202] # 2 variants/brief
for b in briefs:
- prompt, w, h = sdxl_prompt(b)
+ prompt, w, h, guidance, extra_neg = sdxl_prompt(b)
+ neg = NEG + (", " + extra_neg if extra_neg else "")
for i, seed in enumerate(seeds, 1):
tag = f"{b['id']}_v{i}"
payload = {"version": VERSION, "input": {
- "prompt": prompt, "negative_prompt": NEG,
+ "prompt": prompt, "negative_prompt": neg,
"width": w, "height": h, "num_inference_steps": 30,
- "guidance_scale": 7.5, "seed": seed, "refine": "no_refiner"
+ "guidance_scale": guidance, "seed": seed, "refine": "no_refiner"
}}
ok = False
for attempt in range(4):
diff --git a/whimsical-compare/.port b/whimsical-compare/.port
index 1b98715..8c9536e 100644
--- a/whimsical-compare/.port
+++ b/whimsical-compare/.port
@@ -1 +1 @@
-60218
\ No newline at end of file
+9793
\ No newline at end of file
diff --git a/whimsical-compare/public/faces.html b/whimsical-compare/public/faces.html
new file mode 100644
index 0000000..fd736d3
--- /dev/null
+++ b/whimsical-compare/public/faces.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<title>Tema e Variazioni — Our Faces</title>
+<style>
+ :root { --cols: 4; }
+ * { box-sizing: border-box; }
+ body { margin: 0; font-family: -apple-system, "Segoe UI", Roboto, sans-serif; background: #f3f1ec; color: #1c1a17; }
+ header { position: sticky; top: 0; z-index: 5; background: #fdfcf9; border-bottom: 1px solid #e2dccf;
+ padding: 16px 24px; display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
+ header h1 { margin: 0; font-size: 20px; font-weight: 600; letter-spacing: .4px; }
+ header .sub { color: #8a8172; font-size: 12px; }
+ .controls { margin-left: auto; display: flex; align-items: center; gap: 14px; }
+ .controls label { font-size: 12px; color: #6b6355; display: flex; align-items: center; gap: 6px; }
+ .note { padding: 10px 24px; background: #fbf4e6; border-bottom: 1px solid #ecdfc4; font-size: 12px; color: #7a6a2f; }
+ .wrap { padding: 24px; }
+ .grid { display: grid; grid-template-columns: repeat(var(--cols), 1fr); gap: 20px; }
+ .tile { background: #fff; border: 1px solid #e2dccf; border-radius: 12px; overflow: hidden; }
+ .tile img { width: 100%; aspect-ratio: 1/1; object-fit: cover; display: block; background: #eee; }
+ .tile .cap { padding: 9px 12px; }
+ .tile .cap b { font-size: 13px; } .tile .cap .d { font-size: 11px; color: #8a8172; margin-top: 2px; }
+ .wallprev { margin: 8px 0 0; }
+ .pending { display: flex; align-items: center; justify-content: center; aspect-ratio: 1/1;
+ background: repeating-linear-gradient(45deg,#eee,#eee 10px,#e6e1d6 10px,#e6e1d6 20px); color: #999; font-size: 12px; }
+</style>
+</head>
+<body>
+<header>
+ <div><h1>Tema e Variazioni — <span style="color:#8a8172">Our Faces</span></h1>
+ <div class="sub">20 original b&w portrait-medallion tiles · whimsical variations · our own face</div></div>
+ <div class="controls">
+ <label>Density <input type="range" id="density" min="2" max="6" value="4"></label>
+ <label><input type="checkbox" id="wall"> show as wall repeat</label>
+ </div>
+</header>
+<div class="note">Original homage to the <b>theme-and-variations portrait-plate format</b> — our own invented face and variations. Not a reproduction of Fornasetti's design or their model.</div>
+<div class="wrap"><div class="grid" id="grid"></div></div>
+<script>
+const $ = s => document.querySelector(s);
+let DATA = { designs: [] }, WALL = false;
+function tile(d) {
+ const img = d.file
+ ? (WALL ? `<div class="wallprev" style="aspect-ratio:1/1;background:url('${d.file}');background-size:33%;background-repeat:repeat"></div>`
+ : `<img loading="lazy" src="${d.file}" alt="${d.name}">`)
+ : `<div class="pending">rendering…</div>`;
+ return `<div class="tile">${img}<div class="cap"><b>${d.n}. ${d.name}</b><div class="d">${d.desc}</div></div></div>`;
+}
+function render() { $('#grid').innerHTML = DATA.designs.map(tile).join(''); }
+async function load() {
+ const r = await fetch('/api/faces'); DATA = await r.json();
+ // pad to 20 slots so pending tiles show
+ const have = new Set(DATA.designs.map(d => d.n));
+ for (let i = 1; i <= 20; i++) if (!have.has(i)) DATA.designs.push({ n: i, name: 'variation ' + i, desc: '', file: null });
+ DATA.designs.sort((a, b) => a.n - b.n); render();
+}
+$('#density').oninput = e => document.documentElement.style.setProperty('--cols', e.target.value);
+$('#wall').onchange = e => { WALL = e.target.checked; render(); };
+load(); setInterval(load, 12000);
+</script>
+</body>
+</html>
diff --git a/whimsical-compare/public/faces/face_01.png b/whimsical-compare/public/faces/face_01.png
new file mode 100644
index 0000000..568159e
Binary files /dev/null and b/whimsical-compare/public/faces/face_01.png differ
diff --git a/whimsical-compare/public/faces/face_02.png b/whimsical-compare/public/faces/face_02.png
new file mode 100644
index 0000000..9480903
Binary files /dev/null and b/whimsical-compare/public/faces/face_02.png differ
diff --git a/whimsical-compare/public/faces/face_03.png b/whimsical-compare/public/faces/face_03.png
new file mode 100644
index 0000000..f4dc39e
Binary files /dev/null and b/whimsical-compare/public/faces/face_03.png differ
diff --git a/whimsical-compare/public/faces/face_04.png b/whimsical-compare/public/faces/face_04.png
new file mode 100644
index 0000000..17d313a
Binary files /dev/null and b/whimsical-compare/public/faces/face_04.png differ
diff --git a/whimsical-compare/public/faces/face_05.png b/whimsical-compare/public/faces/face_05.png
new file mode 100644
index 0000000..59469aa
Binary files /dev/null and b/whimsical-compare/public/faces/face_05.png differ
diff --git a/whimsical-compare/public/faces/face_06.png b/whimsical-compare/public/faces/face_06.png
new file mode 100644
index 0000000..b330c3d
Binary files /dev/null and b/whimsical-compare/public/faces/face_06.png differ
diff --git a/whimsical-compare/public/faces/face_07.png b/whimsical-compare/public/faces/face_07.png
new file mode 100644
index 0000000..bd196ba
Binary files /dev/null and b/whimsical-compare/public/faces/face_07.png differ
diff --git a/whimsical-compare/public/faces/face_08.png b/whimsical-compare/public/faces/face_08.png
new file mode 100644
index 0000000..6443a8b
Binary files /dev/null and b/whimsical-compare/public/faces/face_08.png differ
diff --git a/whimsical-compare/public/faces/face_09.png b/whimsical-compare/public/faces/face_09.png
new file mode 100644
index 0000000..d1e14cb
Binary files /dev/null and b/whimsical-compare/public/faces/face_09.png differ
diff --git a/whimsical-compare/public/faces/face_10.png b/whimsical-compare/public/faces/face_10.png
new file mode 100644
index 0000000..49eef43
Binary files /dev/null and b/whimsical-compare/public/faces/face_10.png differ
diff --git a/whimsical-compare/public/faces/face_11.png b/whimsical-compare/public/faces/face_11.png
new file mode 100644
index 0000000..66824a7
Binary files /dev/null and b/whimsical-compare/public/faces/face_11.png differ
diff --git a/whimsical-compare/public/faces/face_12.png b/whimsical-compare/public/faces/face_12.png
new file mode 100644
index 0000000..b19de72
Binary files /dev/null and b/whimsical-compare/public/faces/face_12.png differ
diff --git a/whimsical-compare/public/faces/face_13.png b/whimsical-compare/public/faces/face_13.png
new file mode 100644
index 0000000..e2a8532
Binary files /dev/null and b/whimsical-compare/public/faces/face_13.png differ
diff --git a/whimsical-compare/public/faces/face_14.png b/whimsical-compare/public/faces/face_14.png
new file mode 100644
index 0000000..426fa76
Binary files /dev/null and b/whimsical-compare/public/faces/face_14.png differ
diff --git a/whimsical-compare/public/faces/face_15.png b/whimsical-compare/public/faces/face_15.png
new file mode 100644
index 0000000..7919e3e
Binary files /dev/null and b/whimsical-compare/public/faces/face_15.png differ
diff --git a/whimsical-compare/public/faces/face_16.png b/whimsical-compare/public/faces/face_16.png
new file mode 100644
index 0000000..b4b29be
Binary files /dev/null and b/whimsical-compare/public/faces/face_16.png differ
diff --git a/whimsical-compare/public/faces/face_17.png b/whimsical-compare/public/faces/face_17.png
new file mode 100644
index 0000000..fde43e0
Binary files /dev/null and b/whimsical-compare/public/faces/face_17.png differ
diff --git a/whimsical-compare/public/faces/face_18.png b/whimsical-compare/public/faces/face_18.png
new file mode 100644
index 0000000..937aa96
Binary files /dev/null and b/whimsical-compare/public/faces/face_18.png differ
diff --git a/whimsical-compare/public/faces/face_19.png b/whimsical-compare/public/faces/face_19.png
new file mode 100644
index 0000000..575d920
Binary files /dev/null and b/whimsical-compare/public/faces/face_19.png differ
diff --git a/whimsical-compare/public/faces/face_20.png b/whimsical-compare/public/faces/face_20.png
new file mode 100644
index 0000000..a6900c7
Binary files /dev/null and b/whimsical-compare/public/faces/face_20.png differ
diff --git a/whimsical-compare/public/faces/manifest.json b/whimsical-compare/public/faces/manifest.json
new file mode 100644
index 0000000..4ea5f03
--- /dev/null
+++ b/whimsical-compare/public/faces/manifest.json
@@ -0,0 +1,147 @@
+{
+ "title": "Tema e Variazioni \u2014 our faces",
+ "count": 20,
+ "est_cost_usd": 0.066,
+ "designs": [
+ {
+ "n": 1,
+ "name": "Mona Lisa",
+ "desc": "the face wearing a subtle Mona Lisa smile with a soft renaissance veil",
+ "file": "/faces/face_01.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: the face wearing a subtle Mona Lisa smile with a soft renaissance veil."
+ },
+ {
+ "n": 2,
+ "name": "Pipe Dream",
+ "desc": "a slender pipe held at the lips with a curl of smoke",
+ "file": "/faces/face_02.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a slender pipe held at the lips with a curl of smoke."
+ },
+ {
+ "n": 3,
+ "name": "Monocle",
+ "desc": "a single monocle over one eye on a fine chain",
+ "file": "/faces/face_03.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a single monocle over one eye on a fine chain."
+ },
+ {
+ "n": 4,
+ "name": "Crown",
+ "desc": "a delicate line-drawn crown resting on the hair",
+ "file": "/faces/face_04.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a delicate line-drawn crown resting on the hair."
+ },
+ {
+ "n": 5,
+ "name": "Keyhole",
+ "desc": "a small keyhole motif where one eye would be, surreal",
+ "file": "/faces/face_05.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a small keyhole motif where one eye would be, surreal."
+ },
+ {
+ "n": 6,
+ "name": "Playing Card",
+ "desc": "the portrait mirrored like a queen playing card, top and bottom",
+ "file": "/faces/face_06.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: the portrait mirrored like a queen playing card, top and bottom."
+ },
+ {
+ "n": 7,
+ "name": "Blindfold",
+ "desc": "a lace blindfold across the eyes, mysterious",
+ "file": "/faces/face_07.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a lace blindfold across the eyes, mysterious."
+ },
+ {
+ "n": 8,
+ "name": "Teacup",
+ "desc": "balancing a tiny teacup and saucer on the crown of the head",
+ "file": "/faces/face_08.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: balancing a tiny teacup and saucer on the crown of the head."
+ },
+ {
+ "n": 9,
+ "name": "Clockface",
+ "desc": "a small clock face set into the cheek, surreal collage",
+ "file": "/faces/face_09.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a small clock face set into the cheek, surreal collage."
+ },
+ {
+ "n": 10,
+ "name": "Moon Phase",
+ "desc": "crescent moons for earrings and stars scattered in the hair",
+ "file": "/faces/face_10.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: crescent moons for earrings and stars scattered in the hair."
+ },
+ {
+ "n": 11,
+ "name": "Pince-Nez",
+ "desc": "old-fashioned pince-nez spectacles perched on the nose",
+ "file": "/faces/face_11.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: old-fashioned pince-nez spectacles perched on the nose."
+ },
+ {
+ "n": 12,
+ "name": "Ribbon",
+ "desc": "an oversized bow ribbon tied at the chin",
+ "file": "/faces/face_12.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: an oversized bow ribbon tied at the chin."
+ },
+ {
+ "n": 13,
+ "name": "Birdcage Veil",
+ "desc": "a fine birdcage veil netting over the upper face",
+ "file": "/faces/face_13.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a fine birdcage veil netting over the upper face."
+ },
+ {
+ "n": 14,
+ "name": "Pearl Choker",
+ "desc": "an ornate pearl-and-jewel choker at the throat",
+ "file": "/faces/face_14.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: an ornate pearl-and-jewel choker at the throat."
+ },
+ {
+ "n": 15,
+ "name": "Winking",
+ "desc": "one eye closed in a playful wink",
+ "file": "/faces/face_15.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: one eye closed in a playful wink."
+ },
+ {
+ "n": 16,
+ "name": "Feather Hat",
+ "desc": "a jaunty plumed hat tilted over the brow",
+ "file": "/faces/face_16.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a jaunty plumed hat tilted over the brow."
+ },
+ {
+ "n": 17,
+ "name": "Mustache",
+ "desc": "a curled dapper mustache, gender-play whimsy",
+ "file": "/faces/face_17.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a curled dapper mustache, gender-play whimsy."
+ },
+ {
+ "n": 18,
+ "name": "Veil of Lace",
+ "desc": "half the face dissolving into an intricate lace pattern",
+ "file": "/faces/face_18.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: half the face dissolving into an intricate lace pattern."
+ },
+ {
+ "n": 19,
+ "name": "Sun Rays",
+ "desc": "a halo of fine engraved sun rays behind the head",
+ "file": "/faces/face_19.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: a halo of fine engraved sun rays behind the head."
+ },
+ {
+ "n": 20,
+ "name": "Masquerade",
+ "desc": "an ornate venetian masquerade mask over the eyes",
+ "file": "/faces/face_20.png",
+ "prompt": "black and white vintage engraving wallpaper, a single elegant original woman's face inside a circular medallion plate, fine cross-hatch etching and stipple, monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations portrait-plate wallpaper, our own original face, not a copy of any existing design, seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering; variation: an ornate venetian masquerade mask over the eyes."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/whimsical-compare/scripts/gen_faces.py b/whimsical-compare/scripts/gen_faces.py
new file mode 100644
index 0000000..85833bb
--- /dev/null
+++ b/whimsical-compare/scripts/gen_faces.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+"""
+"Tema e Variazioni" — 20 ORIGINAL face-medallion wallpaper tiles.
+
+Homage to the FORMAT of Fornasetti's black-and-white repeating portrait plates
+(theme-and-variations), rendered with our OWN invented face and our own whimsical
+variations — NOT a copy of Fornasetti's design and NOT their model (Lina Cavalieri).
+Original interpretation only.
+
+Each tile = a seamless repeating wallpaper of a single circular b&w engraved
+portrait medallion with one whimsical twist (pipe, monocle, Mona Lisa framing,
+crown, keyhole, playing-card, etc.).
+
+Replicate SDXL (~1c/img). Usage: python3 gen_faces.py [--n 20] [--seed-base N]
+"""
+import os, re, json, time, sys, urllib.request
+
+HERE = os.path.dirname(os.path.abspath(__file__))
+ROOT = os.path.dirname(HERE)
+OUT = f"{ROOT}/public/faces"
+os.makedirs(OUT, exist_ok=True)
+
+def argv(f, d=None):
+ a = sys.argv; return a[a.index(f)+1] if f in a else d
+N = int(argv("--n", "20"))
+SEED_BASE = int(argv("--seed-base", str(int(time.time()) % 1000000)))
+
+tok = None
+with open(os.path.expanduser("~/Projects/secrets-manager/.env")) as f:
+ m = re.search(r"REPLICATE_API_TOKEN=([A-Za-z0-9_-]+)", f.read()); tok = m and m.group(1)
+assert tok, "no replicate token"
+UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
+
+# 20 whimsical variations — our own "theme e variazioni"
+VARIATIONS = [
+ ("Mona Lisa", "the face wearing a subtle Mona Lisa smile with a soft renaissance veil"),
+ ("Pipe Dream", "a slender pipe held at the lips with a curl of smoke"),
+ ("Monocle", "a single monocle over one eye on a fine chain"),
+ ("Crown", "a delicate line-drawn crown resting on the hair"),
+ ("Keyhole", "a small keyhole motif where one eye would be, surreal"),
+ ("Playing Card", "the portrait mirrored like a queen playing card, top and bottom"),
+ ("Blindfold", "a lace blindfold across the eyes, mysterious"),
+ ("Teacup", "balancing a tiny teacup and saucer on the crown of the head"),
+ ("Clockface", "a small clock face set into the cheek, surreal collage"),
+ ("Moon Phase", "crescent moons for earrings and stars scattered in the hair"),
+ ("Pince-Nez", "old-fashioned pince-nez spectacles perched on the nose"),
+ ("Ribbon", "an oversized bow ribbon tied at the chin"),
+ ("Birdcage Veil", "a fine birdcage veil netting over the upper face"),
+ ("Pearl Choker", "an ornate pearl-and-jewel choker at the throat"),
+ ("Winking", "one eye closed in a playful wink"),
+ ("Feather Hat", "a jaunty plumed hat tilted over the brow"),
+ ("Mustache", "a curled dapper mustache, gender-play whimsy"),
+ ("Veil of Lace", "half the face dissolving into an intricate lace pattern"),
+ ("Sun Rays", "a halo of fine engraved sun rays behind the head"),
+ ("Masquerade", "an ornate venetian masquerade mask over the eyes"),
+]
+
+BASE = ("black and white vintage engraving wallpaper, a single elegant original woman's face "
+ "inside a circular medallion plate, fine cross-hatch etching and stipple, "
+ "monochrome charcoal on ivory, surrealist whimsical homage to theme-and-variations "
+ "portrait-plate wallpaper, our own original face, not a copy of any existing design, "
+ "seamless repeating wallpaper pattern, tileable, flat lay, even lighting, high-end wallcovering")
+NEG = ("color, colour, photograph, photo-realistic, modern, text, watermark, signature, logo, "
+ "blurry, low quality, jpeg artifacts, seams, frame, border, vignette, extra faces, deformed")
+
+def hj(url, payload=None):
+ hdr = {"User-Agent": UA, "Content-Type": "application/json", "Authorization": f"Bearer {tok}"}
+ data = json.dumps(payload).encode() if payload else None
+ req = urllib.request.Request(url, data=data, headers=hdr, method="POST" if data else "GET")
+ with urllib.request.urlopen(req, timeout=180) as r: return json.load(r)
+
+def sdxl(prompt, seed):
+ ver = hj("https://api.replicate.com/v1/models/stability-ai/sdxl")["latest_version"]["id"]
+ pred = hj("https://api.replicate.com/v1/predictions", {"version": ver, "input": {
+ "prompt": prompt, "negative_prompt": NEG, "width": 1024, "height": 1024,
+ "num_inference_steps": 34, "guidance_scale": 8.0, "seed": seed, "refine": "no_refiner"}})
+ for _ in range(90):
+ if pred.get("status") in ("succeeded", "failed", "canceled"): break
+ time.sleep(2); pred = hj(pred["urls"]["get"])
+ return pred
+
+designs = []; total = 0.0
+for i, (name, desc) in enumerate(VARIATIONS[:N], 1):
+ prompt = f"{BASE}; variation: {desc}."
+ pred = sdxl(prompt, SEED_BASE + i * 17)
+ secs = (pred.get("metrics") or {}).get("predict_time", 0) or 0; total += secs
+ if pred.get("status") != "succeeded":
+ print(f"[{i}] {name} FAIL {pred.get('status')}", flush=True); continue
+ out = pred["output"]; url = out[0] if isinstance(out, list) else out
+ fn = f"face_{i:02d}.png"; dest = f"{OUT}/{fn}"
+ urllib.request.urlretrieve(url, dest)
+ designs.append({"n": i, "name": name, "desc": desc, "file": f"/faces/{fn}", "prompt": prompt})
+ print(f"[{i}/{N}] {name} OK {secs:.1f}s", flush=True)
+ time.sleep(0.6)
+
+cost = round(total * 0.000725, 4)
+json.dump({"title": "Tema e Variazioni — our faces", "count": len(designs),
+ "est_cost_usd": cost, "designs": designs}, open(f"{OUT}/manifest.json", "w"), indent=2)
+print(f"\n=== {len(designs)} tiles | est ${cost} ===", flush=True)
diff --git a/whimsical-compare/server.js b/whimsical-compare/server.js
index 36dfb37..936a0b7 100644
--- a/whimsical-compare/server.js
+++ b/whimsical-compare/server.js
@@ -16,7 +16,7 @@ const https = require('https');
const ROOT = __dirname;
const PG = 'postgresql:///dw_unified?host=/tmp';
-const PORT = process.env.PORT || 0; // OS-assigned free port
+const PORT = process.env.PORT || 9793; // stable port for a durable URL
const OURS = path.join(ROOT, 'public', 'ours');
// ---- secrets ----
@@ -54,6 +54,12 @@ function psql(sql) {
});
}
+app.get('/api/faces', (req, res) => {
+ const mf = path.join(ROOT, 'public', 'faces', 'manifest.json');
+ if (!fs.existsSync(mf)) return res.json({ count: 0, designs: [] });
+ res.json(JSON.parse(fs.readFileSync(mf, 'utf8')));
+});
+
app.get('/api/designs', async (req, res) => {
try {
const out = await psql(
← d9bd2b6 fernwick daily drop: 20 settlement-passed originals/day, ran
·
back to Pattern Vault
·
Tema e Variazioni: 20 original b&w face-medallion tiles (our 7a0948d →