Skill: site-cloner
Visão geral
Pipeline em CLI que recebe uma URL de referência e:
- Analisa a página com Playwright — extrai design tokens (cores, tipografia,
spacing, radius, sombras, transições, z-index), um inventário hierárquico de
componentes, as interações presentes (carousel, modal, countdown, accordion,
tabs, dropdown, form, smooth-scroll), screenshots baseline em 3 viewports e
um snapshot autossuficiente: DOM renderizado + todo o CSS (inclusive
folhas de CDN, re-buscadas server-side) + imagens/fontes baixadas para
public/assets/, com URLs reescritas.
- Gera um projeto Astro 4. Com snapshot,
index.astro reproduz o
<body> real da referência com o CSS capturado (set:html); sem snapshot,
cai num scaffold semeado pelos tokens. Sempre emite tailwind.config.ts
(theme.extend com os tokens), roda npm install + astro build.
- Valida o projeto gerado — screenshots nos 3 viewports vs. referência
(pixelmatch + SSIM 50/50), recortes hero/header/cta quando ambos os lados
expõem o landmark, e uma suíte funcional Playwright — com loop de correção
(até 5 iterações).
- Emite
validation-report.html + JSONs com os scores.
Expectativas realistas (leia antes de usar)
- Com snapshot (caso normal) a reprodução é fiel: mesmo DOM, mesmo CSS,
mesmos assets. É um clone visual estático — sem JavaScript: carrosséis,
modais, contadores e menus não funcionam, só aparecem no estado capturado.
- Similaridade visual típica: ~80–90% para um template real denso. O que
segura abaixo de 100%: SSIM de janela única (aproximação), diferenças de
timing/animação entre as duas renderizações, e sub-pixel de scrollbar/altura.
O gate
≥90% é meta, não garantia — o relatório lista os gaps.
- Recortes hero/cta ficam
n/a quando o template não expõe um landmark
semântico correspondente nos dois lados; isso não reprova o gate (só conta
o que foi medido de fato).
- Sem snapshot (falha de captura), o fallback é o scaffold por tokens — aí a
similaridade cai bastante e o projeto é só um ponto de partida.
- Entregáveis sempre confiáveis: tokens prontos para Tailwind, mapa de
componentes/interações, screenshots baseline, assets locais e o
harness de validação reaproveitável.
Quando usar
- "Clone este site: https://exemplo.com" / "replique o layout de "
- "Extraia o design system / os tokens de "
- "Quero um projeto Astro partindo do visual de "
- Qualquer pedido de bootstrap de projeto a partir de uma referência visual.
Parâmetros fixos
| Parâmetro |
Valor |
Motivo |
| Framework |
Astro 4 |
SSG, ilhas de interatividade |
| Styling |
Tailwind CSS |
tokens diretos em theme.extend |
| Score visual |
pixelmatch + SSIM, média 50/50 |
pixel + perceptual |
| Viewports |
375 / 768 / 1440 px |
mobile / tablet / desktop |
| Máx. iterações |
5 |
tempo × convergência |
| Deploy |
fora de escopo |
só gera código |
Interface CLI
site-cloner clone <url> # analyze → generate → validate → iterate → report
site-cloner analyze <url> # só a extração (tokens, componentes, screenshots)
site-cloner validate <dir> # revalida um projeto já gerado
Opções de clone (ver --help para a lista completa):
-o, --output <dir> saída (default ./cloned-site)
-c, --content-mapping <json> mapa seletor→texto: '{"h1":"Meu Título"}'
-t, --threshold <n> threshold visual overall (default 0.90)
-i, --max-iterations <n> default 5
-v, --viewports <lista> default mobile,tablet,desktop
--headless <bool> default true
-r, --report <path> default <output>/validation-report.html
--cache-dir <dir> default <skill>/.cache/site-cloner
-f, --force-fresh ignora o cache de análise
--verbose
Variáveis de ambiente:
SITE_CLONER_NO_INSTALL=1 — não roda npm install/build no projeto gerado
(offline, ou quando quem chama vai montar o projeto).
SITE_CLONER_LIVE=1 — habilita o teste de extração ao vivo em npm test.
Fluxo de execução
analyze-reference.ts Playwright → design-tokens, component-map, interactions, screenshots/, snapshot/ (cache 24h por hash(url+viewports))
utils/snapshot.ts coleta DOM + CSS (folhas de CDN re-buscadas server-side) + baixa assets → public/assets, reescreve URLs
generate-project.ts snapshot → index.astro fiel (set:html) | fallback scaffold; tailwind.config.ts; npm install + astro build
validate-visual.ts sobe `astro preview` (mata o processo no fim); screenshots nos 3 viewports; pixelmatch+SSIM full-page + recortes
validate-functional.ts suíte Playwright (nav, forms, modais, carrosséis, responsivo, console, a11y básica)
iterate-fix.ts prioriza os maiores gaps; ajusta tokens/estilos; re-valida; para em 5 iterações ou na convergência
Saídas em <output>/
src/ public/ projeto Astro 4 (+ node_modules/ e dist/ após o build)
src/snapshot/ body.html + captured.css (a página reproduzida)
public/assets/ imagens/fontes baixadas da referência
tailwind.config.ts design tokens extraídos
validation-report.html relatório visual + funcional
visual-validation-report.json scores por viewport/recorte
functional-validation-report.json resultado dos testes funcionais
visual-diffs/ PNGs de diferença (pixelmatch)
README.md guia de personalização
Critérios de validação
| Categoria |
Métrica |
Threshold |
| Visual overall (desktop full-page) |
pixelmatch + SSIM |
≥ 0.90 |
| Visual hero / header |
SSIM do recorte |
≥ 0.95 quando medido (senão n/a) |
| Visual CTAs |
SSIM do recorte |
≥ 0.93 quando medido (senão n/a) |
| Visual mobile / tablet |
SSIM full-page |
≥ 0.88 |
| Funcional (todos os testes) |
pass/fail Playwright |
100% |
| Console |
erros JS críticos |
0 |
Um recorte sem landmark correspondente nos dois lados entra como n/a e não
reprova o gate — só conta o que foi de fato comparado.
Detalhe e metodologia em references/validation-criteria.md.
Guia de extração por tipo de site em references/extraction-guide.md.
Mapeamento CSS→Tailwind em references/tailwind-mapping.md.
Limitações conhecidas
| Limitação |
Mitigação |
| Clone estático — sem JS |
carrosséis/modais/contadores só no estado capturado; re-anime à mão |
| SPAs / JS pesado |
captura o DOM já hidratado (networkidle + fonts.ready + scroll-nudge) |
@import aninhado em CSS |
não seguido — só folhas de 1º nível e <style> |
| CSS/asset com CORS estrito no servidor de origem |
re-busca server-side (context.request); se o host bloquear IP, o asset é pulado |
| Iframes cross-origin |
não capturados |
| SSIM é janela única (global) |
aproximação — teto realista ~90–95% mesmo em render idêntico |
| Fallback scaffold (sem snapshot) |
similaridade baixa; tratar como ponto de partida |
Estrutura da skill
site-cloner/
├── SKILL.md
├── package.json tsconfig.json
├── scripts/
│ ├── cli.ts entry point (commander)
│ ├── analyze-reference.ts extração Playwright + snapshot
│ ├── generate-project.ts página fiel (snapshot) ou scaffold + install/build
│ ├── validate-visual.ts pixelmatch + SSIM; dono do `astro preview`
│ ├── validate-functional.ts suíte funcional Playwright
│ ├── iterate-fix.ts loop de correção (máx 5)
│ ├── commands/ clone.ts analyze.ts validate.ts
│ └── utils/
│ ├── cache-manager.ts cache 24h por hash(url+viewports)
│ ├── snapshot.ts DOM + CSS + assets → bundle autossuficiente
│ ├── token-extractor.ts CSS computado → design tokens
│ ├── component-mapper.ts DOM → árvore de componentes
│ └── pixel-diff.ts pixelmatch + SSIM + PNG de diff
├── references/
│ ├── extraction-guide.md tailwind-mapping.md validation-criteria.md
│ └── astro-templates/ 9 componentes base (Button, Card, Section,
│ Container, Grid, Badge, Input, Modal, Footer)
├── templates/ *.hbs (package.json, astro.config, tsconfig, README)
└── evals/
├── evals.json 3 casos (Event Go, Stripe, Vercel)
└── evals.test.ts schema sempre; extração ao vivo com SITE_CLONER_LIVE=1
Dependências
playwright (browser + screenshots + testes), pixelmatch + pngjs +
sharp (diff visual), css-tree / postcss (parse CSS), handlebars
(templates), astro (astro preview na validação), commander / chalk /
ora (CLI).
Build e teste
npm install
npx playwright install chromium
npm run typecheck # tsc --noEmit
npm run build # tsc → dist/
npm test # vitest — schema dos evals (offline)
SITE_CLONER_LIVE=1 npm test # + extração ao vivo contra a 1ª referência
1---2name: site-cloner3description: Captura DOM + CSS + assets de uma URL com Playwright e gera um projeto Astro 4 que reproduz a pagina, mais design tokens para Tailwind, e valida por diff de screenshots + testes funcionais. Use ao pedir clonar um site, replicar um layout ou extrair o design system de uma URL.4---56# Skill: site-cloner78## Visão geral910Pipeline em CLI que recebe uma URL de referência e:11121. **Analisa** a página com Playwright — extrai design tokens (cores, tipografia,13 spacing, radius, sombras, transições, z-index), um inventário hierárquico de14 componentes, as interações presentes (carousel, modal, countdown, accordion,15 tabs, dropdown, form, smooth-scroll), screenshots baseline em 3 viewports e16 um **snapshot autossuficiente**: DOM renderizado + todo o CSS (inclusive17 folhas de CDN, re-buscadas server-side) + imagens/fontes baixadas para18 `public/assets/`, com URLs reescritas.192. **Gera** um projeto **Astro 4**. Com snapshot, `index.astro` reproduz o20 `<body>` real da referência com o CSS capturado (`set:html`); sem snapshot,21 cai num scaffold semeado pelos tokens. Sempre emite `tailwind.config.ts`22 (`theme.extend` com os tokens), roda `npm install` + `astro build`.233. **Valida** o projeto gerado — screenshots nos 3 viewports vs. referência24 (pixelmatch + SSIM 50/50), recortes hero/header/cta quando ambos os lados25 expõem o landmark, e uma suíte funcional Playwright — com **loop de correção**26 (até 5 iterações).274. Emite `validation-report.html` + JSONs com os scores.2829## Expectativas realistas (leia antes de usar)3031- **Com snapshot** (caso normal) a reprodução é fiel: mesmo DOM, mesmo CSS,32 mesmos assets. É um **clone visual estático — sem JavaScript**: carrosséis,33 modais, contadores e menus não *funcionam*, só aparecem no estado capturado.34- **Similaridade visual típica: ~80–90%** para um template real denso. O que35 segura abaixo de 100%: SSIM de janela única (aproximação), diferenças de36 timing/animação entre as duas renderizações, e sub-pixel de scrollbar/altura.37 O gate `≥90%` é meta, não garantia — o relatório lista os gaps.38- Recortes **hero/cta** ficam `n/a` quando o template não expõe um landmark39 semântico correspondente nos dois lados; isso **não** reprova o gate (só conta40 o que foi medido de fato).41- Sem snapshot (falha de captura), o fallback é o scaffold por tokens — aí a42 similaridade cai bastante e o projeto é só um ponto de partida.43- Entregáveis sempre confiáveis: **tokens prontos para Tailwind**, **mapa de44 componentes/interações**, **screenshots baseline**, **assets locais** e o45 **harness de validação** reaproveitável.4647## Quando usar4849- "Clone este site: https://exemplo.com" / "replique o layout de <URL>"50- "Extraia o design system / os tokens de <URL>"51- "Quero um projeto Astro partindo do visual de <URL>"52- Qualquer pedido de bootstrap de projeto a partir de uma referência visual.5354## Parâmetros fixos5556| Parâmetro | Valor | Motivo |57|-----------|-------|--------|58| Framework | Astro 4 | SSG, ilhas de interatividade |59| Styling | Tailwind CSS | tokens diretos em `theme.extend` |60| Score visual | pixelmatch + SSIM, média 50/50 | pixel + perceptual |61| Viewports | 375 / 768 / 1440 px | mobile / tablet / desktop |62| Máx. iterações | 5 | tempo × convergência |63| Deploy | fora de escopo | só gera código |6465## Interface CLI6667```bash68site-cloner clone <url> # analyze → generate → validate → iterate → report69site-cloner analyze <url> # só a extração (tokens, componentes, screenshots)70site-cloner validate <dir> # revalida um projeto já gerado71```7273Opções de `clone` (ver `--help` para a lista completa):7475```76-o, --output <dir> saída (default ./cloned-site)77-c, --content-mapping <json> mapa seletor→texto: '{"h1":"Meu Título"}'78-t, --threshold <n> threshold visual overall (default 0.90)79-i, --max-iterations <n> default 580-v, --viewports <lista> default mobile,tablet,desktop81 --headless <bool> default true82-r, --report <path> default <output>/validation-report.html83 --cache-dir <dir> default <skill>/.cache/site-cloner84-f, --force-fresh ignora o cache de análise85 --verbose86```8788Variáveis de ambiente:8990- `SITE_CLONER_NO_INSTALL=1` — não roda `npm install`/`build` no projeto gerado91 (offline, ou quando quem chama vai montar o projeto).92- `SITE_CLONER_LIVE=1` — habilita o teste de extração ao vivo em `npm test`.9394## Fluxo de execução9596```97analyze-reference.ts Playwright → design-tokens, component-map, interactions, screenshots/, snapshot/ (cache 24h por hash(url+viewports))98utils/snapshot.ts coleta DOM + CSS (folhas de CDN re-buscadas server-side) + baixa assets → public/assets, reescreve URLs99generate-project.ts snapshot → index.astro fiel (set:html) | fallback scaffold; tailwind.config.ts; npm install + astro build100validate-visual.ts sobe `astro preview` (mata o processo no fim); screenshots nos 3 viewports; pixelmatch+SSIM full-page + recortes101validate-functional.ts suíte Playwright (nav, forms, modais, carrosséis, responsivo, console, a11y básica)102iterate-fix.ts prioriza os maiores gaps; ajusta tokens/estilos; re-valida; para em 5 iterações ou na convergência103```104105## Saídas em `<output>/`106107```108src/ public/ projeto Astro 4 (+ node_modules/ e dist/ após o build)109src/snapshot/ body.html + captured.css (a página reproduzida)110public/assets/ imagens/fontes baixadas da referência111tailwind.config.ts design tokens extraídos112validation-report.html relatório visual + funcional113visual-validation-report.json scores por viewport/recorte114functional-validation-report.json resultado dos testes funcionais115visual-diffs/ PNGs de diferença (pixelmatch)116README.md guia de personalização117```118119## Critérios de validação120121| Categoria | Métrica | Threshold |122|-----------|---------|-----------|123| Visual overall (desktop full-page) | pixelmatch + SSIM | ≥ 0.90 |124| Visual hero / header | SSIM do recorte | ≥ 0.95 quando medido (senão `n/a`) |125| Visual CTAs | SSIM do recorte | ≥ 0.93 quando medido (senão `n/a`) |126| Visual mobile / tablet | SSIM full-page | ≥ 0.88 |127| Funcional (todos os testes) | pass/fail Playwright | 100% |128| Console | erros JS críticos | 0 |129130Um recorte sem landmark correspondente nos dois lados entra como `n/a` e **não**131reprova o gate — só conta o que foi de fato comparado.132133Detalhe e metodologia em [references/validation-criteria.md](references/validation-criteria.md).134Guia de extração por tipo de site em [references/extraction-guide.md](references/extraction-guide.md).135Mapeamento CSS→Tailwind em [references/tailwind-mapping.md](references/tailwind-mapping.md).136137## Limitações conhecidas138139| Limitação | Mitigação |140|-----------|-----------|141| Clone estático — sem JS | carrosséis/modais/contadores só no estado capturado; re-anime à mão |142| SPAs / JS pesado | captura o DOM já hidratado (`networkidle` + `fonts.ready` + scroll-nudge) |143| `@import` aninhado em CSS | não seguido — só folhas de 1º nível e `<style>` |144| CSS/asset com CORS estrito no servidor de origem | re-busca server-side (`context.request`); se o host bloquear IP, o asset é pulado |145| Iframes cross-origin | não capturados |146| SSIM é janela única (global) | aproximação — teto realista ~90–95% mesmo em render idêntico |147| Fallback scaffold (sem snapshot) | similaridade baixa; tratar como ponto de partida |148149## Estrutura da skill150151```152site-cloner/153├── SKILL.md154├── package.json tsconfig.json155├── scripts/156│ ├── cli.ts entry point (commander)157│ ├── analyze-reference.ts extração Playwright + snapshot158│ ├── generate-project.ts página fiel (snapshot) ou scaffold + install/build159│ ├── validate-visual.ts pixelmatch + SSIM; dono do `astro preview`160│ ├── validate-functional.ts suíte funcional Playwright161│ ├── iterate-fix.ts loop de correção (máx 5)162│ ├── commands/ clone.ts analyze.ts validate.ts163│ └── utils/164│ ├── cache-manager.ts cache 24h por hash(url+viewports)165│ ├── snapshot.ts DOM + CSS + assets → bundle autossuficiente166│ ├── token-extractor.ts CSS computado → design tokens167│ ├── component-mapper.ts DOM → árvore de componentes168│ └── pixel-diff.ts pixelmatch + SSIM + PNG de diff169├── references/170│ ├── extraction-guide.md tailwind-mapping.md validation-criteria.md171│ └── astro-templates/ 9 componentes base (Button, Card, Section,172│ Container, Grid, Badge, Input, Modal, Footer)173├── templates/ *.hbs (package.json, astro.config, tsconfig, README)174└── evals/175 ├── evals.json 3 casos (Event Go, Stripe, Vercel)176 └── evals.test.ts schema sempre; extração ao vivo com SITE_CLONER_LIVE=1177```178179## Dependências180181`playwright` (browser + screenshots + testes), `pixelmatch` + `pngjs` +182`sharp` (diff visual), `css-tree` / `postcss` (parse CSS), `handlebars`183(templates), `astro` (`astro preview` na validação), `commander` / `chalk` /184`ora` (CLI).185186## Build e teste187188```bash189npm install190npx playwright install chromium191npm run typecheck # tsc --noEmit192npm run build # tsc → dist/193npm test # vitest — schema dos evals (offline)194SITE_CLONER_LIVE=1 npm test # + extração ao vivo contra a 1ª referência195```