Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
8 KiB
| name | description | arguments | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| site-teardown | Deconstruct any live website into reusable recipe — extract HTML, CSS, JS, design tokens, animations. Use when user says: teardown, deconstruct, clone site, reverse engineer, how is this site built. |
|
Site Teardown — Deconstruct Any Website into a Reusable Recipe
Extracts design tokens, layout structure, animation techniques, and library stack from a live website.
Output: structured recipe that can be fed into /frontend-design, /landing-page, /design-system.
Phase 1 — Navigate & Screenshot
1. browser_navigate → {url}
2. browser_resize → width: 1280, height: 900
3. browser_take_screenshot → fullPage: true, filename: "teardown-desktop.png"
4. browser_resize → width: 375, height: 812
5. browser_take_screenshot → fullPage: true, filename: "teardown-mobile.png"
6. browser_resize → width: 1280, height: 900 (restore)
Save screenshots to teardown/{domain}/ in the project directory (relative to $PWD).
Phase 2 — Extract HTML Structure
Run browser_evaluate with:
() => {
const sections = Array.from(document.querySelectorAll('section, [class*="section"], main > div'));
const nav = document.querySelector('nav, header');
const footer = document.querySelector('footer');
const headings = Array.from(document.querySelectorAll('h1, h2, h3')).map(h => ({
tag: h.tagName, text: h.textContent.trim().slice(0, 80)
}));
return {
title: document.title,
sectionCount: sections.length,
hasNav: !!nav,
navType: nav?.classList?.toString() || 'unknown',
hasFooter: !!footer,
headings,
bodyClasses: document.body.classList.toString(),
htmlLang: document.documentElement.lang
};
}
Also extract full HTML for deep analysis:
() => document.documentElement.outerHTML
Save to teardown/{domain}/index.html.
Phase 3 — Extract Design Tokens
Run browser_evaluate to extract computed styles from key elements:
() => {
const get = (sel) => {
const el = document.querySelector(sel);
return el ? getComputedStyle(el) : null;
};
const body = get('body');
const h1 = get('h1');
const btn = get('a[class*="btn"], button[class*="btn"], .cta, a[class*="cta"]');
const card = get('[class*="card"], [class*="Card"]');
const props = {};
const root = getComputedStyle(document.documentElement);
for (const name of ['--primary', '--secondary', '--accent', '--background', '--foreground',
'--radius', '--font-sans', '--font-mono', '--brand']) {
const val = root.getPropertyValue(name).trim();
if (val) props[name] = val;
}
return {
colors: {
background: body?.backgroundColor,
text: body?.color,
heading: h1?.color,
button: btn ? { bg: btn.backgroundColor, text: btn.color, radius: btn.borderRadius } : null,
card: card ? { bg: card.backgroundColor, border: card.borderColor, radius: card.borderRadius, shadow: card.boxShadow } : null
},
typography: {
bodyFont: body?.fontFamily,
bodySize: body?.fontSize,
h1Font: h1?.fontFamily,
h1Size: h1?.fontSize,
h1Weight: h1?.fontWeight,
lineHeight: body?.lineHeight
},
spacing: {
bodyPadding: body?.padding,
sectionPadding: get('section')?.padding
},
customProperties: props
};
}
Output: Save as teardown/{domain}/tokens.json.
Phase 4 — Fetch CSS & JS Sources
4a. Collect resource URLs
() => {
const css = Array.from(document.querySelectorAll('link[rel="stylesheet"]')).map(l => l.href);
const js = Array.from(document.querySelectorAll('script[src]')).map(s => s.src);
const inlineStyles = document.querySelectorAll('style').length;
return { css, js, inlineStyleBlocks: inlineStyles };
}
4b. Fetch each CSS file via WebFetch
For each CSS URL: WebFetch with prompt:
"Extract ALL design-relevant CSS from this stylesheet: custom properties (--vars), @keyframes, @font-face, color values, gradient definitions, backdrop-filter, box-shadow patterns, border-radius values, transition/animation properties. Return as structured list."
4c. Detect JS libraries
() => ({
gsap: typeof gsap !== 'undefined',
ScrollTrigger: typeof ScrollTrigger !== 'undefined',
lenis: !!document.querySelector('[data-lenis-prevent]') || typeof Lenis !== 'undefined',
framerMotion: !!document.querySelector('[data-framer-component-type]'),
three: typeof THREE !== 'undefined',
curtains: typeof Curtains !== 'undefined',
particles: typeof tsParticles !== 'undefined',
aos: typeof AOS !== 'undefined',
locomotive: !!document.querySelector('[data-scroll-container]'),
swiper: typeof Swiper !== 'undefined',
tailwind: !!document.querySelector('[class*="bg-"], [class*="text-"], [class*="flex"]'),
react: typeof __NEXT_DATA__ !== 'undefined' || !!document.getElementById('__next'),
astro: !!document.querySelector('[data-astro-source-file]'),
vue: !!document.getElementById('__nuxt') || !!document.querySelector('[data-v-]')
})
4d. Network analysis (supplementary)
browser_network_requests with filter: "\\.css$|\\.js$", static: false — cross-reference with DOM-extracted URLs.
Phase 5 — Animation Catalog
() => {
const anims = [];
const allEls = document.querySelectorAll('*');
const seen = new Set();
allEls.forEach(el => {
const s = getComputedStyle(el);
if (s.animationName && s.animationName !== 'none' && !seen.has(s.animationName)) {
seen.add(s.animationName);
anims.push({ type: 'css-animation', name: s.animationName, duration: s.animationDuration });
}
if (s.transition && s.transition !== 'all 0s ease 0s' && s.transition !== 'none') {
const key = s.transition.slice(0, 60);
if (!seen.has(key)) { seen.add(key); anims.push({ type: 'transition', value: s.transition.slice(0, 120) }); }
}
});
const canvases = document.querySelectorAll('canvas').length;
const videos = document.querySelectorAll('video').length;
const svgAnims = document.querySelectorAll('animate, animateTransform').length;
return { animations: anims, canvasCount: canvases, videoCount: videos, svgAnimations: svgAnims };
}
Output: Save analysis as teardown/{domain}/animations.md.
If depth=quick → STOP here with tokens + screenshots only.
Phase 6 — Compile Recipe
Assemble teardown/{domain}/recipe.md:
# Site Teardown: {domain}
Date: {date}
## Layout Structure
{section map from Phase 2}
## Design Tokens
{from Phase 3 — colors, typography, spacing}
## Tech Stack
- Framework: {React/Next/Astro/Vue from Phase 4c}
- CSS: {Tailwind/custom/styled-components}
- Animation: {GSAP/Framer Motion/CSS/AOS from Phase 4c}
- Scroll: {Lenis/Locomotive/native from Phase 4c}
- 3D/WebGL: {Three.js/curtains.js/none from Phase 4c}
## Animation Techniques
{catalog from Phase 5}
## Reproduction Steps
1. Set up {framework} project with {css approach}
2. Apply design tokens: {token summary}
3. Implement layout: {section sequence}
4. Add animations: {technique list with skill references}
5. Optimize: /web-assets → /a11y-audit → /perf-audit
## Recommended Skills
- /frontend-design archetype={suggested}
- /scroll-animation technique={if GSAP detected}
- /web-effects effect={if WebGL detected}
- /motion-design {if Framer Motion detected}
Chaining
| Direction | Skill | How |
|---|---|---|
| FROM | /design-inspiration |
User picks best reference → teardown |
| FROM | /competitor-analysis |
Deep-dive competitor's site |
| TO | /frontend-design |
Feed tokens → suggest archetype |
| TO | /landing-page |
Use recipe as template |
| TO | /design-system |
Generate token system from extracted tokens |
| TO | /scroll-animation |
Reproduce detected scroll effects |
| TO | /web-effects |
Reproduce detected WebGL/particle effects |