Approaches for Handling Layered Images in Website Cloning Tasks: Detection and Implementation

Layered images in website cloning require detecting both <img> tags and CSS background-image values across the entire DOM tree to preserve pixel-perfect visual fidelity.

When cloning a website using the JCodesMore/ai-website-cloner-template repository, a single visual element often comprises multiple stacked image layers—background gradients, foreground mockups, and overlay icons. Missing any layer results in a clone that looks incomplete or visually inaccurate, making proper handling of these assets essential for high-fidelity replication.

Why Layered Assets Matter in Website Cloning

Visual components such as hero sections, cards, and modals are rarely single images. Instead, they are compositions assembled from several stacked layers, each with distinct positioning and z-index values.

  • Visual fidelity – Overlays, gradients, and decorative icons contribute to the design’s visual weight. Omitting any layer breaks the pixel-perfect match.
  • Component composition – UI elements often use position: absolute and z-index stacking contexts that depend on all layers being present.
  • AI generation pitfalls – Automated agents that scrape only the top-most image generate components with blank spaces where overlays should appear.

According to the source code in .opencode/commands/clone-website.md (lines 55-56), the authors explicitly warn: "Layered assets matter. A section that looks like one image is often multiple layers — a background watercolor/gradient, a foreground UI mockup PNG, an overlay icon. Inspect each container's full DOM tree and enumerate ALL <img> elements and background images within it, including absolutely-positioned overlays."

Detecting Layered Images in the DOM

Traversing the Full DOM Tree

To capture every visual layer, you must inspect the complete DOM structure of each container:

  1. Walk container trees – Examine every section, component wrapper, and grouping element.
  2. Collect <img> tags – Record src, alt, dimensions, and computed CSS properties including position and z-index.
  3. Capture CSS backgrounds – Use getComputedStyle(element).backgroundImage to detect decorative layers not implemented as <img> tags.
  4. Record context – Store parent class names and sibling counts to identify overlay patterns and stacking order.

The Asset Discovery Script

The repository provides a JavaScript snippet that runs inside a browser MCP (such as Playwright or Chrome DevTools) during the Asset Discovery phase. This script extracts all image layers, videos, background images, and fonts:

// Run this via browser MCP to discover all assets
JSON.stringify({
  images: [...document.querySelectorAll('img')].map(img => ({
    src: img.src || img.currentSrc,
    alt: img.alt,
    width: img.naturalWidth,
    height: img.naturalHeight,
    // Include parent info to detect layered compositions
    parentClasses: img.parentElement?.className,
    siblings: img.parentElement ? [...img.parentElement.querySelectorAll('img')].length : 0,
    position: getComputedStyle(img).position,
    zIndex: getComputedStyle(img).zIndex
  })),
  videos: [...document.querySelectorAll('video')].map(v => ({
    src: v.src || v.querySelector('source')?.src,
    poster: v.poster,
    autoplay: v.autoplay,
    loop: v.loop,
    muted: v.muted
  })),
  backgroundImages: [...document.querySelectorAll('*')].filter(el => {
    const bg = getComputedStyle(el).backgroundImage;
    return bg && bg !== 'none';
  }).map(el => ({
    url: getComputedStyle(el).backgroundImage,
    element: el.tagName + '.' + el.className?.split(' ')[0]
  })),
  svgCount: document.querySelectorAll('svg').length,
  fonts: [...new Set([...document.querySelectorAll('*')].slice(0,200).map(el => getComputedStyle(el).fontFamily))],
  favicons: [...document.querySelectorAll('link[rel*="icon"]')].map(l => ({ href: l.href, sizes: l.sizes?.toString() }))
});

This code is referenced in .opencode/commands/clone-website.md at lines 94-102.

Downloading and Organizing Image Layers

After the discovery script returns a JSON payload, the workflow delegates to a Node.js utility for retrieval:

node scripts/download-assets.mjs \
  --images assets.json \
  --output public/images

The scripts/download-assets.mjs utility (referenced in the workflow documentation) should implement three critical behaviors:

  • Parallelize downloads using 4-6 concurrent requests to minimize latency.
  • De-duplicate identical URLs to prevent redundant files.
  • Preserve naming context – When two layers share filenames but belong to different components, prefix filenames with the component name (e.g., hero-bg.webp, hero-overlay.png).

