[object Object]

← back to Dw Domain Fleet

Add /info page, trim navpanel to 4 items, sun/moon theme toggle

26f2aef016b6a94f9177aca71a3088b51ed39fc6 · 2026-05-19 08:51:30 -0700 · SteveStudio2

TASK 1: New per-site /info page (infoPage in shared/render.js + /info
route in server.js) — Memo Samples, Trade Program, Shipping & Lead
Times, FAQ. cfg-driven, no vendor names, no banned 'wallpaper' word,
rel=canonical to the site's own /info.

TASK 2: Navpanel now exactly 4 items — Designs, About, Info, Contact.

TASK 3: Theme toggle shows a sun in light mode, moon in dark mode —
both SVGs in the button, swapped via CSS keyed on html[data-theme=dark],
no JS change so it survives the anti-flash inline script.

Verified: node -c passes both files; grassclothwallcovering booted on
:10999 — /, /info, /about, /catalog all 200; /info renders all 4
sections; nav shows the 4 items; no 'wallpaper' in /info copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 26f2aef016b6a94f9177aca71a3088b51ed39fc6
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date:   Tue May 19 08:51:30 2026 -0700

    Add /info page, trim navpanel to 4 items, sun/moon theme toggle
    
    TASK 1: New per-site /info page (infoPage in shared/render.js + /info
    route in server.js) — Memo Samples, Trade Program, Shipping & Lead
    Times, FAQ. cfg-driven, no vendor names, no banned 'wallpaper' word,
    rel=canonical to the site's own /info.
    
    TASK 2: Navpanel now exactly 4 items — Designs, About, Info, Contact.
    
    TASK 3: Theme toggle shows a sun in light mode, moon in dark mode —
    both SVGs in the button, swapped via CSS keyed on html[data-theme=dark],
    no JS change so it survives the anti-flash inline script.
    
    Verified: node -c passes both files; grassclothwallcovering booted on
    :10999 — /, /info, /about, /catalog all 200; /info renders all 4
    sections; nav shows the 4 items; no 'wallpaper' in /info copy.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 server.js        |  4 +++
 shared/render.js | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/server.js b/server.js
index 82f57d5..caf7ff4 100644
--- a/server.js
+++ b/server.js
@@ -103,6 +103,10 @@ app.get('/about', (req, res) => {
   res.type('html').send(render.aboutPage(cfg));
 });
 
+app.get('/info', (req, res) => {
+  res.type('html').send(render.infoPage(cfg));
+});
+
 app.get('/health', (req, res) => {
   res.json({ ok: true, site: SITE, domain: cfg.domain, niche: NICHE.length, serving: POOL.length });
 });
diff --git a/shared/render.js b/shared/render.js
index 1259af9..2164980 100644
--- a/shared/render.js
+++ b/shared/render.js
@@ -59,7 +59,11 @@ img{display:block;max-width:100%}
 .navpanel.open{right:0}
 .navpanel a{display:block;padding:13px 0;font-size:14px;letter-spacing:.06em;text-transform:uppercase;
   border-bottom:1px solid rgba(255,255,255,.1)}
