How to Identify and Extract Layered Image Compositions with ai-website-cloner-template
To identify and extract layered image compositions with ai-website-cloner-template, run the browser-side detection script from .windsurf/workflows/clone-website.md to capture parent context, sibling counts, and CSS positioning data, then flag any container with multiple images or background-image declarations as a layered asset.
The ai-website-cloner-template treats stacked visual assets as first-class extraction targets to ensure cloned websites remain pixel-perfect. Missing a single layer—such as a foreground illustration or background gradient—breaks the visual integrity of the final build. This guide walks through the exact detection logic embedded in the repository's workflow files to help you capture every raster and SVG component.
Understanding Layered Image Compositions
Layered images are UI sections that appear as single pictures but consist of multiple raster or SVG assets stacked via CSS. A typical example combines a background watercolor, a mid-ground photo, and foreground icon overlays. The template's extraction workflow explicitly targets these compositions because omitting any layer produces an incomplete clone.
Detection Logic Locations
The identification system spans several key files in the JCodesMore/ai-website-cloner-template repository:
.windsurf/workflows/clone-website.md(lines 88-124): Contains the primary asset-discovery script and narrative guidance on enumerating all<img>and background-image elements..opencode/commands/clone-website.md: Reproduces the same layered-asset guidance for command-line interface usage.docs/research/INSPECTION_GUIDE.md: High-level audit checklist referencing "Z-index layers" and "Layered assets matter."
How the Detection Algorithm Works
The algorithm relies on parent-context analysis within the browser's DOM. When you run the discovery script via a browser MCP tool (Chrome DevTools, Playwright, etc.), it performs the following steps:
- Iterates over every
<img>element to extractsrc,alt, natural dimensions, and computed CSS properties. - Records
parentClassesfromimg.parentElement?.classNameto identify shared containers. - Counts
siblingCountusing[...img.parentElement.querySelectorAll('img')].lengthto detect stacked images. - Captures
positionandzIndexfromgetComputedStyleto spot absolutely-positioned overlays. - Scans all DOM nodes for non-
nonebackgroundImagevalues.
Any container exhibiting siblingCount > 1 or containing both an <img> and a background-image is flagged as a layered composition candidate.
Running the Browser Extraction Script
Execute the following JavaScript in your browser MCP console to generate the layer map:
// Run in browser MCP (e.g., Chrome DevTools or Playwright)
const layers = (() => {
const imgs = [...document.querySelectorAll('img')].map(img => ({
src: img.src || img.currentSrc,
alt: img.alt,
width: img.naturalWidth,
height: img.naturalHeight,
parentClasses: img.parentElement?.className ?? '',
siblingCount:
img.parentElement
? [...img.parentElement.querySelectorAll('img')].length
: 0,
position: getComputedStyle(img).position,
zIndex: getComputedStyle(img).zIndex,
}));
const bgs = [...document.querySelectorAll('*')]
.filter(el => {
const bg = getComputedStyle(el).backgroundImage;
return bg && bg !== 'none';
})
.map(el => ({
url: getComputedStyle(el).backgroundImage,
element: `${el.tagName.toLowerCase()}.${el.className.split(' ')[0] || ''}`,
}));
return JSON.stringify({ imgs, bgs }, null, 2);
})();
console.log(layers);
Reading the Layer Map Output
The script returns a JSON object with imgs and bgs arrays. Consider this output from a hero-section container:
{
"imgs": [
{
"src": "/images/hero-bg.jpg",
"alt": "",
"width": 1920,
"height": 1080,
"parentClasses": "hero-section",
"siblingCount": 2,
"position": "relative",
"zIndex": "auto"
},
{
"src": "/images/hero-illustration.png",
"alt": "",
"width": 400,
"height": 350,
"parentClasses": "hero-section",
"siblingCount": 2,
"position": "absolute",
"zIndex": "10"
}
],
"bgs": [
{
"url": "url(\"/images/hero-gradient.png\")",
"element": "section.hero-section"
}
]
}
Here, the hero-section container contains two sibling images (siblingCount: 2) plus a background-image, confirming a three-layer composition: gradient background, base photo, and overlay illustration.
From Detection to Project Integration
Once you identify a layered composition, follow these steps to integrate it into your clone:
-
Download assets to
public/images/, preserving original filenames or using descriptive prefixes (e.g.,hero-bg.jpg,hero-illustration.png). -
Document in the component spec under the Assets section (referencing the spec template in
.windsurf/workflows/clone-website.mdlines 57-61):## Assets - Background image: `public/images/hero-gradient.png` - Base photo: `public/images/hero-bg.jpg` - Overlay illustration: `public/images/hero-illustration.png` -
Implement in React using absolute positioning to recreate the stack:
// src/components/HeroSection.tsx export default function HeroSection() { return ( <section className="relative overflow-hidden"> <img src="/images/hero-bg.jpg" alt="" className="w-full h-auto object-cover" /> <img src="/images/hero-illustration.png" alt="" className="absolute inset-0 m-auto w-48 h-48" /> </section> ); }
Production Checklist
Before finalizing your clone, verify:
- The layer detection script executed without errors in the browser context.
- All containers with
siblingCount > 1or background-images appear in the JSON output. - Every
srcandurlpath has a corresponding file inpublic/images/. - The component spec includes an Assets block listing all layers.
- The React component uses Tailwind
absolute,relative, andz-indexutilities to match original positioning. -
npm run buildandnpx tsc --noEmitpass without type errors.
Summary
- Layered compositions require detecting multiple images or background-images within shared DOM containers.
- The browser-side script in
.windsurf/workflows/clone-website.mdextractsparentClasses,siblingCount, and CSS positioning to identify these stacks. - JSON output reveals layered assets when
siblingCountexceeds 1 or background-images coexist with<img>tags. - Store extracted layers in
public/images/and reference them in the component spec's Assets section. - Reconstruct visual stacks in React using absolute positioning and z-index management.
Frequently Asked Questions
What defines a "layered image composition" in ai-website-cloner-template?
A layered image composition is any UI section visually constructed from multiple raster or SVG assets—such as background gradients, base photographs, and foreground illustrations—rather than a single image file. The template flags these separately because each layer must be extracted individually to preserve the original design's fidelity.
How does the detection script differentiate between standalone images and layered assets?
The script analyzes parent container context via the siblingCount and parentClasses fields. Standalone images typically show siblingCount: 1 within their parent, while layered assets demonstrate siblingCount > 1 or coexist with CSS background-image declarations on the same container, indicating stacked elements.
Where should extracted layer files be stored in the project?
Download all identified assets into the public/images/ directory at the project root. Maintain descriptive filenames that reflect their role (e.g., hero-bg.jpg, hero-illustration.png) to ensure the component spec and React imports remain readable and maintainable.
Can the asset download process be automated?
Yes. After running the browser detection script, pipe the JSON output to a Node.js script (such as scripts/download-assets.mjs) that iterates over the src and url fields, downloading each file to public/images/. This automation ensures no layer is missed during bulk extraction operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →