← back to Pattern Vault
public/handoff.html
94 lines
<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Pattern Vault — Manual Handoff</title>
<style>
:root{--bg:#0d0b10;--card:#17141d;--ink:#efe9f7;--mut:#9a8fb0;--gold:#d4af6a;--line:#2a2436;--good:#37d67a}
*{box-sizing:border-box;margin:0}body{background:var(--bg);color:var(--ink);font:14px/1.5 "Avenir Next",system-ui,sans-serif}
header{padding:34px 6vw 12px}h1{font-size:26px;letter-spacing:.1em;text-transform:uppercase}h1 em{color:var(--gold);font-style:normal}
.sub{color:var(--mut);margin-top:6px}
h2{font-size:15px;letter-spacing:.08em;text-transform:uppercase;color:var(--gold);margin:26px 6vw 10px;padding-top:20px;border-top:1px solid var(--line)}
.steps{padding:0 6vw;display:grid;gap:10px}
.step{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:14px 16px;display:flex;gap:14px;align-items:flex-start}
.num{flex:0 0 26px;height:26px;border-radius:50%;background:#221a33;color:var(--gold);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px}
.step .t{font-weight:600}.step .d{color:var(--mut);font-size:13px;margin-top:2px}
.step a.btn{display:inline-block;margin-top:8px;background:var(--gold);color:#1a1206;padding:7px 14px;border-radius:8px;font-weight:600;text-decoration:none;font-size:13px}
.step a.btn.sec{background:transparent;color:var(--gold);border:1px solid var(--gold)}
.tools{padding:6px 6vw 0;display:flex;gap:10px;flex-wrap:wrap}
.tools button{background:#221a33;color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:9px 14px;cursor:pointer;font-size:13px}
.tools button:hover{border-color:var(--gold);color:var(--gold)}
.grid{padding:10px 6vw 60px;display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}
.dcard{background:var(--card);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.dcard img{width:100%;aspect-ratio:1;object-fit:cover;display:block}
.dpad{padding:12px 14px}.dpad .dt{font-weight:600}.dpad .ds{color:var(--mut);font-size:12px;margin:4px 0 10px;min-height:32px}
.row{display:flex;gap:6px;flex-wrap:wrap}
.row button,.row a{font-size:11.5px;padding:5px 9px;border-radius:7px;border:1px solid var(--line);background:transparent;color:var(--ink);cursor:pointer;text-decoration:none}
.row button:hover,.row a:hover{border-color:var(--gold);color:var(--gold)}
.copied{color:var(--good)!important;border-color:var(--good)!important}
.pill{font-size:11px;color:var(--gold);border:1px solid var(--gold);border-radius:99px;padding:2px 8px;display:inline-block;margin-bottom:8px}
</style></head><body>
<header><h1>Pattern Vault — <em>Manual Handoff</em></h1>
<div class="sub">Everything that needs YOU (accounts + uploads). The designs, print masters, and paste-ready copy are done — this page hands them to you in one place.</div>
<div style="margin-top:12px;padding:10px 14px;background:#160f22;border:1px solid var(--gold);border-radius:10px;font-size:13px">
<b style="color:var(--gold)">Uploads account (seller):</b> <b>info@designerwallcoverings.com</b> · <span style="color:var(--mut)">all future uploads land here. info@printmurals.com (Fernwick Studio, handle fernwickstudio) is now a <b>designer persona</b>, not the upload target — its 24-design batch stays as the initial record.</span></div></header>
<h2>① Accounts & signups (one-time)</h2>
<div class="steps">
<div class="step"><div class="num">1</div><div><div class="t">Spoonflower — recommended first (you already have a login)</div>
<div class="d">Log in with your existing <b>info@designerwallcoverings.com</b> account → Sell → Upload. The 14 tiles are print-clean 4096px masters; use the copy below. ~10–15% commission, passive after upload.</div>
<a class="btn" href="https://www.spoonflower.com/login" target="_blank" rel="noopener">Open Spoonflower login →</a>
<a class="btn sec" href="https://www.spoonflower.com/designs/new" target="_blank" rel="noopener">Upload a design →</a></div></div>
<div class="step"><div class="num">2</div><div><div class="t">Etsy — own the customer (~$0.20/listing)</div>
<div class="d">Create/confirm a seller account, then paste each listing (copy below).</div>
<a class="btn" href="https://www.etsy.com/sell" target="_blank" rel="noopener">Etsy — start selling →</a></div></div>
<div class="step"><div class="num">3</div><div><div class="t">Stripe (AbramsEgo account) — to sell licenses on the Vault itself</div>
<div class="d">Create the dedicated AbramsEgo Stripe account, then paste me the <b>sk_test_</b> key (I verify a 4242 checkout) before any live key.</div>
<a class="btn" href="https://dashboard.stripe.com/register" target="_blank" rel="noopener">Register Stripe →</a></div></div>
</div>
<h2>② Affiliate programs (paste your links back to me)</h2>
<div class="steps">
<div class="step"><div class="num">4</div><div><div class="t">Join any — then send me the referral URLs</div>
<div class="row" style="margin-top:8px">
<a href="https://www.digitalocean.com/referral-program" target="_blank" rel="noopener">DigitalOcean</a>
<a href="https://www.hetzner.com/referral-program" target="_blank" rel="noopener">Hetzner</a>
<a href="https://betterstack.com/affiliate" target="_blank" rel="noopener">Better Stack</a>
<a href="https://www.vultr.com/company/referral-program/" target="_blank" rel="noopener">Vultr</a>
<a href="https://elevenlabs.io/affiliates" target="_blank" rel="noopener">ElevenLabs</a></div></div></div>
</div>
<h2>③ The 14 designs — masters + paste-ready copy</h2>
<div class="tools">
<button onclick="dlCSV()">⬇ Download all listings (CSV)</button>
<button onclick="dlAllMasters()">⬇ Open all 14 print masters</button>
<span style="color:var(--mut);font-size:12px;align-self:center">Click any field to copy it to your clipboard.</span>
</div>
<div class="grid" id="grid">loading…</div>
<script>
let ITEMS=[];
const master=d=>'/assets/masters/'+d.img.split('/').pop().replace('.webp','')+'_4x.png';
const tagsOf=d=>{const b=(d.styleLine||'').split('—')[0].trim().toLowerCase();
return [...b.split(' ').filter(w=>w.length>3).slice(0,4),'seamless pattern','wallpaper','original design','repeat pattern','surface design','print ready','removable wallpaper','peel and stick'].slice(0,13).join(', ')};
const descOf=d=>(d.styleLine||'')+' Seam-verified seamless repeat, print-clean. Digital single-use license included; commercial + exclusive available. Original — never a copy.';
function copy(el,txt){navigator.clipboard.writeText(txt).then(()=>{const o=el.textContent;el.textContent='✓ copied';el.classList.add('copied');setTimeout(()=>{el.textContent=o;el.classList.remove('copied')},1200)})}
function render(){document.getElementById('grid').innerHTML=ITEMS.map((d,i)=>`
<div class="dcard"><img loading="lazy" src="${d.img}" alt="${d.title}">
<div class="dpad"><span class="pill">✦ #${i+1}</span><div class="dt">${d.title}</div><div class="ds">${d.styleLine||''}</div>
<div class="row">
<button onclick="copy(this,${JSON.stringify(d.title).replace(/"/g,'"')})">Copy title</button>
<button onclick='copy(this,DESC[${i}])'>Copy description</button>
<button onclick='copy(this,TAGS[${i}])'>Copy tags</button>
<a href="${master(d)}" download target="_blank">⬇ Master (4096px)</a>
</div></div></div>`).join('')}
let DESC=[],TAGS=[];
function dlCSV(){let rows=[['title','description','tags','digital_price','commercial_price','master']];
ITEMS.forEach(d=>{const t=d.licenseTiers||[];const dg=(t.find(x=>x.tier==='digital_single_use')||{}).priceUsd||149;const cm=(t.find(x=>x.tier==='commercial_print')||{}).priceUsd||495;
rows.push([d.title,descOf(d),tagsOf(d),dg,cm,master(d)])});
const csv=rows.map(r=>r.map(c=>'"'+String(c).replace(/"/g,'""')+'"').join(',')).join('\n');
const a=document.createElement('a');a.href=URL.createObjectURL(new Blob([csv],{type:'text/csv'}));a.download='pattern-vault-listings.csv';a.click()}
function dlAllMasters(){ITEMS.forEach((d,i)=>setTimeout(()=>window.open(master(d),'_blank'),i*250))}
(async()=>{const r=await fetch('/api/catalog');const j=await r.json();
ITEMS=(j.items||[]).filter(x=>x.category==='in-house-original');
DESC=ITEMS.map(descOf);TAGS=ITEMS.map(tagsOf);render()})();
</script></body></html>