-.theme-toggle{background:transparent;border:0;cursor:pointer;color:var(--top-fg,#fff);padding:4px}
+.theme-toggle{background:transparent;border:0;cursor:pointer;color:var(--top-fg,#fff);padding:4px;
+  display:inline-flex;align-items:center}
+.theme-toggle .icon-moon{display:none}
+html[data-theme=dark] .theme-toggle .icon-sun{display:none}
+html[data-theme=dark] .theme-toggle .icon-moon{display:inline-block}
 
 /* hero */
 .cinema{position:relative;width:100%;min-height:clamp(560px,90vh,1080px);overflow:hidden;background:#111}
@@ -141,8 +145,10 @@ function chrome(cfg) {
   <a class="brand" href="/">${esc(cfg.siteName)}</a>
   <div style="display:flex;gap:14px;align-items:center">
     <button class="theme-toggle" id="themeBtn" aria-label="Toggle theme">
-      <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+      <svg class="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
         <circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4"/></svg>
+      <svg class="icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
+        <path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
     </button>
   </div>
 </div>
@@ -151,12 +157,10 @@ function chrome(cfg) {
   <span class="gucci-menu__label">Menu</span>
 </button>
 <nav class="navpanel" id="navpanel">
-  <a href="/">Home</a>
-  <a href="/catalog">Catalog</a>
+  <a href="/catalog">Designs</a>
   <a href="/about">About</a>
-  <a href="${DW}/pages/trade">Trade Program</a>
+  <a href="/info">Info</a>
   <a href="mailto:${esc(cfg.siteEmail)}">Contact</a>
-  <a href="${DW}">Designer Wallcoverings</a>
 </nav>`;
 }
 
@@ -350,6 +354,74 @@ function aboutPage(cfg){
 ${footer(cfg)}${script(cfg)}</body></html>`;
 }
 
+/* ---------- info page ----------
+ * Per-site informational page: memo samples, trade program, shipping &
+ * lead times, and a short FAQ. Driven entirely by cfg so it reads well for
+ * any fleet site. rel=canonical points to this site's own /info.
+ */
+function infoPage(cfg){
+  const title=`Info — ${cfg.siteName}`;
+  const niche=clean(cfg.nicheLabel);
+  const desc=`Memo samples, trade program, shipping and lead times for ${clean(cfg.siteName)} — ${niche} from a Sherman Oaks design house.`;
+  const sec=(h,body)=>`
+  <section style="margin:34px 0;padding-bottom:30px;border-bottom:1px solid var(--rule)">
+    <h2 style="font-family:var(--serif);font-size:clamp(24px,3vw,34px);margin-bottom:12px">${h}</h2>
+    ${body}
+  </section>`;
+  const faq=[
+    ['Do memo samples cost anything?',
+     `No. Memo samples are free and mailed to you so you can judge colour, texture, and scale in your own light before committing.`],
+    ['How many samples can I request?',
+     `Request as many as your project needs. We would rather you see every ${niche} option in person than guess from a screen.`],
+    ['Can you help me choose?',
+     `Yes. Our team hand-holds every order — share your room, lighting, and palette and we will narrow the field with you.`],
+    ['Do you work with designers and architects?',
+     `Absolutely — the trade program below is built for designers, architects, and specifiers.`]
+  ];
+  return head(cfg,title,desc,'/info')+jsonld(cfg)+chrome(cfg)+`
+<div style="height:84px"></div>
+<div class="wrap" style="max-width:820px">
+  <div class="hero-mark" style="padding:40px 0 6px"><h1>Information</h1>
+    <p>${esc(clean(cfg.siteName))} · ${esc(niche)}</p></div>
+
+  ${sec('Memo Samples', `
+    <p style="font-size:16px;line-height:1.8;color:var(--fg)">
+      Every pattern in our catalogue ships with a <strong>free memo sample</strong> — a mailed
+      swatch you can hold against your wall, in your own light, before you order a single roll.
+      Browse the catalogue, request the swatches that interest you, and we will put them in the
+      post. There is no charge and no obligation.</p>
+    <p style="margin-top:16px"><a class="hero-cta__btn" style="position:static;background:var(--accent);color:#fff" href="/catalog">Browse &amp; Request Samples</a></p>`)}
+
+  ${sec('Trade Program', `
+    <p style="font-size:16px;line-height:1.8;color:var(--fg)">
+      Designers, architects, and specifiers receive trade pricing, priority memo-sample
+      handling, and a dedicated point of contact for every project. If you work in the
+      trade, enrol once and the pricing applies across the full ${esc(niche)} collection.</p>
+    <p style="margin-top:14px"><a href="${DW}/pages/trade" rel="noopener noreferrer"
+      style="color:var(--accent);font-weight:500">View the Trade Program &rarr;</a></p>`)}
+
+  ${sec('Shipping &amp; Lead Times', `
+    <p style="font-size:16px;line-height:1.8;color:var(--fg)">
+      Memo samples typically ship within one to two business days. Full orders are made to
+      order — most ${esc(niche)} ship in roughly two to four weeks, though hand-finished and
+      specialty lines can take longer. We confirm the lead time for your specific selection
+      before the order is placed, and our team keeps you posted from selection through
+      delivery and installation. We ship across the United States.</p>`)}
+
+  ${sec('Frequently Asked', faq.map(([q,a])=>`
+    <div style="margin:16px 0">
+      <div style="font-family:var(--serif);font-size:19px;color:var(--fg)">${q}</div>
+      <p style="font-size:15px;line-height:1.75;color:var(--muted);margin-top:5px">${a}</p>
+    </div>`).join(''))}
+
+  <p style="margin:6px 0 60px;font-size:15px;color:var(--muted);line-height:1.8">
+    Still have a question? Email
+    <a href="mailto:${esc(cfg.siteEmail)}" style="color:var(--accent)">${esc(cfg.siteEmail)}</a>
+    and a real person will answer.</p>
+</div>
+${footer(cfg)}${script(cfg)}</body></html>`;
+}
+
 function footer(cfg){
   return `<footer><div class="wrap">
   <div><div class="fb">${esc(cfg.siteName)}</div>
@@ -479,4 +551,4 @@ ${script(cfg)}
 </body></html>`;
 }
 
-module.exports = { homePage, catalogPage, aboutPage, productPage, clean, esc };
+module.exports = { homePage, catalogPage, aboutPage, infoPage, productPage, clean, esc };

← 40eaabd DNS cutover batch 4 (idx 27-35): 9/9 live HTTPS 200  ·  back to Dw Domain Fleet  ·  DNS cutover batch 5 (idx 36-43): 8/8 live HTTPS 200 — fleet 8b73567 →