|
1
|
--- |
|
2
|
name: website-cloning |
|
3
|
description: Clone any website as a pixel-perfect React + Vite app using Playwright extraction. |
|
4
|
--- |
|
5
|
|
|
6
|
# Clone Website — Pixel-Perfect Methodology |
|
7
|
|
|
8
|
Reverse-engineer and rebuild a target website as an exact replica React + Vite clone. Every font, color, icon, image, section, background, transition, and interaction must match the original. Zero guessing, zero placeholders. |
|
9
|
|
|
10
|
## Cardinal Rules |
|
11
|
|
|
12
|
1. **Raw HTML is the source of truth.** Before building ANY section, read the corresponding portion of `raw.html`. Never build from memory, screenshots alone, or guessed structure. |
|
13
|
2. **One component per visual pattern.** Never reuse a component designed for one layout (e.g., product cards with prices) for a structurally different layout (e.g., category cards with just names). If two sections look different, they get different components or distinct CSS classes. |
|
14
|
|
|
15
|
3. **All assets downloaded before building starts.** Every image, font, SVG, and video must be local in `public/` before any component code is written. No mid-build downloads. |
|
16
|
4. **Build all sections, then verify the full page.** Building and screenshotting section-by-section is too slow. Build all components from raw HTML, assemble in App.tsx, then take a full-page screenshot and fix any discrepancies. This is 3-5x faster than per-section verification loops. |
|
17
|
|
|
18
|
5. **No fabricated content.** Every heading, subtitle, button label, badge, price, and link must come from the source HTML. Never invent text that doesn't exist on the original page. |
|
19
|
6. **Replace the scaffolded CSS entirely.** The `createArtifact`scaffold includes Tailwind/shadcn boilerplate. Replace`index.css` completely with plain CSS — a Google Font import, CSS reset, CSS variables for design tokens, and nothing else. Clone pages don't use component libraries. |
|
20
|
|
|
21
|
## Anti-Patterns (Common Mistakes to Avoid) |
|
22
|
|
|
23
|
| Mistake | Correct Approach | |
|
24
|
|
|
25
|
|---------|-----------------| |
|
26
|
|
|
27
|
| Outlined/bordered buttons when original uses filled/solid | Check `raw.html`for button classes and extract`background-color`, not`border` | |
|
28
|
|
|
29
|
| Center-aligned text when original is left-aligned | Extract `text-align` from computed styles | |
|
30
|
|
|
31
|
| Adding badges/labels that don't exist in original | Only add elements that exist in `raw.html` | |
|
32
|
|
|
33
|
| Skipping sections or changing their order | Follow the section inventory checklist exactly | |
|
34
|
|
|
35
|
| Using placeholder images | Download all images in Phase 1 before building | |
|
36
|
|
|
37
|
| Reusing `ProductCard` for category grids | Each visually distinct card type gets its own component | |
|
38
|
|
|
39
|
| Guessing font sizes, colors, spacing | Extract exact computed values; never approximate | |
|
40
|
|
|
41
|
| Building from screenshot interpretation alone | Always cross-reference `raw.html` for structure and content | |
|
42
|
|
|
43
|
| Using an SVG `<text>`element for the logo | Extract the real SVG logo paths from`raw.html` | |
|
44
|
|
|
45
|
| Running per-section screenshot QA loops | Build all sections, then do one full-page verify pass | |
|
46
|
|
|
47
|
| Keeping Tailwind/shadcn/Radix in a clone | Replace index.css with plain CSS; remove unused deps | |
|
48
|
|
|
49
|
| Translating/anglicizing text from a non-English page | Clone must use the EXACT language shown on the target page | |
|
50
|
|
|
51
|
| Guessing the announcement bar color | Extract computed `background-color` from the banner element | |
|
52
|
|
|
53
|
| Centering the logo when it's left-aligned | Take a header screenshot and compare logo position | |
|
54
|
|
|
55
|
| Omitting the account/rewards bar text | Extract ALL header elements including loyalty/rewards UI | |
|
56
|
|
|
57
|
## Legitimate Use Policy |
|
58
|
|
|
59
|
Before cloning, confirm the user's intent is legitimate. Ask: |
|
60
|
|
|
61
|
1. "Is this your own website or your client's website?" |
|
62
|
2. "What is this clone for?" |
|
63
|
|
|
64
|
Acceptable: rebuilding your own site, design reference/learning, staging copy, platform migration. |
|
65
|
|
|
66
|
**Refuse** if: impersonation, phishing, traffic theft, trademark infringement, or deception. |
|
67
|
|
|
68
|
For non-owned sites (design inspiration), remind the user to replace logos, brand names, trademarks, product data, and contact info with their own. |
|
69
|
|
|
70
|
## Prerequisites |
|
71
|
|
|
72
|
```bash |
|
73
|
|
|
74
|
pip install playwright |
|
75
|
|
|
76
|
CHROMIUM_PATH=$(find /nix/store -maxdepth 4 -name "chromium" -type f 2>/dev/null | head -1) |
|
77
|
|
|
78
|
echo "Chromium at: $CHROMIUM_PATH" |
|
79
|
|
|
80
|
``` |
|
81
|
|
|
82
|
### Critical Playwright settings |
|
83
|
|
|
84
|
- Always use `--no-sandbox` args |
|
85
|
- Use `wait_until="domcontentloaded"`(not`"networkidle"`) |
|
86
|
|
|
87
|
- Add `page.wait_for_timeout(5000)` after navigation |
|
88
|
- Set `timeout=60000`on all`page.goto()` calls |
|
89
|
|
|
90
|
--- |
|
91
|
|
|
92
|
## Phase 1: Reconnaissance & Extraction |
|
93
|
|
|
94
|
All extraction happens before any building. See `extraction.md` for complete Python scripts. |
|
95
|
|
|
96
|
### 1.1 Save Raw HTML (THE SOURCE OF TRUTH) |
|
97
|
|
|
98
|
```python |
|
99
|
|
|
100
|
raw_html = page.content() |
|
101
|
|
|
102
|
with open(f"{OUT_DIR}/raw.html", "w", encoding="utf-8") as f: |
|
103
|
|
|
104
|
f.write(raw_html) |
|
105
|
|
|
106
|
``` |
|
107
|
|
|
108
|
This file is the authoritative reference for ALL section structure, content, class names, element ordering, and text content. Computed styles supplement it but never replace it. |
|
109
|
|
|
110
|
### 1.2 Language & Locale Detection (CRITICAL) |
|
111
|
|
|
112
|
If the target URL contains a locale path (e.g., `/es-do`,`/fr`,`/de`,`/ja`), the clone MUST be in that language. However, server-side rendering may return English even for locale URLs — the localization often happens via client-side JavaScript after page load. |
|
113
|
|
|
114
|
#### Detection steps |
|
115
|
|
|
116
|
1. After `page.wait_for_timeout(8000)` (extra wait for JS locale loading), extract all visible text from key areas: |
|
117
|
|
|
118
|
```python |
|
119
|
|
|
120
|
locale_info = page.evaluate(""" |
|
121
|
|
|
122
|
() => ({ |
|
123
|
|
|
124
|
bannerText: document.querySelector('[class*="banner"], [class*="announcement"]')?.innerText?.trim(), |
|
125
|
|
|
126
|
navLinks: [...document.querySelectorAll('nav a, .main-nav a')].map(a => a.innerText.trim()).filter(t => t).slice(0, 8), |
|
127
|
|
|
128
|
loyaltyText: document.querySelector('[class*="loyalty"], [class*="rewards"]')?.innerText?.trim(), |
|
129
|
|
|
130
|
headerText: document.querySelector('header')?.innerText?.trim()?.slice(0, 500), |
|
131
|
|
|
132
|
htmlLang: document.documentElement.lang, |
|
133
|
|
|
134
|
url: window.location.href |
|
135
|
|
|
136
|
}) |
|
137
|
|
|
138
|
""") |
|
139
|
|
|
140
|
``` |
|
141
|
|
|
142
|
1. If the URL locale doesn't match the extracted text language, the page probably needs more time for JS to run, or the locale is cookie-based. |
|
143
|
2. **When in doubt, use the language implied by the URL locale.** If `/es-do` shows English text in the raw HTML, translate all user-facing text to Spanish when building. The URL locale is the user's intent. |
|
144
|
|
|
145
|
**Brand terms stay in the original language.** Product names (e.g., "ALO Runner"), color names (e.g., "SUNSHINE"), brand names (e.g., "ALO Wellness Club") should NOT be translated — the real site keeps these in English even on localized pages. |
|
146
|
|
|
147
|
### 1.3 Screenshots (Desktop only for initial build) |
|
148
|
|
|
149
|
Take a full-page screenshot at 1440px. This becomes the primary visual reference. Tablet and mobile screenshots are only needed if the user specifically requests responsive behavior. |
|
150
|
|
|
151
|
**Take a separate header-only screenshot** at this stage — crop to just the top 150px. This will be your reference for logo placement, nav layout, banner color, and account/rewards UI. Header issues are the most common mistakes. |
|
152
|
|
|
153
|
### 1.4 Section Inventory |
|
154
|
|
|
155
|
Parse the raw HTML to produce a complete ordered checklist. For each section, record: |
|
156
|
|
|
157
|
- Section index and DOM selector (tag, id, classes) |
|
158
|
- Exact heading text and subheading text |
|
159
|
|
|
160
|
- Button labels |
|
161
|
- Image count |
|
162
|
|
|
163
|
- Background color (if non-transparent) |
|
164
|
|
|
165
|
Save as `clone-data/inventory.json`. This becomes the build checklist. |
|
166
|
|
|
167
|
### 1.5 Design Tokens |
|
168
|
|
|
169
|
Extract CSS custom properties, body font-family, heading font-family, primary colors. Save to `clone-data/tokens.json`. |
|
170
|
|
|
171
|
### 1.6 Font Handling |
|
172
|
|
|
173
|
#### Priority order |
|
174
|
|
|
175
|
1. **Download actual font files** — Check `@font-face`rules for`.woff2`/`.woff`URLs. Download to`public/fonts/`and declare`@font-face`in`index.css`. |
|
176
|
2. **Use Google Fonts if available** — If the site uses Google Fonts, add the `@import`or`<link>` tag. |
|
177
|
|
|
178
|
3. **Map to closest equivalent** — Only as a last resort: |
|
179
|
|
|
180
|
| Proprietary Font | Google Fonts Equivalent | |
|
181
|
|
|
182
|
|-----------------|----------------------| |
|
183
|
|
|
184
|
| Proxima Nova | DM Sans | |
|
185
|
|
|
186
|
| Geograph | DM Sans | |
|
187
|
|
|
188
|
| Self Modern | DM Serif Text | |
|
189
|
|
|
190
|
| Graphik | Inter | |
|
191
|
|
|
192
|
| Circular | DM Sans | |
|
193
|
|
|
194
|
| GT Walsheim | Plus Jakarta Sans | |
|
195
|
|
|
196
|
| Tiempos | Playfair Display | |
|
197
|
|
|
198
|
| Apercu | Source Sans Pro | |
|
199
|
|
|
200
|
| Founders Grotesk | Space Grotesk | |
|
201
|
|
|
202
|
| National | DM Sans | |
|
203
|
|
|
204
|
| Futura | Jost | |
|
205
|
|
|
206
|
| Avenir | Nunito Sans | |
|
207
|
|
|
208
|
| Gotham | Montserrat | |
|
209
|
|
|
210
|
| Brandon Grotesque | Raleway | |
|
211
|
|
|
212
|
### 1.7 SVG Logo Extraction (CRITICAL) |
|
213
|
|
|
214
|
The site's logo is almost always an inline SVG in the `raw.html`, NOT just text. Search for it: |
|
215
|
|
|
216
|
```bash |
|
217
|
|
|
218
|
# Search raw HTML for SVG near logo references |
|
219
|
|
|
220
|
python3 -c " |
|
221
|
|
|
222
|
with open('clone-data/raw.html') as f: |
|
223
|
|
|
224
|
html = f.read() |
|
225
|
|
|
226
|
# Search around 'logo' class references |
|
227
|
|
|
228
|
import re |
|
229
|
|
|
230
|
for m in re.finditer(r'logo', html[:15000], re.IGNORECASE): |
|
231
|
|
|
232
|
idx = m.start() |
|
233
|
|
|
234
|
# Look for SVG nearby |
|
235
|
|
|
236
|
svg_start = html.find('<svg', max(0, idx-200)) |
|
237
|
|
|
238
|
if svg_start != -1 and svg_start < idx + 500: |
|
239
|
|
|
240
|
svg_end = html.find('</svg>', svg_start) + 6 |
|
241
|
|
|
242
|
print(html[svg_start:svg_end]) |
|
243
|
|
|
244
|
break |
|
245
|
|
|
246
|
" |
|
247
|
|
|
248
|
``` |
|
249
|
|
|
250
|
**Never use an SVG `<text>`element as a logo substitute.** Extract the real SVG`<path>` elements from the source HTML. The logo is the most recognizable element on the page — getting it wrong immediately signals "fake." |
|
251
|
|
|
252
|
### 1.8 Asset Download (ALL assets, ALL at once) |
|
253
|
|
|
254
|
Download every image, video, SVG, background image, and font file before building starts. See `extraction.md` for the complete download script. |
|
255
|
|
|
256
|
**CDN URL upscaling** (increase resolution before downloading): |
|
257
|
|
|
258
|
- **Shopify `_small`suffix**:`_small.jpg`→`_1200x.jpg` (very common pattern) |
|
259
|
- **Shopify query params**: `?width=X`→`?width=1200` |
|
260
|
|
|
261
|
- **Sanity**: `?w=X`→`?w=1200` |
|
262
|
- **Cloudinary**: `w_X`→`w_1200` |
|
263
|
|
|
264
|
- **Contentful**: `?w=X`→`?w=1200` |
|
265
|
|
|
266
|
**Verification:** After downloading, verify every file exists and is >100 bytes. The download script includes automatic retry with fallback User-Agent strings. |
|
267
|
|
|
268
|
### 1.9 Header Deep Extraction (CRITICAL) |
|
269
|
|
|
270
|
The header is the most error-prone section. Extract detailed information beyond the basic inventory: |
|
271
|
|
|
272
|
```python |
|
273
|
|
|
274
|
header_info = page.evaluate(""" |
|
275
|
|
|
276
|
() => { |
|
277
|
|
|
278
|
const header = document.querySelector('header'); |
|
279
|
|
|
280
|
if (!header) return null; |
|
281
|
|
|
282
|
// Banner/announcement bar |
|
283
|
|
|
284
|
const banner = document.querySelector('[class*="banner"], [class*="announcement"], [class*="uni-banner"]'); |
|
285
|
|
|
286
|
const bannerBg = banner ? getComputedStyle(banner.querySelector('[class*="col"], div') || banner).backgroundColor : null; |
|
287
|
|
|
288
|
// Logo position |
|
289
|
|
|
290
|
const logo = header.querySelector('svg, [class*="logo"] img, [class*="logo"] svg'); |
|
291
|
|
|
292
|
const logoRect = logo?.getBoundingClientRect(); |
|
293
|
|
|
294
|
const headerRect = header.getBoundingClientRect(); |
|
295
|
|
|
296
|
// Nav links |
|
297
|
|
|
298
|
const navLinks = [...header.querySelectorAll('nav a, [class*="nav"] a')].map(a => a.innerText.trim()).filter(t => t && t.length < 30); |
|
299
|
|
|
300
|
// Right-side elements (account, rewards, search, cart, wishlist) |
|
301
|
|
|
302
|
const rightElements = [...header.querySelectorAll('[class*="loyalty"], [class*="rewards"], [class*="account"], [class*="cart"], [class*="wishlist"]')]; |
|
303
|
|
|
304
|
return { |
|
305
|
|
|
306
|
bannerText: banner?.innerText?.trim(), |
|
307
|
|
|
308
|
bannerBgColor: bannerBg, |
|
309
|
|
|
310
|
bannerTextColor: banner ? getComputedStyle(banner).color : null, |
|
311
|
|
|
312
|
logoPosition: logoRect ? (logoRect.left < headerRect.width / 3 ? 'left' : logoRect.left < headerRect.width * 2/3 ? 'center' : 'right') : 'unknown', |
|
313
|
|
|
314
|
navLinks: navLinks.slice(0, 10), |
|
315
|
|
|
316
|
rightSideText: rightElements.map(el => el.innerText?.trim()).filter(t => t), |
|
317
|
|
|
318
|
rightSideHTML: rightElements.map(el => el.innerHTML?.slice(0, 300)), |
|
319
|
|
|
320
|
}; |
|
321
|
|
|
322
|
} |
|
323
|
|
|
324
|
""") |
|
325
|
|
|
326
|
``` |
|
327
|
|
|
328
|
This prevents the three most common header mistakes: wrong banner color, wrong logo position, missing account/rewards text. |
|
329
|
|
|
330
|
### 1.10 Footer Link Extraction |
|
331
|
|
|
332
|
Extract all footer links separately — they're needed for the footer component: |
|
333
|
|
|
334
|
```python |
|
335
|
|
|
336
|
footer_data = page.evaluate(""" |
|
337
|
|
|
338
|
() => { |
|
339
|
|
|
340
|
const footer = document.querySelector('footer'); |
|
341
|
|
|
342
|
if (!footer) return null; |
|
343
|
|
|
344
|
return { |
|
345
|
|
|
346
|
text: footer.innerText, |
|
347
|
|
|
348
|
bgColor: getComputedStyle(footer).backgroundColor, |
|
349
|
|
|
350
|
links: [...footer.querySelectorAll('a')].map(a => ({ |
|
351
|
|
|
352
|
text: a.innerText.trim(), href: a.getAttribute('href') |
|
353
|
|
|
354
|
})).filter(l => l.text) |
|
355
|
|
|
356
|
}; |
|
357
|
|
|
358
|
} |
|
359
|
|
|
360
|
""") |
|
361
|
|
|
362
|
``` |
|
363
|
|
|
364
|
--- |
|
365
|
|
|
366
|
## Phase 2: Foundation Build |
|
367
|
|
|
368
|
Sequential — do this yourself, not delegated. |
|
369
|
|
|
370
|
1. **Create artifact** via `createArtifact()`with type`react-vite` |
|
371
|
2. **Replace `index.css` entirely** — Remove ALL Tailwind/shadcn boilerplate. Write plain CSS: |
|
372
|
|
|
373
|
- Google Fonts `@import`(or`@font-face` for self-hosted) |
|
374
|
- Universal reset (`*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }`) |
|
375
|
|
|
376
|
- CSS variables for design tokens (font families, colors) |
|
377
|
- Basic body styles (font-family, color, background, antialiasing) |
|
378
|
|
|
379
|
- Reset styles for `a`,`button`,`img`,`ul/ol` |
|
380
|
|
|
381
|
1. **Replace `App.tsx`** — Remove all router/query/toast boilerplate. A clone is a single static page. |
|
382
|
2. **Organize assets** in `public/images/` |
|
383
|
|
|
384
|
--- |
|
385
|
|
|
386
|
## Phase 3: Build All Sections |
|
387
|
|
|
388
|
Build all components from the section inventory, referencing `raw.html` for exact content. Use inline styles or CSS modules — not Tailwind. |
|
389
|
|
|
390
|
### For EACH section in the inventory |
|
391
|
|
|
392
|
**Step 1: Read the raw HTML** for that section's exact structure, text, and element hierarchy. |
|
393
|
|
|
394
|
**Step 2: Build the component** using: |
|
395
|
|
|
396
|
- Exact text content from raw HTML (copy-paste headings, button labels) |
|
397
|
- Local image paths from `public/images/` |
|
398
|
|
|
399
|
- Real SVG paths for logos/icons extracted from raw HTML |
|
400
|
- Inline styles for layout (position, display, flex, grid, padding, colors, fonts) |
|
401
|
|
|
402
|
- Hover interactions via `onMouseEnter`/`onMouseLeave` inline handlers |
|
403
|
- For carousels: `useRef`+`scrollBy`with`overflow-x: auto; scrollbar-width: none` |
|
404
|
|
|
405
|
**Step 3: Use `import.meta.env.BASE_URL`prefix** for all image`src` attributes so they resolve correctly under the artifact's preview path. |
|
406
|
|
|
407
|
### Build tips |
|
408
|
|
|
409
|
- **Build ALL sections before verifying.** Don't stop to screenshot after each one. |
|
410
|
- **Use inline styles** — Simpler than CSS files for clones, and avoids naming/scoping issues. |
|
411
|
|
|
412
|
- **Reusable components are okay when the visual pattern is truly identical** (e.g., two hero banners that differ only in image/button text can share a `HeroBanner` component with props). |
|
413
|
- **`href="#"` is fine** — For a visual clone, real link targets are a nice-to-have, not a requirement. |
|
414
|
|
|
415
|
- **Remove unused scaffolded dependencies** — The `package.json`from`createArtifact` includes 40+ shadcn/Radix packages. These are dead weight for a clone. |
|
416
|
|
|
417
|
--- |
|
418
|
|
|
419
|
## Phase 4: Page Assembly & Verification |
|
420
|
|
|
421
|
1. Import all components into `App.tsx` in exact DOM order from the inventory |
|
422
|
2. Start the dev server and take a full-page screenshot at 1280px |
|
423
|
|
|
424
|
3. Compare against the original screenshot from Phase 1 |
|
425
|
4. Fix discrepancies section by section |
|
426
|
|
|
427
|
5. Run e2e test to verify all sections render (use `runTest()`) |
|
428
|
|
|
429
|
### Verification checklist |
|
430
|
|
|
431
|
- [ ] All sections present in correct order |
|
432
|
- [ ] Logo is the real SVG (not text substitute) |
|
433
|
|
|
434
|
- [ ] Logo position matches (left/center/right) |
|
435
|
- [ ] All images load (no broken images in console) |
|
436
|
|
|
437
|
- [ ] Heading text matches exactly |
|
438
|
- [ ] All text is in the correct language (match URL locale) |
|
439
|
|
|
440
|
- [ ] Button styles match (filled vs outlined, correct colors) |
|
441
|
- [ ] Background colors match for sections with colored backgrounds |
|
442
|
|
|
443
|
- [ ] Announcement bar has correct background color AND text |
|
444
|
- [ ] Account/rewards/loyalty text is present in header (if original has it) |
|
445
|
|
|
446
|
- [ ] Carousels scroll properly |
|
447
|
- [ ] Hover states work on interactive elements |
|
448
|
|
|
449
|
- [ ] Footer has correct columns and content |
|
450
|
|
|
451
|
--- |
|
452
|
|
|
453
|
## Component Specification Format |
|
454
|
|
|
455
|
For complex sections dispatched to subagents, write specs at `docs/research/components/<name>.md`: |
|
456
|
|
|
457
|
```markdown |
|
458
|
|
|
459
|
# <ComponentName> Specification |
|
460
|
|
|
461
|
## Overview |
|
462
|
|
|
463
|
- Target file: `src/components/<ComponentName>.tsx` |
|
464
|
- Interaction model: <static | click | scroll | time> |
|
465
|
|
|
466
|
## DOM Structure (from raw.html) |
|
467
|
|
|
468
|
<Exact element hierarchy with tag names, classes, nesting> |
|
469
|
|
|
470
|
## Computed Styles (exact values) |
|
471
|
|
|
472
|
### Container |
|
473
|
|
|
474
|
- display: flex; flex-direction: row; gap: 24px; padding: 60px 80px; |
|
475
|
|
|
476
|
### Heading |
|
477
|
|
|
478
|
- font-size: 48px; font-weight: 400; color: \#230d0d; |
|
479
|
|
|
480
|
### Button |
|
481
|
|
|
482
|
- background-color: \#f195a7; border-radius: 999px; padding: 12px 32px; |
|
483
|
|
|
484
|
## Text Content (verbatim from raw.html) |
|
485
|
|
|
486
|
<Every heading, paragraph, button label — copy-pasted exactly> |
|
487
|
|
|
488
|
## Assets (local paths) |
|
489
|
|
|
490
|
- /images/products/charm-1.webp |
|
491
|
|
|
492
|
## States & Behaviors |
|
493
|
|
|
494
|
### Hover on card |
|
495
|
|
|
496
|
- transform: none → scale(1.02) |
|
497
|
- transition: transform 0.3s ease |
|
498
|
|
|
499
|
``` |
|
500
|
|
|
501
|
--- |
|
502
|
|
|
503
|
## Quick Reference: Full Workflow |
|
504
|
|
|
505
|
```text |
|
506
|
|
|
507
|
1. pip install playwright; find Chromium path |
|
508
|
2. Navigate to target URL with Playwright |
|
509
|
|
|
510
|
3. Save raw.html (page.content()) — THIS IS THE SOURCE OF TRUTH |
|
511
|
4. Detect locale/language from URL path (e.g., /es-do = Spanish) |
|
512
|
|
|
513
|
5. Take full-page desktop screenshot + header-only screenshot (top 150px) |
|
514
|
6. Build section inventory from raw.html → clone-data/inventory.json |
|
515
|
|
|
516
|
7. Extract design tokens → clone-data/tokens.json |
|
517
|
8. Extract SVG logo from raw.html (search for <svg near 'logo' classes) |
|
518
|
|
|
519
|
9. Extract header details: banner color, logo position, nav links, rewards/loyalty text |
|
520
|
10. Extract fonts (download .woff2 files or map to Google Fonts) |
|
521
|
|
|
522
|
11. Download ALL images/videos/SVGs to public/images/ (batch with retry) |
|
523
|
12. Extract footer links → clone-data/footer.json |
|
524
|
|
|
525
|
13. createArtifact("react-vite", ...) |
|
526
|
14. Replace index.css (plain CSS reset + design tokens — NO Tailwind/shadcn) |
|
527
|
|
|
528
|
15. Replace App.tsx (remove router/query boilerplate — single page) |
|
529
|
16. Build ALL section components (referencing raw.html, using correct language) |
|
530
|
|
|
531
|
17. Assemble page in App.tsx (exact DOM order from inventory) |
|
532
|
18. Start dev server, take full-page screenshot, compare vs original |
|
533
|
|
|
534
|
19. Fix discrepancies (check header first — most common mistake area) |
|
535
|
20. Run e2e test to verify all sections render |
|
536
|
|
|
537
|
21. Present artifact |
|
538
|
|
|
539
|
``` |
|
540
|
|
|
541
|
## Reference Files |
|
542
|
|
|
543
|
- `extraction.md` — Complete Python extraction scripts (Playwright) |
|
544
|
- `pitfalls.md` — Detailed common pitfalls and solutions |