# Site Cloner

> 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.

- Skill: `devopsadmins/site-cloner` (Agent Skill, multi-file: 36 files)
- Install (CLI): `npx skillmds@latest add devopsadmins/site-cloner`
- Raw SKILL.md: https://api.skillmd.com/api/skills/devopsadmins/site-cloner/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: devopsadmins (https://skillmd.com/u/devopsadmins)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/devopsadmins/site-cloner

---


# Skill: site-cloner

## Visão geral

Pipeline em CLI que recebe uma URL de referência e:

1. **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.
2. **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`.
3. **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).
4. 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 <URL>"
- "Extraia o design system / os tokens de <URL>"
- "Quero um projeto Astro partindo do visual de <URL>"
- 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

```bash
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](references/validation-criteria.md).
Guia de extração por tipo de site em [references/extraction-guide.md](references/extraction-guide.md).
Mapeamento CSS→Tailwind em [references/tailwind-mapping.md](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

```bash
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
```

