skill
Adom SF Convert
Public Made by Adomby adom
Native Rust converter: EAGLE/Fusion .lbr + Altium .SchLib/.PcbLib → KiCad, rendering each format's own geometry.
← Commit history
Hero v6: rendered the canonical way via adom-wiki-hero build-variants.js (bottom x pcb); commit generator source for reproducibility
3 files changed
+168−2
adom-sfconvert-hero-v6.pngadded⋯ 1 unchanged line ⋯
hero-build-variants.jsadded+166@@ -0,0 +1,166 @@+// build-variants.js — generate adom-wiki-hero heroes across two axes: LAYOUT × THEME.+// Usage:+// node build-variants.js -> writes the curated showcase set (see COMBOS)+// node build-variants.js <layout> <theme> -> one hero, e.g. "bleedRight pcb"+// node build-variants.js name <comboName> -> one named combo from COMBOS+// LAYOUTS: bottom | mirror | bleedRight | contained+// THEMES: midnight | pcb | onion | pill | gradient+// Brand assets (fonts, wordmark, Kickstand tiles) are bundled under assets/, referenced relatively.+const fs = require('fs');+const path = require('path');+const DIR = __dirname;++const WORDMARK = fs.readFileSync(path.join(DIR, 'assets', 'adom-white.svg'), 'utf8')+ .replace(/<\?xml[^>]*\?>/, '').replace(/<style>[\s\S]*?<\/style>/, '').replace(/class="cls-1"/g, 'fill="#fff"');++// recolor a currentColor tile SVG and return a CSS background data-URI+function tile(name, color) {+ const svg = fs.readFileSync(path.join(DIR, 'assets', 'tiling', name), 'utf8').replace(/currentColor/g, color);+ return `url("data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}")`;+}++// ---- content (adom-sfconvert hero) ----+const C = {+ headline: 'EAGLE, Fusion 360<br>& Altium <span class="accent">→ KiCad</span>',+ sub: 'Converts EAGLE/Fusion <b>.lbr</b> and Altium <b>.SchLib/.PcbLib</b> <b>into</b> KiCad — each format rendered from its <b>own geometry</b> as a native SVG. No KiCad install.',+ chip: 'SF Convert', prompt: 'convert this EAGLE .lbr to KiCad',+ url: 'wiki.adom.inc/adom/adom-sfconvert',+ winlabel: 'adom-sfconvert · ADS1263 footprint · four-source compare · Adom webview',+ shot: 'file:///tmp/herowork2/shot.png',+};++// ---- THEMES: background + texture overlay + text colors ----+const THEMES = {+ midnight: {+ bg: `radial-gradient(1200px 800px at 88% -10%, rgba(0,184,177,.22), transparent 60%),+ radial-gradient(900px 700px at -5% 110%, rgba(140,107,247,.18), transparent 55%),+ linear-gradient(155deg,#0a0e14 0%,#0d1117 45%,#071318 100%)`,+ tex: `background:${tile('dot-grid.svg', '#ffffff')} 0 0/24px repeat;opacity:.05;+ -webkit-mask-image:linear-gradient(115deg,transparent 0%,#000 48%);mask-image:linear-gradient(115deg,transparent 0%,#000 48%)`,+ text: '#e6edf3', sub: '#aeb8c4', chipB: 'rgba(0,184,177,.34)', chipF: 'rgba(0,184,177,.07)', chipT: '#7fe3dd', accent: true,+ },+ // PCB traces — Kickstand "ethereal circuit field" on deep brand teal+ pcb: {+ bg: `radial-gradient(1000px 760px at 86% -5%, rgba(0,184,177,.28), transparent 60%),+ linear-gradient(160deg,#022a2b 0%,#003c3f 46%,#021a1c 100%)`,+ tex: `background:${tile('pcb-trace.svg', '#8FD3D4')} center/170px repeat;opacity:.16;+ -webkit-mask-image:linear-gradient(115deg,transparent 6%,#000 52%);mask-image:linear-gradient(115deg,transparent 6%,#000 52%)`,+ text: '#eafdfb', sub: '#a9d6d2', chipB: 'rgba(143,211,212,.40)', chipF: 'rgba(0,184,177,.10)', chipT: '#8fd3d4', accent: true,+ },+ // Onion corner — signature concentric-arc motif on solid navy (deck "substance" slide)+ onion: {+ bg: `radial-gradient(900px 700px at 80% -10%, rgba(100,171,255,.16), transparent 60%),+ linear-gradient(160deg,#021a36 0%,#00204f 50%,#01122b 100%)`,+ tex: `background:${tile('onion-corner.svg', '#8FD3D4')} right bottom/62% no-repeat;opacity:.5`,+ text: '#eaf2ff', sub: '#a9c0e0', chipB: 'rgba(100,171,255,.40)', chipF: 'rgba(100,171,255,.10)', chipT: '#9fc4ff', accent: true,+ },+ // Pill field on navy+ pill: {+ bg: `radial-gradient(900px 700px at 85% 0%, rgba(100,171,255,.18), transparent 60%),+ linear-gradient(160deg,#001a3f 0%,#00204f 50%,#001129 100%)`,+ tex: `background:${tile('pill-field.svg', '#64ABFF')} center/64px repeat;opacity:.5;+ -webkit-mask-image:linear-gradient(115deg,transparent 4%,#000 50%);mask-image:linear-gradient(115deg,transparent 4%,#000 50%)`,+ text: '#eaf2ff', sub: '#a9c0e0', chipB: 'rgba(100,171,255,.40)', chipF: 'rgba(100,171,255,.10)', chipT: '#9fc4ff', accent: true,+ },+ // Brand gradient — the "wow"/cover-slide look; left scrim keeps copy readable+ gradient: {+ bg: `linear-gradient(90deg, rgba(5,8,12,.82) 0%, rgba(5,8,12,.42) 42%, rgba(5,8,12,.08) 70%),+ radial-gradient(800px 600px at 90% 0%, rgba(255,255,255,.12), transparent 55%),+ linear-gradient(115deg,#00b8b1 0%,#0061ef 52%,#8c6bf7 100%)`,+ tex: ``,+ text: '#ffffff', sub: '#d7e2ee', chipB: 'rgba(255,255,255,.40)', chipF: 'rgba(255,255,255,.10)', chipT: '#ffffff', accent: true,+ },+};++// ---- LAYOUTS: window position/shape + text side ----+const LAYOUTS = {+ bottom: { side: 'left', win: 'right:72px;top:280px;width:806px;border-radius:16px 16px 0 0', imgH: 760 },+ mirror: { side: 'right', win: 'left:72px;top:280px;width:806px;border-radius:16px 16px 0 0', imgH: 760 },+ bleedRight: { side: 'left', win: 'right:-74px;top:104px;width:900px;border-radius:16px 0 0 16px', imgH: 812 },+ contained: { side: 'left', win: 'right:80px;top:150px;width:752px;border-radius:16px', imgH: 672 },+};++function html(L, T) {+ const left = L.side === 'left';+ return `<!DOCTYPE html><html><head><meta charset="utf-8">+<style>+@font-face{font-family:'Familjen Grotesk';font-weight:700;font-display:block;src:url('assets/fonts/familjen-grotesk-700-normal.woff2') format('woff2')}+@font-face{font-family:'Satoshi';font-weight:400;font-display:block;src:url('assets/fonts/satoshi-400-normal.woff2') format('woff2')}+@font-face{font-family:'Satoshi';font-weight:500;font-display:block;src:url('assets/fonts/satoshi-500-normal.woff2') format('woff2')}+*{margin:0;padding:0;box-sizing:border-box}+html,body{width:1600px;height:1000px;overflow:hidden}+body{font-family:'Satoshi',sans-serif;color:${T.text};position:relative;background:${T.bg};}+.tex{position:absolute;inset:0;z-index:0;${T.tex}}+.zone{position:absolute;inset:0;padding:80px 92px 0;z-index:3;display:flex;flex-direction:column}+.top{display:flex;align-items:flex-start;justify-content:space-between}+.wordmark svg{height:44px;width:auto;display:block}+.chip{border:1px solid ${T.chipB};background:${T.chipF};border-radius:999px;padding:9px 17px;font-size:14px;+ letter-spacing:2.5px;text-transform:uppercase;color:${T.chipT};display:inline-flex;align-items:center;gap:9px;font-weight:600}+.chip .dot{width:8px;height:8px;border-radius:50%;background:#00e6dc;box-shadow:0 0 10px #00e6dc}+.col{max-width:600px;${left ? '' : 'margin-left:auto;text-align:right;display:flex;flex-direction:column;align-items:flex-end'}}+h1{font-family:'Familjen Grotesk',sans-serif;font-weight:700;font-size:54px;line-height:1.04;letter-spacing:-1.4px;color:${T.text};margin-top:46px;margin-bottom:22px}+h1 .accent{${T.accent ? 'background:linear-gradient(100deg,#00e6dc,#39b8ff 60%,#8c6bf7);-webkit-background-clip:text;background-clip:text;color:transparent' : 'color:' + T.text}}+.sub{font-size:23px;line-height:1.5;color:${T.sub};max-width:500px;margin-bottom:30px}+.sub b{color:${T.text};font-weight:500}+.prompt{display:inline-flex;align-items:center;gap:12px;background:rgba(255,255,255,.06);border:1px solid rgba(0,230,220,.30);+ border-radius:14px;padding:15px 20px;font-size:19px;color:#e3eaf2}+.prompt .q{color:#00e6dc;font-weight:700}.prompt .ask{color:#9aa6b5;font-size:15px;margin-left:6px}+.url{position:absolute;${left ? 'left:92px' : 'right:92px'};bottom:54px;z-index:3;color:#00e6dc;font-weight:600;font-size:19px;font-family:'Familjen Grotesk',sans-serif}+.window{position:absolute;${L.win};overflow:hidden;z-index:1;+ box-shadow:0 28px 80px rgba(0,0,0,.62), 0 0 0 1px rgba(255,255,255,.07), 0 0 130px rgba(0,184,177,.07)}+.chrome{height:42px;background:#1b2128;display:flex;align-items:center;padding-left:18px;border-bottom:1px solid #232a33}+.chrome .ct{color:#8b949e;font-size:15px;margin-right:auto}+.winbtns{display:flex;height:100%}.winbtns .b{width:48px;height:100%;display:flex;align-items:center;justify-content:center;color:#b9c2cd}+.winbtns .min i{display:block;width:12px;height:1.5px;background:#b9c2cd}+.winbtns .max i{display:block;width:11px;height:11px;border:1.5px solid #b9c2cd;border-radius:1px}+.winbtns .cls{font-family:Arial,sans-serif;font-size:18px;line-height:1}+.window img{width:100%;height:${L.imgH}px;display:block;object-fit:cover;object-position:top left}+</style></head><body>+ <div class="tex"></div>+ <div class="window">+ <div class="chrome"><span class="ct">${C.winlabel}</span>+ <div class="winbtns"><span class="b min"><i></i></span><span class="b max"><i></i></span><span class="b cls">✕</span></div></div>+ <img src="${C.shot}">+ </div>+ <div class="zone">+ <div class="top"><div class="wordmark">${WORDMARK}</div><div class="chip"><span class="dot"></span>${C.chip}</div></div>+ <div class="col">+ <h1>${C.headline}</h1>+ <div class="sub">${C.sub}</div>+ <div class="prompt"><span class="q">"${C.prompt}"</span><span class="ask">— just ask Claude</span></div>+ </div>+ </div>+ <div class="url">${C.url}</div>+</body></html>`;+}++// curated showcase set: name -> [layout, theme]+const COMBOS = {+ 'midnight': ['bottom', 'midnight'],+ 'mirror': ['mirror', 'midnight'],+ 'pcb': ['bottom', 'pcb'],+ 'onion': ['bottom', 'onion'],+ 'pill': ['bottom', 'pill'],+ 'gradient': ['bottom', 'gradient'],+ 'bleed-right': ['bleedRight', 'midnight'],+ 'bleed-right-pcb': ['bleedRight', 'pcb'],+ 'contained': ['contained', 'midnight'],+ 'contained-gradient': ['contained', 'gradient'],+};++function write(name, layoutKey, themeKey) {+ const L = LAYOUTS[layoutKey], T = THEMES[themeKey];+ if (!L || !T) throw new Error('bad layout/theme: ' + layoutKey + '/' + themeKey);+ const out = path.join(DIR, `variant-${name}.html`);+ fs.writeFileSync(out, html(L, T));+ console.log('wrote', out, `(${layoutKey} × ${themeKey})`);+}++const a = process.argv.slice(2);+if (a.length === 0) {+ for (const [name, [l, t]] of Object.entries(COMBOS)) write(name, l, t);+} else if (a[0] === 'name') {+ const [l, t] = COMBOS[a[1]]; write(a[1], l, t);+} else {+ write(`${a[0]}-${a[1]}`, a[0], a[1]);+}
package.json+2−2@@ -24,7 +24,7 @@ ], "hero": { "type": "image",- "path": "adom-sfconvert-hero-v5.png"+ "path": "adom-sfconvert-hero-v6.png" }, "discovery_triggers": [ "convert eagle to kicad",@@ -38,7 +38,7 @@ "license": "MIT", "files": [ "skills/adom-sfconvert/SKILL.md",- "adom-sfconvert-hero-v5.png",+ "adom-sfconvert-hero-v6.png", "README.md", "SKILL.md", "install.sh",