wireframe

Produce low-fidelity black-and-white UI wireframes as SVGs or viewer pages. Use when asked to wireframe, sketch a screen, draft a layout, make a low-fi mockup, or publish wireframes.

  • design
  • wireframe
  • ux
  • prototyping
  • svg
Install
npx skills add 'https://github.com/paperclipai/paperclip/tree/master/packages/skills-catalog/catalog/bundled/product/wireframe'
Download bundle ↓
master · 5b913e7Scanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md
<!doctype html><!--  Wireframe review viewer — copy to design/<task-slug>/index.html and fill in.  House style: monochrome, system font, 8px grid, sticky TOC, lightbox.  Replace TODO markers; duplicate <section class="screen"> per wireframe.--><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>TODO — review viewer title</title><style>  :root {    --bg: #fafaf8;    --panel: #ffffff;    --ink: #111111;    --muted: #666666;    --line: #e5e5e0;    --accent: #d33;    --maxw: 1200px;  }  * { box-sizing: border-box; }  html, body { margin: 0; padding: 0; }  body {    font: 15px/1.55 -apple-system, system-ui, "Segoe UI", sans-serif;    background: var(--bg);    color: var(--ink);    -webkit-font-smoothing: antialiased;  }  a { color: inherit; }   .shell { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }   .toc {    position: sticky; top: 0; align-self: start;    height: 100vh; overflow: auto;    padding: 24px 16px 24px 24px;    border-right: 1px solid var(--line);    background: var(--panel);    font-size: 13px;    z-index: 20;  }  .toc h1 { font-size: 14px; margin: 0 0 4px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); }  .toc h2 { font-size: 12px; margin: 24px 0 6px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); font-weight: 700; }  .toc a { display: block; text-decoration: none; padding: 6px 8px; margin-left: -8px; border-radius: 4px; color: var(--ink); }  .toc a:hover { background: var(--bg); }  .toc .num { display: inline-block; width: 22px; color: var(--muted); }  .toc .toc-summary { display: none; }  .toc .toc-body { display: block; }   main { padding: 48px 56px 96px; max-width: 1300px; min-width: 0; }   header.hero { max-width: var(--maxw); margin-bottom: 64px; }  header.hero .crumb { color: var(--muted); font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; }  header.hero h1 { font-size: 36px; line-height: 1.15; margin: 8px 0 16px; }  header.hero p { color: var(--muted); max-width: 720px; font-size: 16px; }  header.hero .pills { margin-top: 20px; display: flex; gap: 8px; flex-wrap: wrap; }  header.hero .pill { font-size: 12px; padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); color: var(--muted); }   section { scroll-margin-top: 24px; max-width: var(--maxw); margin-bottom: 96px; }  section .lede { color: var(--muted); margin: 0 0 12px; font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; font-weight: 700; }  section h2 { font-size: 28px; line-height: 1.2; margin: 0 0 8px; }  section h2 .step-num { display: inline-block; width: 40px; color: var(--muted); }  section h3 { font-size: 16px; margin: 24px 0 8px; }  section .desc { color: var(--muted); margin: 0 0 24px; max-width: 760px; }   /* canvas: desktop wire (wide) on left, mobile wire (tall narrow) middle, notes right.     Mobile is a first-class deliverable — never tabbed, never stacked away. */  .grid {    display: grid; gap: 24px;    grid-template-columns: minmax(0, 1.4fr) 220px minmax(0, 0.9fr);    align-items: start;  }  @media (max-width: 1180px) {    .grid { grid-template-columns: minmax(0, 1fr) 200px; }    .grid > .notes-col { grid-column: 1 / -1; }  }  @media (max-width: 980px) { .grid { grid-template-columns: 1fr; } .grid > .mobile-col { max-width: 280px; } }   /* tablet */  @media (max-width: 900px) {    .shell { grid-template-columns: 1fr; }    .toc {      position: sticky; top: 0;      height: auto; max-height: 60vh;      padding: 12px 16px;      border-right: none;      border-bottom: 1px solid var(--line);    }    .toc .toc-summary {      display: flex;      justify-content: space-between;      align-items: center;      cursor: pointer;      list-style: none;      padding: 4px 0;    }    .toc .toc-summary::-webkit-details-marker { display: none; }    .toc .toc-summary .title { font-size: 13px; font-weight: 600; }    .toc .toc-summary .crumb { font-size: 11px; color: var(--muted); letter-spacing: 0.04em; text-transform: uppercase; }    .toc .toc-summary .chevron {      width: 10px; height: 10px;      border-right: 1.5px solid var(--ink);      border-bottom: 1.5px solid var(--ink);      transform: rotate(45deg);      transition: transform 120ms ease;      margin-right: 4px;    }    .toc[open] .toc-summary .chevron { transform: rotate(225deg) translate(-2px, -2px); }    .toc .toc-body { display: none; padding-top: 8px; border-top: 1px solid var(--line); margin-top: 8px; }    .toc[open] .toc-body { display: block; }    main { padding: 24px 20px 64px; }    header.hero { margin-bottom: 40px; }    header.hero h1 { font-size: 28px; }    header.hero p { font-size: 15px; }    section { margin-bottom: 64px; scroll-margin-top: 80px; }    section h2 { font-size: 24px; }    section h2 .step-num { width: 32px; }    .flow-section { padding: 20px; margin-bottom: 40px; scroll-margin-top: 80px; }  }   /* phone */  @media (max-width: 560px) {    main { padding: 16px 14px 56px; }    header.hero { margin-bottom: 32px; }    header.hero h1 { font-size: 24px; line-height: 1.2; }    header.hero p { font-size: 14px; }    section { margin-bottom: 48px; }    section h2 { font-size: 20px; line-height: 1.25; }    section h2 .step-num { width: 28px; }    section h3 { font-size: 15px; margin: 20px 0 6px; }    section .desc { font-size: 14px; }    .grid { gap: 16px; }    .flow-section { padding: 16px; border-radius: 8px; }    .wire .label { padding: 8px 10px; font-size: 11px; gap: 8px; }    body { font-size: 14px; }  }   .wire {    background: var(--panel);    border: 1px solid var(--line);    border-radius: 8px;    overflow: hidden;    cursor: zoom-in;    transition: transform 80ms ease, box-shadow 80ms ease;  }  .wire:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.08); }  .wire .label {    padding: 10px 14px;    font-size: 12px;    color: var(--muted);    border-bottom: 1px solid var(--line);    display: flex; justify-content: space-between; align-items: center;  }  .wire img { display: block; width: 100%; height: auto; background: #fff; }  /* mobile wire renders narrow inside its 220px column so it reads as a phone */  .wire.mobile-wire img { max-width: 220px; margin: 0 auto; }   .ref {    background: var(--panel);    border: 1px solid var(--line);    border-radius: 8px;    padding: 14px;  }  .ref .label { font-size: 12px; color: var(--muted); margin-bottom: 8px; display: flex; justify-content: space-between; align-items: baseline; }  .ref img { display: block; width: 100%; height: auto; border: 1px solid var(--line); border-radius: 4px; cursor: zoom-in; }   .notes ul { padding-left: 20px; margin: 8px 0; }  .notes li { margin-bottom: 6px; }  .notes .why {    background: var(--panel);    border: 1px solid var(--line);    border-left: 3px solid var(--ink);    padding: 14px 18px;    border-radius: 4px;    margin-top: 12px;    font-size: 14px;  }   .flow-section { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 32px; margin-bottom: 64px; max-width: var(--maxw); }  .flow-section h2 { margin-top: 0; }  .flow-section .wire { margin-top: 16px; }   /* lightbox */  .lightbox {    position: fixed; inset: 0;    background: rgba(0,0,0,0.86);    display: none;    align-items: center; justify-content: center;    z-index: 100;    cursor: zoom-out;    padding: 32px;  }  .lightbox.open { display: flex; }  .lightbox img { max-width: 100%; max-height: 100%; background: #fff; box-shadow: 0 30px 80px rgba(0,0,0,0.4); border-radius: 4px; }  .lightbox .close { position: absolute; top: 16px; right: 24px; font-size: 28px; color: #fff; cursor: pointer; }  .lightbox .caption { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); color: #fff; font-size: 13px; opacity: 0.9; }   /* mobile lightbox — must come after the desktop rules to win the cascade */  @media (max-width: 560px) {    .lightbox { padding: 12px; overflow: auto; touch-action: pinch-zoom; }    .lightbox.open { display: block; }    .lightbox img { display: block; width: 100%; max-width: none; max-height: none; height: auto; margin: 40px auto 56px; box-shadow: none; }    .lightbox .close { position: fixed; top: 8px; right: 12px; font-size: 32px; }    .lightbox .caption { position: fixed; left: 50%; transform: translateX(-50%); font-size: 12px; bottom: 12px; text-align: center; background: rgba(0,0,0,0.7); border-radius: 4px; padding: 6px 12px; }  }   .footer { color: var(--muted); font-size: 12px; max-width: var(--maxw); border-top: 1px solid var(--line); padding-top: 24px; }</style></head><body>  <div class="shell">    <details class="toc">      <summary class="toc-summary">        <span>          <span class="crumb">TODO-ID · TODO short title</span><br>          <span class="title">Jump to a screen</span>        </span>        <span class="chevron" aria-hidden="true"></span>      </summary>      <nav class="toc-body" aria-label="Section navigation">        <h1>TODO-ID</h1>        <div style="font-size: 13px; color: var(--muted); margin-bottom: 16px;">TODO short title</div>         <h2>Flow</h2>        <a href="#flow"><span class="num">⤳</span>Flow diagram</a>         <h2>Screens</h2>        <a href="#s1"><span class="num">1</span>TODO screen 1 name</a>        <!-- duplicate per screen -->         <h2>Open questions</h2>        <a href="#open"><span class="num">?</span>For reviewer</a>      </nav>    </details>     <main>      <header class="hero">        <div class="crumb">TODO-ID · Wireframes</div>        <h1>TODO — long title</h1>        <p>TODO — one-paragraph summary of what this set covers and why.</p>        <div class="pills">          <span class="pill">TODO N screens</span>          <span class="pill">Desktop + mobile</span>          <span class="pill">Lo-fi · monochrome</span>          <span class="pill">Click any wireframe to zoom</span>        </div>      </header>       <!-- ========== Flow diagram (optional) ========== -->      <section id="flow" class="flow-section">        <div class="lede">Flow</div>        <h2>TODO — flow title</h2>        <p class="desc">TODO — describe arrow conventions (solid = happy path, dashed = branch).</p>        <div class="wire" data-zoom data-caption="Flow diagram">          <div class="label"><span>flow.svg</span><span>TODO WxH</span></div>          <img src="wireframes/flow.svg" alt="Flow diagram" />        </div>      </section>       <!-- ========== Screen template — duplicate per screen ==========           Three cells per row: desktop wire | mobile wire | notes-col.           Mobile is mandatory; only drop it when the user explicitly opted out. -->      <section id="s1">        <div class="lede">Step 1 · TODO group</div>        <h2><span class="step-num">1.</span>TODO screen name</h2>        <p class="desc">TODO — one-paragraph describing the screen's purpose.</p>        <div class="grid">          <div class="wire" data-zoom data-caption="01 · TODO screen name (desktop)">            <div class="label"><span>01-screen.svg</span><span>1280×800 · desktop</span></div>            <img src="wireframes/01-screen.svg" alt="TODO screen name (desktop) wireframe" />          </div>          <div class="wire mobile-wire mobile-col" data-zoom data-caption="01 · TODO screen name (mobile)">            <div class="label"><span>mobile</span><span>375×812</span></div>            <img src="wireframes/01-screen-mobile.svg" alt="TODO screen name (mobile) wireframe" />          </div>          <div class="notes-col">            <!-- Optional reference (real-world example we're modelling) -->            <div class="ref">              <div class="label"><span>Reference</span><span>TODO source</span></div>              <img src="screenshots/TODO-ref.png" alt="TODO reference" data-zoom />            </div>            <div class="notes">              <h3>Annotations</h3>              <ul>                <li><b>1</b> — TODO callout 1.</li>                <li><b>2</b> — TODO callout 2 (note where mobile diverges).</li>              </ul>              <div class="why"><b>Why this changes:</b> TODO rationale vs current state.</div>            </div>          </div>        </div>      </section>       <!-- ========== Open questions ========== -->      <section id="open">        <div class="lede">For reviewer</div>        <h2>Open questions</h2>        <div class="notes">          <ul>            <li><b>TODO</b> — Open question 1.</li>          </ul>        </div>      </section>       <div class="footer">        Wireframes follow the in-tree <code>wireframe</code> skill house style — black on white, 1.5pt strokes, 8px grid, type sizes 12/14/20/28. Red dashed annotations are the call-out layer only and not part of the proposed UI.      </div>    </main>  </div>   <div class="lightbox" id="lb" aria-hidden="true">    <span class="close" id="lbClose">×</span>    <img id="lbImg" alt="" />    <div class="caption" id="lbCap"></div>  </div> <script>  // Click-to-zoom: any element marked [data-zoom] OR any <img> inside [data-zoom]  const lb = document.getElementById('lb');  const lbImg = document.getElementById('lbImg');  const lbCap = document.getElementById('lbCap');  const lbClose = document.getElementById('lbClose');   document.querySelectorAll('[data-zoom]').forEach((el) => {    el.addEventListener('click', () => {      const target = el.tagName === 'IMG' ? el : el.querySelector('img');      if (!target) return;      lbImg.src = target.src;      lbImg.alt = target.alt;      lbCap.textContent = el.dataset.caption || target.alt || '';      lb.classList.add('open');    });  });   function close() { lb.classList.remove('open'); }  lb.addEventListener('click', close);  lbClose.addEventListener('click', close);  document.addEventListener('keydown', (e) => { if (e.key === 'Escape') close(); });   // TOC: open by default on desktop (<details> would otherwise hide body),  // closed by default on mobile so the long list doesn't dominate the viewport.  const toc = document.querySelector('details.toc');  if (toc) {    const mq = window.matchMedia('(max-width: 900px)');    const apply = () => { toc.open = !mq.matches; };    apply();    mq.addEventListener('change', apply);    // On mobile, collapse the TOC after the user taps a link.    toc.querySelectorAll('.toc-body a').forEach((a) => {      a.addEventListener('click', () => { if (mq.matches) toc.open = false; });    });  }</script></body></html> 
Referenced from SKILL.md