cloning-websites-to-weaverse — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cloning-websites-to-weaverse (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this repo-specific workflow to turn a reference website into maintainable Weaverse pages. Optimize for reusable sections, accurate section matching, and clear schema boundaries, not one-off screenshot cloning.
Priority order: brand guideline beats source website on visual conflicts. The source website drives page structure, content flow, interaction patterns, and merchandising logic.
.guides/brand-guideline.md is the source of truth.
If the live site conflicts with the brand guideline, you MUST follow the brand guideline. This is mandatory even when:
make it look like the live siteUse this rule:
In conflict cases, explicitly state: I will match the live site where possible, but the brand guideline is the source of truth for conflicting decisions.
app/sections/ and Weaverseapp/styles/app.css, and app/weaverse/schema.server.tsDo not use this for tiny copy-only edits or isolated bug fixes.
.guides/brand-guideline.mdsections.mdapp/weaverse/components.tsapp/routes/clone-preview.$page.tsx) that renders the full cloned page as React + Tailwind — user must approve this before section decomposition beginsThe clone preview route is the verification checkpoint. The design spec and content manifest together form the complete handoff to generating-weaverse-project-json.
| Need | Source |
|---|---|
| Colors, type, logo, shape language, legal rules | .guides/brand-guideline.md |
| Section order, content hierarchy, CTA flow, merchandising | crawled reference website |
| Existing reusable section matches and child block constraints | sections.md |
| Registry of currently available Weaverse components | app/weaverse/components.ts |
| Shared tokens and repeated cross-section styles | app/styles/app.css |
| Sitewide editable controls | app/weaverse/schema.server.ts |
| Section-local content and controls | section schema in app/sections/* |
.guides/brand-guideline.md first.sections.md exists and is trustworthy before doing section matching. firecrawl scrape "<url>" --format markdown,html -o .firecrawl/<site>-<page>.jsonThis returns both clean markdown (for content extraction) and raw HTML (for layout/media analysis) in one request. For pages with JS-rendered content, add --wait-for 3000.
firecrawl crawl "<url>" --include-paths <relevant-paths> --limit 10 --max-depth 1 --wait -o .firecrawl/<site>-crawl.json<video>, <source>, <iframe>, <embed> URLs from the HTML (see Firecrawl Rules → Media source extraction)app/routes/clone-preview.$page.tsx that renders the entire page as React + Tailwind. This is a single file with all visual blocks rendered inline — no separate component files. Include desktop and mobile responsive styles. The route must be visually faithful to the origin page while using the repo's Tailwind setup and applying brand guideline tokens where they conflict with the origin. Use clearly commented section markers (e.g., {/* === HERO === */}, {/* === PRODUCT GRID === */}) to delineate each visual block — these markers become the splitting boundaries for section decomposition later.Present the user with:
http://localhost:3456/clone-preview/<page-slug>)Do not proceed to step 9 until the user explicitly confirms approval.
If the user requests changes:
static-image, video, animation, product-media, collection-image, or external-embed.background-overlay (text on top of full-bleed media), side-by-side (text beside media in columns), stacked (text above or below media), card-grid (repeated cards with image+text), card-slider (one card visible at a time in a carousel).single-full-bleed, split-columns, grid, slider/carousel, overflow-rail, flex-wrap, marquee/ticker.static, autoplay-carousel, snap-scroll, arrow-navigation, fade-transition, auto-scroll-marquee.These classifications come from the raw HTML output — look for slider components (Swiper, Flickity, Slick, custom <slider-component>, data-slider), grid classes, flex patterns, <video> elements, and absolute-positioned text overlays.
sections.md using the layout matching priority defined there:Then classify as:
REUSE_EXISTINGADAPT_EXISTINGCREATE_NEW_REUSABLE_SECTIONIf the source block's composition, layout mechanism, or media type does not match the candidate section, that mismatch must be resolved — either by choosing a different section or by flagging an adaptation requirement. Never accept a layout mismatch as a "trade-off" without first searching the full section registry for a better match.
Deep structural verification (mandatory for every REUSE or ADAPT classification): After classifying a block, read the candidate section's source code (app/sections/<section>/index.tsx and its child files) and verify that its schema settings can produce the exact visual output the origin block requires. Check:
9:16, 3:2), or is a ratio hardcoded?75/25), or is the max width capped lower?If any schema capability is missing, reclassify from REUSE_EXISTING to ADAPT_EXISTING and document the specific gap. If multiple capabilities are missing, consider CREATE_NEW_REUSABLE_SECTION instead.
app/styles/app.cssapp/weaverse/schema.server.tsschemaapp/weaverse/components.ts.app/routes/clone-preview.$page.tsx once the final Weaverse-rendered page matches the approved preview.The content manifest is the bridge between this skill and generating-weaverse-project-json. Without it, the JSON generator guesses content and produces placeholder-filled exports that do not match the source.
After crawling and extracting the source page DNA, build a concrete per-section table before doing section matching. The manifest must cover every visual block on the source page.
| Column | Description |
|---|---|
| Block # | Sequential position on the page |
| Block name | Short label (e.g., "Hero", "Netflix promo", "Connect CTA") |
| Media type | static-image, video, animation, product-media, collection-image, or external-embed |
| Image/video URLs | Every real asset URL for that block, directly from the crawl output. List all — primary image, secondary images, logo overlays, background images. Use the full CDN URL as it appears in the crawl. |
| Text content | Headings, subheadings, body copy, CTA labels — exact wording from the source |
| Link targets | Every URL the block links to (internal paths or external URLs) |
| Shopify refs | Product handles/IDs or collection handles/IDs if the block is product- or collection-driven |
| Notes | Anything unusual: external embed, partner logo with external link, video autoplay, etc. |
<img> src attributes and visible image URLs — use those exact values.video or external-embed blocks, populate the Image/video URLs column with the actual video source URL (MP4, WebM, HLS, YouTube embed, etc.) extracted from the HTML format output — not the poster/thumbnail image. If a thumbnail is also useful (e.g., as a fallback), list both with clear labels (Video (MP4): ..., Thumbnail: ...).MISSING — [describe what should be here] so the JSON generator knows to flag it rather than silently substituting a placeholder.generating-weaverse-project-json.Add the content manifest as a section in the design spec file (e.g., design.md) or as a separate content-manifest.md in the same spec folder.
The clone preview route is the verification checkpoint between scraping and section decomposition. It lets the user visually confirm the clone is accurate before any Weaverse mapping work begins.
A single Hydrogen route file at app/routes/clone-preview.$page.tsx that renders the entire cloned page as React + Tailwind. It is:
import type {MetaFunction} from '@remix-run/react';
export const meta: MetaFunction = () => {
return [{title: 'Clone Preview — <page name>'}];
};
export default function ClonePreview() {
return (
<div className="clone-preview">
{/* === HERO === */}
<section className="relative w-full h-screen ...">
{/* hero content */}
</section>
{/* === PRODUCT GRID === */}
<section className="max-w-7xl mx-auto py-16 ...">
{/* product grid content */}
</section>
{/* === NEWSLETTER CTA === */}
<section className="bg-primary text-white py-12 ...">
{/* CTA content */}
</section>
</div>
);
}<style> blocks..guides/brand-guideline.md, the preview must already reflect the brand version — not the origin. This prevents the user from approving something that will change later.{/* === BLOCK NAME === */} comments to delineate each section-sized block. These markers are the splitting boundaries for step 9 (section segmentation). The block names should match the content manifest's "Block name" column.<video> tag with autoplay. The preview does not need pixel-perfect interaction parity, but should demonstrate the core behavior so the user can judge whether it works.$page slug (e.g., /clone-preview/homepage, /clone-preview/about). Do not put multiple pages in one route.After generating the preview route, stop and wait for user confirmation:
| Phase | Status of preview route |
|---|---|
| Steps 1-6 (scrape + manifest) | Does not exist yet |
| Step 7 (generate preview) | Created at app/routes/clone-preview.$page.tsx |
| Step 8 (approval checkpoint) | User reviews, may request iterations |
| Steps 9-14 (section decomposition + build) | Kept as side-by-side reference |
| Step 15 (cleanup) | Deleted after Weaverse page is verified |
--format markdown,html). The markdown is for content extraction; the HTML is for layout classification and media source extraction.--include-paths to scope the crawl to relevant paths..firecrawl/ directory with descriptive names (e.g., .firecrawl/example-homepage.json).Markdown output strips <video>, <source>, <iframe>, and <embed> elements. These are invisible in the markdown but carry critical asset URLs. This is why both formats are required.
From the HTML format output, extract:
<video> and <source src="..."> — MP4, WebM, HLS stream URLs<iframe src="..."> — YouTube, Vimeo, or other embed URLsdata-src, data-video-url, or other lazy-load attributes on media containersSearch the HTML for patterns like .mp4, .webm, .m3u8, youtube.com/embed, vimeo.com, player. to find video sources that the markdown output missed.
If a section-sized block has a video or embed in the HTML but only an image (thumbnail/poster) in the markdown output, the block's primary media type is video or external-embed, not static-image. Record the actual video/embed URL in the content manifest, not the thumbnail.
From the HTML format output, also extract layout structure for each section:
<slider-component>, data-slider, data-slider-fullwidth, data-dots, autoplay options in JSON attributes).--COLUMNS), responsive breakpoint classes.brick__section, split-width classes (brick__block--three-quarters), reversed order classes.<ticker-bar>, marquee autoplay attributes, continuous scroll behavior.This HTML analysis is mandatory — do not classify layout behavior from the markdown output alone. Markdown output is never sufficient for pages that contain sliders, overlays, or interactive components.
sections.md Rulessections.md is the migration guide for choosing the best existing Weaverse section in this repo.
It must inventory the registered Weaverse section system and child blocks with:
If sections.md is missing, create it before mapping source sections.
If sections.md is stale or incomplete, update it from the real registry and schema files before making reuse decisions.
Do not guess section capability from current styling alone. Use the actual schema and composition constraints.
Use this analysis sequence from app/skill.md:
static-image, video, animation, product-media, collection-image, or external-embed. This classification determines whether the matched section can support the block without adaptation.background-overlay, side-by-side, stacked, card-grid, or card-slider. Determine this from the HTML — look at whether text is inside an absolutely-positioned overlay on media, in a separate flex/grid column beside media, or stacked above/below media.single-full-bleed, split-columns, grid, slider/carousel, overflow-rail, flex-wrap, or marquee/ticker. Look for slider components, grid CSS, flex patterns, and scroll containers in the HTML.static, autoplay-carousel, snap-scroll, arrow-navigation, fade-transition, or auto-scroll-marquee. Look for autoplay attributes, navigation arrows/dots, and scroll-snap CSS.sections.md.sections.md:background-overlay block must not be matched to a side-by-side section.slider/carousel block must not be matched to a grid section.autoplay-carousel block needs a Swiper-based section, not a static grid.sections.md and app/weaverse/components.ts for another section that supports the block's media type (e.g., if the block is video, look for sections with videoURL, video, or react-player support).card-slider (one item at a time with navigation) must match slideshow, not product-spotlight-rail (grid)background-overlay (text on full-bleed image) must match hero-image or promotion-grid, not image-with-text (side-by-side)stacked layout (image above text, centered) may need columns-with-images or a rich-text section, not image-with-text (which goes side-by-side on desktop)After identifying a candidate section via schema matching, read the section's actual source code (app/sections/<section>/index.tsx and child files) before accepting the match. Verify each of the following against the origin block's requirements:
| Check | What to verify |
|---|---|
| Aspect ratio support | Does the schema expose an aspect ratio selector that includes the ratios the origin uses? Many sections hardcode a single ratio (e.g., aspect-square). |
| Media type match | An image-only section cannot substitute for a video block. Check for videoURL, <video>, or player component support. |
| Responsive image variants | If the origin uses <picture> with separate <source> elements for mobile/desktop, a single image field is not a match. Look for imageMobile, imageDesktop, or responsive breakpoint logic. |
| Split ratios | Check the schema's width constraints. If the origin uses a 75/25 image-text split but the section caps image width at 60%, that is an adaptation requirement. |
| Child block types | Verify the section's childTypes or inspector.children allows the blocks the origin needs (buttons, badges, countdown timers, rating stars, etc.). |
| Animation / interaction | A static section cannot reproduce marquee scrolling, parallax, or auto-advance transitions. Check for animation props, Swiper config, or CSS animation support. |
| Text readability aids | If the origin places text over an image with a gradient backdrop or color overlay, the section must support overlayColor, overlayOpacity, or equivalent. A plain image section with no overlay is not a match. |
If any check fails, the section cannot be classified as REUSE_EXISTING. Reclassify as ADAPT_EXISTING with the specific gaps documented, or CREATE_NEW_REUSABLE_SECTION if multiple checks fail.
app/styles/app.css only when they are shared primitives: variables, font hooks, repeated background treatments, or reusable utilities.app/weaverse/schema.server.ts only when they should be editable across the storefront.app/routes/clone-preview.$page.tsx (temporary — preview checkpoint)app/sections/app/weaverse/components.tsapp/styles/app.cssapp/weaverse/schema.server.tssections.md.guides/brand-guideline.mdapp/styles/app.cssapp/weaverse/schema.server.tssections.md and guessing which section is closestproduct-spotlight-rail for a full-screen slideshow)image-with-text for a full-width hero with text on top of image)image-with-text for a centered image-above-text block)sections.md summaries describe purpose, not full capabilityvideoURL or player component support{/* === BLOCK NAME === */} comments, the preview cannot serve as a splitting reference for section decomposition| Excuse | Reality |
|---|---|
| "Leadership will compare screenshots" | Screenshot parity does not override the repo's brand rules. Match layout with the source site; match tokens with the brand guideline. |
| "The live site is newer than the guideline" | Unless the repo guidance is updated, .guides/brand-guideline.md remains the implementation source of truth. |
| "I'll copy the live colors first, then clean up later" | This usually leaves bad globals behind. Set the right tokens first, then style sections against them. |
| "I can tell which section matches by looking at the UI" | Visual similarity is not enough. Use sections.md and the actual schema constraints. Check composition, layout mechanism, and interaction — not just how the colors look. |
| "I only need screenshots, not a crawl" | Screenshot memory misses hierarchy, repeated modules, and linked-page patterns. Scrape the source site with Firecrawl first. |
| "I'll fill in the real images later" | The JSON generator cannot recover asset URLs you did not capture. Build the content manifest now, from the crawl output. |
| "The section only needs an image, the video is nice-to-have" | If the source block is a video, the matched section must support video or the mismatch must be flagged. Do not silently downgrade media types. |
| "It's the same concept so one section is fine" | If the same concept appears with two different visual treatments on the page, it needs two separate section blocks. |
| "It's basically a grid, just different styling" | A slider showing one item at a time with arrows/dots is NOT "basically a grid." Check the HTML for slider components before classifying layout. |
| "image-with-text works for everything with an image and text" | image-with-text is specifically a side-by-side split layout. It does NOT work for full-bleed overlays, stacked vertical layouts, or card grids. Match composition first. |
| "The origin sections are adjacent so I can merge them" | If the origin has two separate HTML sections (e.g., a background video + a separate rich-text block), keep them as two separate Weaverse sections. Merging changes the layout behavior. |
| "The section name matches, so it should work." | Section names describe purpose, not capability. Read the schema source code to verify every visual requirement — aspect ratios, responsive images, split widths, child types, animation support. |
| "The section has an image field, so it supports images." | One image field does not mean responsive images. Check for separate mobile/desktop image fields or <picture> element support if the origin uses responsive variants. |
| "The preview looks close enough, I'll skip user approval" | The approval checkpoint exists because the agent cannot judge visual fidelity the way a human can. Always stop and wait for explicit confirmation. |
| "I'll generate the preview after section mapping" | The preview must come before section decomposition. Its purpose is to catch scrape errors, missing content, and brand conflicts before committing to a section mapping that might be based on wrong assumptions. |
| "Placeholders are fine in the preview, I'll swap in real URLs later" | The preview is a fidelity check. Placeholder content defeats the purpose — the user cannot verify accuracy against placeholders. Use the content manifest's real URLs. |
Stakeholder says: Make it look like the live site.
Correct response: I will match the live site where possible, but .guides/brand-guideline.md is the source of truth for conflicting brand decisions.
Exact screenshot thinking -> match structure and feel, but keep the implementation reusable.Global junk drawer -> if one section owns it, keep it local.Over-customizing old sections -> if adaptation becomes awkward, create a clean new section instead.Skipping registration -> new sections must be added to app/weaverse/components.ts.Ignoring the registry -> use sections.md and app/weaverse/components.ts before inventing new sections.Missing content manifest -> the design spec is incomplete without a per-section table of real asset URLs, text, and links from the crawl. Without it, the JSON generator fills in placeholders.Media type blindness -> mapping a video hero to an image-only section, or an animated block to a static section, without flagging the gap.Concept merging -> collapsing two visually distinct occurrences of the same concept into one section block.Layout blindness -> matching by content type alone without checking composition (overlay vs side-by-side vs stacked), layout mechanism (slider vs grid vs full-bleed), and interaction (static vs carousel vs scroll). This is the most common cause of sections that render completely differently from the origin.Section merging -> combining two separate origin sections (e.g., a background-only video + a separate text block) into one Weaverse section, changing the visual hierarchy.Skipping HTML analysis -> classifying layout from the markdown crawl alone. Markdown strips slider components, grid classes, overlay positioning, and interactive elements. The raw HTML is required for accurate layout classification.Name-matching without schema verification -> a section named "hero-image" does not mean it can reproduce every hero layout. Read the section source code and verify schema settings (aspect ratios, responsive image fields, overlay options, child types) before classifying as REUSE.Assuming aspect ratios are configurable -> many sections hardcode aspect ratios (e.g., aspect-square). Check the actual schema enum values or CSS classes before assuming the section can produce the ratio the origin uses.Ignoring responsive image requirements -> if the origin uses <picture> with separate mobile/desktop <source> elements, a section with a single image field is not a match. The section needs imageMobile/imageDesktop fields or equivalent.Skipping the preview checkpoint -> the clone preview route exists so the user can catch problems before section decomposition begins. Skipping it means discovering layout errors after significant Weaverse mapping work is done.Auto-approving the preview -> the agent must not treat its own judgment as approval. Only an explicit user response ("approved", "proceed", etc.) unblocks section decomposition.Preview without section markers -> forgetting the {/* === BLOCK NAME === */} comments means the preview cannot serve double duty as a decomposition guide. Always include them.Zombie preview route -> forgetting to delete app/routes/clone-preview.$page.tsx after the Weaverse page is verified. It is a temporary artifact, not a permanent route.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.