SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

html2elementor

Design e Frontend

Convert HTML+CSS into Elementor JSON that imports into WordPress. Always use this skill whenever the user has HTML/CSS (pasted, file, URL, or AI-generated) and wants it to end up as an Elementor page — phrases like "convert HTML to Elementor", "import this landing into WordPress as Elementor", "make this Tailwind mockup an Elementor page", "turn my markup into Elementor JSON", "recreate this site

9estrelas
Ver no GitHub ↗Autor: dudasterLicença: MIT

html2elementor

Paste HTML+CSS, get a JSON payload you can drop into _elementor_data. A small, free, open-source HTML → Elementor converter that runs locally.

When to use this skill

Use whenever the user has HTML on one side and wants Elementor on the other. Triggering phrases include (but aren't limited to):

  • "convert this HTML to Elementor"
  • "import this landing page into WordPress"
  • "recreate this design as an Elementor page"
  • "turn my mockup into Elementor"
  • "bring this Tailwind page into WordPress"
  • "I have HTML from [tool X], make it Elementor"
  • "Elementor JSON from this markup"

Also use it implicitly — the user pastes or attaches HTML and asks "make this work in Elementor" without naming a tool.

Don't use for:

  • Editing pages that are already Elementor (use WP-CLI / REST API directly).
  • Plain WordPress pages with no Elementor (just wp_insert_post with post_content).
  • Figma / Sketch / design files — this converts markup, not design-tool exports. If the user has a Figma file, suggest they first export to HTML with a tool like Figma-to-HTML or Anima, then run that output through this skill.

The four-step flow

Prepare → convert → verify → import. The first three are local and identical regardless of the user's WordPress setup. The fourth depends on how they run WordPress.

Step 0 — Prepare the input

  • External stylesheets. If the HTML uses <link rel="stylesheet" href="styles.css">, inline the CSS into a <style> block before running the converter. The parser reads <style> blocks and inline style="", not external files. Inlining preserves the cascade exactly.
  • Relative image paths. If <img src="assets/foo.png"> points to local files on disk, run the converter with --upload (see Step 3). Keep the input file next to the assets/ directory — the uploader resolves relative paths against the HTML file's own directory.
  • Pasted HTML. If the user pasted raw HTML, write it to a temp file (e.g. /tmp/input.html) so the converter has a real path to anchor relative URLs and so error messages make sense.

Step 1 — Convert

Run from the installed skill directory (typically ~/.claude/skills/html2elementor or ~/.openclaw/skills/html2elementor):

.venv/bin/python3 -m html2elementor path/to/input.html -o /tmp/layout.json

Add --upload when the HTML references images (either absolute URLs or relative paths) and the user wants them pulled into the WP media library automatically:

.venv/bin/python3 -m html2elementor path/to/input.html --upload -o /tmp/layout.json

This produces two files:

  • /tmp/layout.json — the _elementor_data payload (a list of top-level containers, each with nested widgets).
  • /tmp/layout.kit.json — custom_colors and custom_typography globals. Widgets in the layout reference these via globals/colors?id=...; without merging this into the active kit the page renders with missing colors and fonts.

Step 2 — Verify

.venv/bin/python3 -m html2elementor.verify path/to/input.html /tmp/layout.json

The verifier walks the source HTML node-by-node and checks that each emitted widget has matching color, font-size, spacing, and max-width. Zero issues means the CSS cascade was resolved correctly and faithfully typed through. It does not guarantee pixel-perfect render — that needs a screenshot diff — but it catches the common failure mode (silent layout drift) cheaply.

Share the issues list with the user verbatim before importing. Each mismatch is actionable.

Step 3 — Import

This step depends on the user's WordPress setup, so ask them how they want to import before running any commands. Common setups and the right approach:

SetupHow to import
Local WP (MAMP, Local by Flywheel, Laravel Valet)wp-cli via terminal
Docker sandboxdocker compose exec wp wp eval ...
Staging on a managed hostSSH + wp-cli, or the REST API
ProductionREST API or Elementor's template-library import

Whatever the transport, two invariants always apply:

  1. Merge .kit.json custom globals into the active kit's _elementor_page_settings post meta. Look up the active kit ID with get_option("elementor_active_kit"), then append each entry from .kit.json's custom_colors and custom_typography (dedupe by _id). Also copy scalar site settings when present: body_background_background ("classic") and body_background_color (hex from the HTML's body background CSS). Skipping the custom arrays makes widgets render with default colors/fonts; skipping the body scalars leaves the site on the Elementor default white instead of the source page's background.

  2. Flush Elementor's CSS cache after updating _elementor_data: wp elementor flush_css --allow-root. Elementor builds per-post CSS files under wp-content/uploads/elementor/css/ and serves those instead of reading settings live. Without flushing, visual changes won't appear on next page load.

If the user reports "my page looks empty" or "colors are wrong after import", one of those two invariants was missed.

Internal links still point at the source HTML filenames. The converter preserves href values verbatim — href="pricing.html" stays href="pricing.html". After import, rewrite those to the WP page slugs before flushing CSS. Safest approach: preprocess the JSON files on disk with sed:

sed -i '' \
  -e 's|"docs/index\.html"|"/dudaster-docs/"|g' \
  -e 's|"index\.html"|"/dudaster-index/"|g' \
  -e 's|"modules\.html"|"/dudaster-modules/"|g' \
  -e 's|"pricing\.html"|"/dudaster-pricing/"|g' \
  page.json

Process the most specific paths first (docs/index.html before index.html) so short names don't clobber longer ones. Do not try this with regex in PHP via update_post_meta — a bad pattern returning null will silently wipe _elementor_data on every matched post. Rewrite on disk, then re-import.

Kit bloat. Every re-import merges new custom_colors / custom_typography IDs into the kit (dedupe by _id) but never removes orphans from intermediate runs. After many iterations the kit accumulates hundreds of unused entries. Garbage-collect by scanning every post's _elementor_data for referenced globals/colors?id= + globals/typography?id= IDs and filtering the kit to just those. See playsand/cleanup_kit.sh in this repo for a reference implementation — safe to run anytime, only prunes IDs no post references, flags orphans where a post references a missing ID.

Step 4 (optional) — Visual verify

After import, screenshot both the source HTML and the rendered Elementor page at the same viewport (1440×auto for desktop). Compare side-by-side. The verifier catches semantic drift but some Elementor quirks (see below) only show in a real browser.

What the converter knows (non-obvious patterns)

The full reference is in README.md. These are the patterns that broke in practice and were hardened:

  • CSS custom properties (--color-brand, --font-sans) are resolved from :root/html/body, substituted post-cascade, then shorthand-re-expanded so background: var(--x) populates background-color correctly.
  • Mixed inline content (<div>Paper<span>fold</span></div>) is emitted as a single widget with <span style="color:#xxx">…</span> inline HTML — never split into two widgets or layout drifts.
  • Circular avatars (div with bg + border-radius:50% + fixed px size + short text) become a styled inner container wrapping a heading — headings alone can't hold width in a flex row.
  • Agenda / schedule slots (flex row with fixed-width label + content) are emitted as a single text-editor with inline absolute-positioned label. Elementor row containers break fixed+grow widths (see quirks below), so we use inline HTML to sidestep.
  • Split hero (text column + image column) — any <img>, <svg>, <picture> in a card counts as content for grid detection, so

Como adicionar

/plugin marketplace add dudaster/html2elementor

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.