# How to Identify and Extract Layered Images (Background and Overlay) in the AI Website Cloner Template

> Learn to identify and extract layered images like background and overlay compositions from AI Website Cloner Template. Discover methods to preserve visual hierarchy and download assets.

- Repository: [JCodesMore/ai-website-cloner-template](https://github.com/JCodesMore/ai-website-cloner-template)
- Tags: how-to-guide
- Published: 2026-07-03

---

**To identify and extract layered images like background and overlay compositions, enumerate all `<img>` elements and CSS `background-image` values within each container, record their stacking contexts, and download each asset separately to preserve the visual hierarchy.**

The `JCodesMore/ai-website-cloner-template` treats every visual asset as a first-class building block, requiring precise extraction of layered graphics to ensure regenerated sites maintain pixel-perfect fidelity. When a target page uses composite visuals—such as a watercolor background paired with a foreground UI mockup or icons positioned over gradients—each layer must be captured as a separate image file. Missing any layer results in incomplete visual reproduction, even when the corresponding CSS is perfectly cloned.

## Understanding Layered Image Assets in Website Cloning

Layered graphics are fundamental to modern marketing pages, hero sections, and complex card components. The template's workflow explicitly recognizes that a **section appearing as one image often contains multiple layers** that require individual extraction.

According to the source code in [`.windsurf/workflows/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.windsurf/workflows/clone-website.md), agents must **enumerate ALL `<img>` elements and background images** within a section, including absolutely-positioned overlays. Similarly, [`.github/skills/clone-website/SKILL.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.github/skills/clone-website/SKILL.md) mandates identification of layered images comprising multiple `<img>` tags or background-images stacked within the same container. The [`docs/research/INSPECTION_GUIDE.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/docs/research/INSPECTION_GUIDE.md) further emphasizes capturing **Z-index layers**—such as navigation, modals, tooltips, and overlays—which frequently correspond to separate image assets.

## Step-by-Step Layered Image Extraction Workflow

### Inspect the DOM Structure

Open the target website in Chrome DevTools and traverse the DOM of each component or section you plan to clone. Group assets by container, treating each "section" as a single logical UI block. If a container contains **more than one image source** (e.g., an `<img>` tag plus a CSS `background-image`), treat each as a distinct layer requiring separate extraction.

### Capture All Image Sources

For every element within the target container, collect:

- **`<img>` tags**: Record `src`, `alt` attributes, and natural dimensions.
- **CSS background images**: Extract `url(...)` values from computed styles, including any data URIs.

Store these references with their associated metadata to ensure accurate reconstruction in the Next.js application.

### Record Stacking Context and Z-Index

Document each layer's stacking context by capturing `z-index`, `position`, and `opacity` values from computed styles. This metadata ensures that when you regenerate the component using `next/image` or custom wrappers, the visual hierarchy matches the original composition exactly.

## Practical Implementation: Browser and Node Scripts

### Browser Console Script for Layer Detection

Run the following JavaScript in your browser's DevTools console to harvest layered assets from the target page:

```javascript
// Collect all image sources for a given container element
function collectLayeredImages(container) {
  const layers = [];

  // <img> elements
  container.querySelectorAll('img').forEach(img => {
    layers.push({
      type: 'img',
      src: img.src,
      alt: img.alt,
      width: img.naturalWidth,
      height: img.naturalHeight,
      zIndex: getComputedStyle(img).zIndex || 0,
    });
  });

  // CSS background images (including gradients that resolve to a URL)
  const style = getComputedStyle(container);
  const bgImg = style.backgroundImage;
  if (bgImg && bgImg !== 'none') {
    const urlMatch = bgImg.match(/url\(["']?(.*?)["']?\)/);
    if (urlMatch) {
      layers.push({
        type: 'background',
        src: urlMatch[1],
        zIndex: style.zIndex || 0,
      });
    }
  }

  return layers;
}

// Example: run on every section with a data-section attribute
const allSections = document.querySelectorAll('[data-section]');
const report = {};

allSections.forEach(sec => {
  const name = sec.getAttribute('data-section') || 'unnamed';
  report[name] = collectLayeredImages(sec);
});

console.log('Layered image report:', report);

```

This function walks each UI section, pulls every `<img>` and its CSS `background-image`, and records the stacking order—directly implementing the "enumerate ALL `<img>` elements" requirement specified in the Windsurf workflow.

### Node.js Download Automation

After collecting URLs from the browser console, use this Node script (compatible with the `scripts/download-assets.mjs` placeholder) to download assets to your local project:

```javascript
import fs from 'fs';
import path from 'path';
import https from 'https';
import http from 'http';

const urls = [
  // <-- paste the URLs collected from the console output above
  // 'https://example.com/images/hero-bg.webp',
  // 'https://example.com/images/hero-fg.png',
];

const destDir = path.resolve('public/images');

if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });

function download(url) {
  const client = url.startsWith('https') ? https : http;
  return new Promise((resolve, reject) => {
    const fileName = path.basename(new URL(url).pathname);
    const filePath = path.join(destDir, fileName);
    client.get(url, res => {
      if (res.statusCode !== 200) return reject(new Error(`Failed ${url}`));
      const file = fs.createWriteStream(filePath);
      res.pipe(file);
      file.on('finish', () => file.close(() => resolve(filePath)));
    }).on('error', reject);
  });
}

(async () => {
  for (const u of urls) {
    try {
      const saved = await download(u);
      console.log(`✅ downloaded ${u} → ${saved}`);
    } catch (e) {
      console.error(`❌ error downloading ${u}`, e);
    }
  }
})();

```

Save the downloaded files to `public/images/` using a naming convention that reflects layer order (e.g., `hero-bg.webp`, `hero-fg.png`), then reference them in your React components:

```tsx
import Image from 'next/image';
import heroBg from '@/public/images/hero-bg.webp';
import heroFg from '@/public/images/hero-fg.png';

export function Hero() {
  return (
    <div className="relative h-[600px]">
      <Image src={heroBg} alt="hero background" fill />
      <Image src={heroFg} alt="hero overlay" fill className="absolute inset-0" />
    </div>
  );
}

```

## Key Source Files and Configuration

The following files in `JCodesMore/ai-website-cloner-template` define the layered image extraction protocol:

- **[`.windsurf/workflows/clone-website.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.windsurf/workflows/clone-website.md)**: Contains the primary workflow instruction to enumerate all `<img>` elements and background images, including absolutely-positioned overlays.
- **[`.github/skills/clone-website/SKILL.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/.github/skills/clone-website/SKILL.md)**: Mirrors the workflow requirements for AI agents, specifically calling out layered images with multiple `<img>` tags or background-images in the same container.
- **[`docs/research/INSPECTION_GUIDE.md`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/docs/research/INSPECTION_GUIDE.md)**: Provides the comprehensive inspection checklist for Z-index layers, navigation overlays, and modal assets.
- **[`src/app/layout.tsx`](https://github.com/JCodesMore/ai-website-cloner-template/blob/main/src/app/layout.tsx)**: Loads the `public/images` directory into the Next.js application, making extracted assets available to components.

## Summary

- **Layered images** require individual extraction of each `<img>` tag and CSS `background-image` within a container to preserve visual fidelity.
- **Browser DevTools** provide the necessary `getComputedStyle` API to capture both image URLs and stacking context data (z-index, position).
- **Naming conventions** like `section-bg.webp` and `section-fg.png` maintain clarity when multiple layers belong to the same UI component.
- **Next.js Image components** reconstruct the original composition using absolute positioning based on the captured metadata.

## Frequently Asked Questions

### How do I distinguish between decorative backgrounds and content images when extracting layers?

Inspect the `alt` attribute and ARIA roles of `<img>` elements—functional content images typically have descriptive alt text, while decorative backgrounds implemented via CSS usually lack alternative text. Additionally, check the `role` attribute: images marked as `role="img"` with meaningful labels are content, whereas purely presentational assets often use `role="presentation"` or appear only as `background-image` values.

### What if the target site uses CSS sprites or data URIs for layered graphics?

For CSS sprites, calculate the `background-position` and `background-size` values from the computed styles to determine the specific sprite coordinates, then use canvas or image processing tools to slice the individual assets. Data URIs embedded in CSS can be decoded directly—the Node script handles these by writing the base64 content to binary files, preserving transparency and formatting.

### Should I extract SVG overlays differently from raster images like PNG or WebP?

Yes. SVG assets should be saved as individual `.svg` files in `public/images/` rather than rasterized, allowing the Next.js application to scale them losslessly. When the browser console script detects an SVG source (either as an `<img>` src or CSS background), flag it for vector preservation to maintain crisp edges at all resolutions.

### How do I handle dynamically loaded images that appear only after scrolling or interaction?

Use Chrome DevTools' **Network** panel to monitor image requests triggered by scroll events or JavaScript interactions. Alternatively, programmatically trigger these events in the console using `element.scrollIntoView()` or `element.click()` before running the extraction script, ensuring lazy-loaded layers are present in the DOM when you collect the asset URLs.