How to Organize and Reference Assets from Target Sites Using ai-website-cloner-template
The ai-website-cloner-template stores all downloaded assets in the public/ folder while preserving the original directory structure from the target site, enabling reference via absolute paths in Next.js components.
The ai-website-cloner-template repository provides a systematic approach to handling media files extracted during website cloning. When replicating a target site, managing images, videos, fonts, and icons requires strict organization to ensure components render correctly. This guide explains how the template structures asset storage and the exact methods for referencing those files in your generated Next.js application.
Asset Storage Conventions in public/
The template follows a strict convention for binary files extracted from target websites. Every asset routes to a specific subdirectory under public/, leveraging Next.js static file serving capabilities.
The Standard Folder Structure
According to the README's Foundation step at [README.md‑L94](https://github.com/JCodesMore/ai-website-cloner-template/blob/master/README.md#L91), the template organizes assets into three primary directories:
public/images/– Raster images including PNG, JPG, and WebP filespublic/videos/– Video assets such as MP4 and WebM formatspublic/seo/– Favicons, Open Graph images, and manifest files
Preserving Source Hierarchy
When the cloning skill executes, the scripts/download-assets.mjs helper preserves the original directory structure from the target URL. A logo located at https://example.com/assets/logo.svg maps directly to public/images/assets/logo.svg in your local project. This mirroring simplifies traceability when auditing or replacing specific assets.
The workflow description detailing this behavior appears in the platform-specific skill files, specifically the Windsurf workflow at [.windsurf/workflows/clone-website.md‑L190](https://github.com/JCodesMore/ai-website-cloner-template/blob/master/.windsurf/workflows/clone-website.md#L183).
Downloading Assets from Target Sites
The asset acquisition process uses a Node.js script that walks the DOM, collects resource URLs, and streams files to the appropriate public/ subdirectories.
The download-assets.mjs Script
The script identifies every <img> tag, CSS background-image URL, and <video> source, then writes files while maintaining subdirectory depth. Below is the core logic for saving remote assets:
// scripts/download-assets.mjs
import { promises as fs } from "fs";
import path from "path";
import fetch from "node-fetch";
/**
* Save a remote file to the public folder while preserving its original path.
*/
async function saveAsset(url: string, root = "public") {
const { pathname } = new URL(url);
// Remove leading slash and prepend the appropriate public sub-folder
const relative = pathname.replace(/^\/+/, "");
const dest = path.join(root, "images", relative); // assumes image; adjust for videos
await fs.mkdir(path.dirname(dest), { recursive: true });
const res = await fetch(url);
if (!res.ok) throw new Error(`Failed to fetch ${url}`);
const buffer = await res.buffer();
await fs.writeFile(dest, buffer);
console.log(`✓ saved ${url} → ${dest}`);
}
// Example usage – called for each discovered asset URL
await saveAsset("https://example.com/assets/logo.png");
Supported Asset Types
The template handles multiple binary formats during the cloning process:
- Images: PNG, JPG, WebP, SVG (raster), and GIF files route to
public/images/ - Videos: MP4, WebM, and MOV files populate
public/videos/ - SEO Assets: Favicons, Apple touch icons, and Open Graph images land in
public/seo/
Referencing Assets in Next.js Code
Because all assets reside under public/, you reference them using absolute URL paths starting with a slash. This eliminates the need for import statements and enables zero-runtime-code serving.
Using the Image Component
For raster images, employ the built-in <Image/> component to enable automatic optimization. The src attribute points to the absolute path inside public/:
import Image from "next/image";
export function Logo() {
return (
<Image
src="/images/assets/logo.svg" // ← path inside `public/`
alt="Company logo"
width={200}
height={80}
priority // optional: preload for above-the-fold assets
/>
);
}
CSS Background Images
Reference downloaded images within CSS using standard url() syntax with absolute paths:
.hero {
background-image: url("/images/hero/background.webp");
background-size: cover;
}
Video and Media Files
For video assets stored in public/videos/, use the HTML5 <video> element with an absolute src path:
export function HeroVideo() {
return (
<video
src="/videos/hero/intro.mp4"
autoPlay
muted
loop
className="w-full h-auto"
/>
);
}
SEO Assets and Favicons
Reference favicons and Open Graph images in your layout or head component using the public/seo/ directory:
import Head from "next/head";
export default function SiteHead() {
return (
<Head>
<link rel="icon" href="/seo/favicon.ico" />
<meta property="og:image" content="/seo/og-image.png" />
</Head>
);
}
Handling SVG Icons
Individual SVG icons extracted from the target site undergo conversion into React components. The template gathers these in src/components/icons.tsx, where each component imports the SVG directly from public/images/ and re-exports it. This centralized approach allows consistent icon usage throughout the UI while maintaining the source file in the public directory.
Benefits of the Public Folder Strategy
Organizing assets under public/ provides specific advantages for cloned websites:
- Zero Runtime Overhead: Next.js serves
public/files without bundling them into your JavaScript, reducing client-side payload - Structural Fidelity: Mirroring the source site's directory layout simplifies asset replacement and auditing
- Exact Path Resolution: Builder agents receive precise file paths in component specifications, eliminating guesswork and ensuring pixel-perfect replication
- SEO Preservation: Keeping favicons and OG images in
public/seo/maintains the original site's search engine optimization metadata
Summary
- Store all cloned assets under
public/with subdirectories forimages,videos, andseofiles - The
scripts/download-assets.mjshelper preserves the target site's original directory hierarchy during download - Reference assets using absolute paths starting with
/rather than relative imports - Use Next.js
<Image/>for raster graphics, absolute URLs for CSS backgrounds, and standard HTML tags for video content - SVG icons convert to React components in
src/components/icons.tsxwhile their source files remain inpublic/images/
Frequently Asked Questions
Where does ai-website-cloner-template store downloaded images?
The template stores all raster images in public/images/, maintaining the subdirectory structure from the source website. For example, an image from https://example.com/assets/photo.jpg saves to public/images/assets/photo.jpg in your local project.
How do I reference a cloned video file in my component?
Reference video files using an absolute path pointing to the public/videos/ directory. Use the HTML5 <video> element with the src attribute set to /videos/ followed by the preserved subdirectory path, such as /videos/hero/intro.mp4.
What happens to SVG icons extracted from the target site?
The template converts extracted SVG icons into React components and collects them in src/components/icons.tsx. Each component references the original SVG file stored in public/images/, allowing you to import and use icons throughout your application while keeping source assets organized.
Why use absolute paths instead of imports for assets?
Absolute paths starting with / leverage Next.js static file serving from the public/ directory, eliminating the need for build-time imports. This approach reduces bundle size, preserves the original URL structure for SEO consistency, and allows builder agents to generate exact references without resolving relative import paths.
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 →