Downloaded assets are stored in public/images/ for static serving in Next.js.

Implementing Layered Assets in Components

When reconstructing a component, import each layer as a separate asset and restore the original stacking context using CSS positioning.

For a hero section with three layers (background, mockup, overlay):

import Image from 'next/image';
import heroBg from '@/public/images/hero-bg.webp';
import heroMockup from '@/public/images/hero-mockup.png';
import heroOverlay from '@/public/images/hero-overlay.svg';

export function HeroSection() {
  return (
    <section className="relative overflow-hidden">
      {/* Background layer */}
      <Image src={heroBg} alt="Background watercolor" fill className="object-cover" />
      {/* Foreground mockup */}
      <Image src={heroMockup} alt="UI mockup" width={1200} height={800} className="absolute inset-0 m-auto" />
      {/* Overlay icon */}
      <Image src={heroOverlay} alt="Decorative icon" width={80} height={80} className="absolute top-4 right-4" />
    </section>
  );
}

For SVG overlays, convert them to React components using the src/components/icons.tsx utility:

import { HeroOverlayIcon } from '@/components/icons';

export function HeroSection() {
  return (
    <section className="relative">
      <Image src={heroBg} alt="Background" fill />
      <Image src={heroMockup} alt="Mockup" className="absolute inset-0" />
      <HeroOverlayIcon className="absolute top-4 right-4 w-20 h-20" />
    </section>
  );
}

Validation Checklist

During the Pre‑Dispatch Checklist (items 41-42 in .opencode/commands/clone-website.md), confirm that every layer has been captured:

  • ✅ All <img> tags inside a container are listed in the discovery output.
  • ✅ All CSS background-image values are enumerated.
  • ✅ Parent class names and z-index values are recorded to reconstruct overlay order.
  • ✅ Downloaded assets reside in public/ and are correctly referenced in component code.

Key Files for Layered Image Handling

File Purpose
.opencode/commands/clone-website.md Contains authoritative guidance on layered assets and the discovery script (lines 55-56, 94-102).
scripts/download-assets.mjs Node.js utility for fetching and organizing discovered assets.
src/components/icons.tsx Destination for extracted SVG icons that form part of layered compositions.
public/images/ Storage directory for all downloaded image layers.
src/app/layout.tsx & src/app/globals.css May define global background-image layers requiring duplication.

Summary

  • Layered images are composite visual elements built from multiple stacked sources requiring complete enumeration.
  • Detection requires traversing the full DOM to capture both <img> tags and CSS background-image values, including absolutely-positioned overlays.
  • Organization depends on parallel downloading, URL de-duplication, and contextual naming to preserve component relationships.
  • Implementation restores original stacking contexts using Next.js Image components with position: absolute and z-index properties.
  • Validation against the Pre-Dispatch Checklist ensures no visual layers are omitted before deployment.

Frequently Asked Questions

How do I detect CSS background images that are not <img> tags?

Use getComputedStyle(element).backgroundImage on every element in the DOM tree. The provided discovery script filters for values that are not 'none' and captures the URL along with the element identifier. This catches decorative gradients and patterns that traditional HTML scrapers miss.

What is the best way to handle naming conflicts when downloading multiple layers?

Prefix each filename with its parent component or container name (e.g., card-bg.jpg, card-icon.svg). The download-assets.mjs script should reference the parentClasses field from the discovery JSON to generate these contextual prefixes, preventing identical filenames from different components from overwriting each other.

Should I convert SVG overlays to React components or use them as image files?

Convert SVG overlays to React components using the src/components/icons.tsx utility. This approach allows dynamic styling via props (color, size) and ensures the overlay renders crisply at any resolution. Use the <Image> component for SVGs only when you need Next.js optimization features and the SVG is purely decorative.

Why does my cloned component look empty even though I downloaded the main image?

You likely missed an absolutely-positioned overlay or a CSS background layer. Check the position and z-index values in the discovery output. Components often use transparent PNGs or SVGs positioned over background gradients—if the foreground layer is missing, the background appears blank or incomplete. Verify checklist items 41-42 in the clone command documentation to ensure all layers are enumerated.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →