[object Object]

← back to Dw Marketing Viewer

Add brand avatars (navy/honey/chamois) + serve statically + avatar picker UI; launchd auto-start

210affff8bef31c707bb0798e015330c75abb9c3 · 2026-06-23 12:39:49 -0700 · Steve

Files touched

Diff

commit 210affff8bef31c707bb0798e015330c75abb9c3
Author: Steve <steve@designerwallcoverings.com>
Date:   Tue Jun 23 12:39:49 2026 -0700

    Add brand avatars (navy/honey/chamois) + serve statically + avatar picker UI; launchd auto-start
---
 avatars/avatar-chamois.png | Bin 0 -> 186508 bytes
 avatars/avatar-honey.png   | Bin 0 -> 268672 bytes
 avatars/avatar-navy.png    | Bin 0 -> 147821 bytes
 avatars/avatar-options.jpg | Bin 0 -> 103199 bytes
 server.js                  |  29 +++++++++++++++++++++++++++--
 5 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/avatars/avatar-chamois.png b/avatars/avatar-chamois.png
new file mode 100644
index 0000000..d9c29a6
Binary files /dev/null and b/avatars/avatar-chamois.png differ
diff --git a/avatars/avatar-honey.png b/avatars/avatar-honey.png
new file mode 100644
index 0000000..6651ccf
Binary files /dev/null and b/avatars/avatar-honey.png differ
diff --git a/avatars/avatar-navy.png b/avatars/avatar-navy.png
new file mode 100644
index 0000000..7665cab
Binary files /dev/null and b/avatars/avatar-navy.png differ
diff --git a/avatars/avatar-options.jpg b/avatars/avatar-options.jpg
new file mode 100644
index 0000000..ce38290
Binary files /dev/null and b/avatars/avatar-options.jpg differ
diff --git a/server.js b/server.js
index e829e4e..fce6429 100644
--- a/server.js
+++ b/server.js
@@ -2,7 +2,11 @@
 // DW Marketing — Wallpaper's Back social command viewer
 // Style matches dw-staged-active-viewer (:9846). Zero deps (raw http).
 const http = require('http');
+const fs = require('fs');
+const path = require('path');
 const PORT = process.env.PORT || 9847;
+const AVATAR_DIR = path.join(__dirname, 'avatars');
+const DEFAULT_AVATAR = '/avatars/avatar-navy.png';
 
 const WPB = 'https://wallpapersback.com';
 const IMG = '/designs/img/';
@@ -53,7 +57,7 @@ function page(){
   const accCards = ACCOUNTS.map(a=>`
     <div class="card acct">
       <div class="ahd">
-        <span class="plat">${a.icon} ${esc(a.platform)}</span>
+        <span class="plat"><img class="av" src="${DEFAULT_AVATAR}" alt="">${a.icon} ${esc(a.platform)}</span>
         <span class="pill ${a.status}">${a.status}</span>
       </div>
       <a class="handle" href="${a.url}" target="_blank" rel="noopener noreferrer">@${esc(a.handle)}</a>
@@ -92,7 +96,14 @@ function page(){
   @media(max-width:820px){.grid{grid-template-columns:1fr;}}
   .card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:12px 13px;display:flex;flex-direction:column;gap:8px;}
   .ahd{display:flex;justify-content:space-between;align-items:center;}
-  .plat{font-weight:650;font-size:14px;}
+  .plat{font-weight:650;font-size:14px;display:flex;align-items:center;gap:8px;}
+  .av{width:30px;height:30px;border-radius:50%;object-fit:cover;border:1px solid var(--line);}
+  .avopts{display:flex;gap:16px;align-items:center;margin:14px 0 2px;}
+  .avopt{display:flex;flex-direction:column;align-items:center;gap:5px;}
+  .avopt img{width:84px;height:84px;border-radius:50%;object-fit:cover;border:2px solid var(--line);}
+  .avopt.pick img{border-color:var(--accent);}
+  .avopt span{font-size:11px;color:var(--mut);}
+  .avlbl{color:var(--mut);font-size:12px;font-weight:600;}
   .pill{font-size:10px;border-radius:5px;padding:1px 7px;text-transform:uppercase;font-weight:700;letter-spacing:.04em;}
   .pill.live{color:#9be59b;border:1px solid #1f5c17;background:#122a12;}
   .pill.ready{color:#ffd479;border:1px solid #5c4a17;background:#241d0a;}
@@ -133,6 +144,12 @@ function page(){
       <span>📱 <b>${SHARED.phone}</b></span>
       <span>🎂 ${SHARED.dob}</span>
     </div>
+    <div class="avopts">
+      <span class="avlbl">Brand avatar:</span>
+      <div class="avopt pick"><img src="/avatars/avatar-navy.png" alt=""><span>navy ✓</span></div>
+      <div class="avopt"><img src="/avatars/avatar-honey.png" alt=""><span>honey</span></div>
+      <div class="avopt"><img src="/avatars/avatar-chamois.png" alt=""><span>chamois</span></div>
+    </div>
     <div class="projnote">Passwords stored in secrets registry (WPB_* keys) — shown as last-4 only.</div>
   </section>
   <section id="carousel">
@@ -166,6 +183,14 @@ function page(){
 
 http.createServer((req,res)=>{
   if(req.url==='/healthz'){res.writeHead(200,{'Content-Type':'text/plain'});return res.end('ok');}
+  if(req.url.startsWith('/avatars/')){
+    const f=path.join(AVATAR_DIR, path.basename(req.url));
+    if(f.startsWith(AVATAR_DIR) && fs.existsSync(f)){
+      res.writeHead(200,{'Content-Type':'image/png','Cache-Control':'no-cache'});
+      return res.end(fs.readFileSync(f));
+    }
+    res.writeHead(404); return res.end('not found');
+  }
   res.writeHead(200,{'Content-Type':'text/html; charset=utf-8'});
   res.end(page());
 }).listen(PORT,'127.0.0.1',()=>console.log('DW Marketing viewer → http://127.0.0.1:'+PORT+'/'));

← 6c52858 Trim TikTok bio to <=80 chars; flag bio overflow in red  ·  back to Dw Marketing Viewer  ·  Auto-fit avatar wordmark inside circular safe-area (was clip 9c7f426 →