From data-liberation
Converts a page's raw HTML into WordPress block-editor markup using design tokens and a screenshot. Call per-page after extraction to produce `post_content` that renders with the theme's tokens and patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/data-liberation:compose-page-blocksThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You compose **one page's** WordPress block markup from its source HTML and, when supplied, a screenshot, using the site's design foundation. The streaming watch loop calls you per-URL; you produce a block-markup string and hand it to the runner via `liberate_block_compose` before the post is inserted.
You compose one page's WordPress block markup from its source HTML and, when supplied, a screenshot, using the site's design foundation. The streaming watch loop calls you per-URL; you produce a block-markup string and hand it to the runner via liberate_block_compose before the post is inserted.
You are NOT generating a theme. That's the replicate-with-blocks skill's job. Your output is post_content for one specific post — not template parts, not patterns the theme registers, just the inner content of one page.
The calling loop hands you, per invocation:
| Field | Type | Description |
|---|---|---|
url | string | Source URL (used for traceability + media-URL rewriting downstream) |
htmlPath | string | Absolute path to the sanitized rendered HTML file. Source HTML went through html-sanitize.ts upstream — script/iframe/object/embed tags, HTML comments, and on*= event handlers are already stripped. |
screenshotPath | string | Absolute path to the desktop screenshot (and .scrolled.png if present at the sibling path), or an explicit skipped-screenshot instruction when the active archetype template already captures the visual treatment |
designFoundationPath | string | Absolute path to the run's design-foundation.json |
archetype | enum | 'page' | 'post' | 'product' | 'gallery' | 'event' |
outputPath | string | Where to write the block-markup string |
Every non-skipped file is required. If an input file is missing or empty, return an error and do not write outputPath.
A single text file at outputPath containing valid WP block markup. The file must:
parse_blocks() — every <!-- wp:foo --> opens has a matching <!-- /wp:foo --> close (or is self-closed <!-- wp:foo /-->).output-verify.ts) checks every text node against the source's plain text. Any hallucinated phrase (rewriting "Foo Industries" as "Bar Inc.", inventing a tagline, generating fake testimonials) gets the entire output discarded.core/paragraph, core/heading, core/list, core/list-item, core/image, core/gallery, core/cover, core/columns, core/column, core/group, core/buttons, core/button, core/separator, core/spacer, core/quote, core/details, core/embed. Do not emit core/html, wp:html, or Custom HTML blocks. Avoid emitting any other block type unless the active replica theme has already registered a purpose-built custom block for this exact component.className. Every section that maps to a foundation role (e.g. accent surfaces, raised surfaces, inverse surfaces) carries the matching style slug (is-style-accent-primary, is-style-soft-card, etc.) in className. The list of registered styles is documented in references/post-content-conventions.md.You MUST NOT:
#0f4d7a directly. Use native slug attributes (backgroundColor, textColor) when the block exposes them; otherwise use a registered className style and let the theme define CSS in style.css or theme.json/block styles.<!-- wp:template-part {"slug":"header"} /-->). Template parts don't render inside post_content; they're a Site Editor concept. If a section "looks like" header/footer chrome in the screenshot, skip it — it's the theme's job, not yours.<script>, no raw <iframe> outside a core/embed block. The pre-skill sanitizer already removed these from input; do not reintroduce them.post_content.core/html / wp:html as an escape hatch for layout, CSS, forms, embeds, icons, or missing block types.<style> tags or inline style attributes to recreate a source section. CSS belongs in the active theme's style.css or theme.json/block styles. Use className hooks and foundation style slugs instead....). Reordering a clause, swapping a word, or writing a "punchier" version is paraphrase and is forbidden. If you can't find the supporting text in the source HTML for a slot, omit the slot or emit a clearly-marked [copy not captured] placeholder — NEVER "fill in plausible words." This applies to body copy just as strictly as to review/testimonial quotes; an earlier getsnooz build paraphrased section body copy ("Real fan-powered sound — no loops…") while the real line was in the captured HTML. Body-copy paraphrase HARD-FAILS the liberate_validate_artifacts provenance gate (body text must be substantially contained in the captured source) — do not bypass it.You MUST:
wp:cover for hero sections — large headline + subtext + optional CTA over a background. Pull url from any <img> directly inside the source's hero region; if no hero image, omit the cover and use wp:group with align: full instead.wp:columns + wp:column for multi-column layouts. Preserve the column count from the source. When a row holds 4 cards in the screenshot, emit 4 wp:column children. The verticalAlignment attribute should match the visual alignment in the screenshot.wp:group (with align: "full" or "wide") for full-bleed sections. Apply foundation surface tokens via backgroundColor slug.wp:gallery for image grids of 3+ images (e.g. portfolio, product gallery teaser). Use wp:image for single images.wp:details for FAQ/accordion patterns — the question is the <summary>, the answer is the children.wp:buttons + wp:button for CTAs. Use native block color slug attributes such as backgroundColor / textColor or a registered className style; do not add ad hoc inline CSS.design-foundation.json to know which slugs are available. Specifically: color.surface.*, color.accent.*, typography.families.*. You will reference these by slug, not by hex.wp:group with a heading + subtext is safer than a wp:cover whose image you couldn't ground.className to the corresponding style slug.wp:image (or wp:gallery for multiple) with the source URL. The downstream media-url-rewrite step swaps these to local upload URLs after compose.outputPath. Do not include any wrapping tags (no <html>, no <body>) — just block markup.{
"url": "https://example.com/about",
"blocksCount": 7,
"sectionsMapped": ["hero", "overview", "features", "cta"],
"foundationsUsed": ["accent-primary", "surface-raised"],
"warnings": []
}
The streaming loop calls a deterministic heuristic-blocks.ts BEFORE invoking you. If the page is "all paragraphs + h2/h3" or "single image followed by paragraphs" or "one section with heading + text," the heuristic emits markup directly and you are skipped. If you ARE invoked, the page has at least one non-trivial structural element — a hero, a multi-column layout, a gallery, an interactive section. Spend your effort there.
<div class="container"> could be a hero, a footer band, or just an alignment wrapper. Use the screenshot to disambiguate.design-foundation.json doesn't list a slug you want (e.g. you imagine a "muted cyan" surface), do not invent it. Pick the closest existing slug or omit the visual treatment.wp:html. Custom HTML blocks are rejected. Always prefer the right semantic block, or ask for a custom block/theme CSS change when the source component cannot be represented with core blocks.core/html to recreate a missing block type. When a layout needs something outside the allow-list above, omit the section and add a warning.references/blocks-reference.md — concrete markup examples for cover, columns, group, heading, image, buttons, gallery, details. Read when you need the exact JSON-attribute shape for a block.references/post-content-conventions.md — what's legal in post_content, what's not. Read before composing.skills/replicate-with-blocks/styling-priority.md — the preset→patch→instance→variation→layout→CSS cascade, the structured-props cheat sheet, and the hard bans (no raw style="" attrs, no invented className CSS hooks). Applies to native block output; core/html islands exempt.evals/evals.json enumerates representative pages from existing fixtures (biostratamarketing rich blog post, getsnooz about page, dopplepress product page). Each eval supplies the inputs your invocation receives plus a brief intent description. Assertions land after the first iteration of grading.
npx claudepluginhub automattic/studio --plugin data-liberation3plugins reuse this skill
First indexed Jun 12, 2026
Converts a page's raw HTML into WordPress block-editor markup using design tokens and a screenshot. Call per-page after extraction to produce `post_content` that renders with the theme's tokens and patterns.
Generate or edit WordPress Gutenberg blocks using Greenshift/GreenLight plugin. Convert data to WordPress blocks, or convert Greenshift blocks back to HTML/CSS/JS.
Converts WPBakery Page Builder shortcode content into native Gutenberg blocks, preserving text, images, buttons, videos, galleries, and CSS classes. Use when migrating a WordPress site from WPBakery to Gutenberg.