Amirhossein Hosseinpouramirhp
CV
Active Agent skill · Claude and Codex

html2elementor

We did not just use the AI. We taught it Elementor.

A skill, meaning a body of rules, references and tools, that lets Claude or Codex take a finished design in HTML, CSS or React and produce a real Elementor site. Not an HTML widget with the design pasted inside: native widgets, global tokens, real menus and reusable templates, deployed to a live WordPress site and then checked in a headless browser at every breakpoint.

See a run Why a skill, not a prompt

Internal tooling at Pigment Dev, MIT-licensed. It is one part of the studio's pipeline from design output to a live, editable site. I co-founded the studio and lead its development.

Since the first commit2026 to today
/html2elementor · deploy mode · pages/home.html

01Designpages/home.html

<section class="hero">
  <h1>Studio</h1>
  <p>Since the start</p>
  <a class="btn">Book</a>
</section>
<div class="features">
  <div>icon + h3 + p</div>
  <div>icon + h3 + p</div>
  <div>icon + h3 + p</div>
</div>

02Skeletonapprove before build

  • containerP-C1
    • headingH1 tokenP-C1-W1
    • text-editorBodyP-C1-W2
    • buttonfittedP-C1-W3
  • containerflex, thirdsP-C2
    • icon-box ×3not decomposedP-C2-W1..3

03Livethree breakpoints

  • Desktop
  • Tablet
  • Mobile

Typography, spacing and icons match the design

  1. Interview
  2. Refinement
  3. Skeleton gate
  4. Convert
  5. Deploy
  6. Verify
  7. Report

7 stages From interview to report, with a progress bar printed after each one.

Treated as defects, not shortcuts

  • A design pasted into an HTML widget. Native widgets come first; where one had to stand in, the report names the page, the widget and the reason.
  • An icon, a heading and a paragraph built as three widgets instead of one icon box
  • A literal pixel width on a container
  • Custom CSS doing a job a flex control should do
  • An SVG from the design swapped for a font-icon lookalike

// works-with

Works with

A skill is a folder. Whichever agent reads it gets the same rules, the same references and the same tools.

Claude Code

The primary home. The skill loads from .claude/skills/html2elementor/, per project or globally, and runs as /html2elementor. Deploy mode and visual verification live here, because both need local tools.

Codex

The same skill through the agents convention: AGENTS.md at the root and .agents/skills/html2elementor pointing at the same folder, so Codex reads exactly what Claude reads. One source, no fork.

Claude on the web and API

Upload the skill and its references as project knowledge, or pass the skill as the system prompt. Conversion works there; live deploy and headless verification stay in Claude Code, where the tools are.

// why

Why we built it

Getting a design into Elementor has always been the slow, lossy step. AI made it fast. It did not make it right, until we wrote down what right means.

Before

A finished design arrives as HTML and CSS, or as a Figma file, or as a folder an AI produced. Then someone rebuilds it in Elementor by hand: every heading, every button, every three-column row, dragged and configured. It takes days, it drifts from the design, and no two people rebuild the same thing the same way.

So we asked the model to do it. It did, in minutes, and the result looked finished.

What the model produced

  • The design pasted into raw HTML widgets where a native one would have done
  • Fixed pixel widths on containers
  • An icon, a heading and a paragraph as two containers and three widgets instead of one icon box
  • Custom CSS carrying the layout that flex controls should have carried
  • Fonts that were almost right, which is worse than wrong, because nobody notices until the client does

What the skill produces

  • Native widgets from a catalogue of dozens, free and Pro, and forms that are always the Form widget
  • Boxed containers that inherit the kit's global width
  • Composite widgets kept whole: one icon box with a position setting
  • Real flex controls, and every surviving custom CSS block reported
  • Type checked on the live render, not read from the stylesheet

The model knew Elementor the way the documentation describes it. It did not know Elementor the way it actually behaves.

The realisation

A model is exactly as good at Elementor as what it has been told about Elementor.

Every mistake it made, we had made once too, years ago, and learned not to. That knowledge lived in our heads and in a decade of client sites, and none of it was written anywhere a model could read. The fix was not a better prompt. It was to write the whole discipline down, with the traps, the exceptions and the reasons, and give it to the agent as a skill it loads every time.

It grew from use: every conversion that shipped with a defect became a rule. The largest was a right-to-left medical site of nearly thirty pages that looked finished and, when measured, had more than three thousand of its text elements rendering in the wrong family, size, weight or line height, and dozens of its icons replaced by lookalikes. That case produced the rule the whole skill now lives by: verify against the render, not against the CSS.

Today it runs end to end. It interviews you, shows you a skeleton you approve before anything is built, converts, uploads every asset, deploys to a live site through its own bridge plugin, then photographs the design and the live page at the site's breakpoints and patches the differences until they agree. At the end it writes a report listing every media file, every token, every page and every deviation, along with what the run cost.

// a-run

What a run looks like

The run counts its own steps and prints a progress bar after each stage, so a long job is never silent. One model from start to finish; heavy stages run as subagents in parallel so the main session stays small.

  1. Interview

    A fixed question set, including whether to keep or strip animations.

  2. Refinement

    A free-text brief: house rules, exceptions, what matters most.

  3. Skeleton gate

    Never skipped. You approve a sample first: home, about, contact and one list page.

  4. Convert

    Elementor JSON authored as shorthand and compiled, so the boilerplate is always correct.

  5. Deploy

    Fonts, kit, media, post types, loop items, pages, menus, header, footer.

  6. Verify

    The design and the live page photographed at the site's breakpoints and diffed.

  7. Report

    One fixed HTML report, every run, with telemetry and cost.

The skeleton you can actually review

Before any JSON exists, the skill shows a labelled skeleton of the page. Every box carries a reference you can quote, in the form page, container, wrapper, widget, so a note like "the third widget in the second wrapper of the hero is the wrong type" points at exactly one thing. Every box takes the width it will take live: a third is a third, a fitted button is fitted. Click a reference to copy it, or jump to it from the toolbar.

Compare puts the real design page beside the skeleton at the same canvas width, with synchronised scrolling you can switch off. It is greyscale, with one accent for focus and another for tokens, so the structure is what you see.

Three ways to run it

Single

One snippet, page or section in; one or more import files out, or paste-ready JSON.

Project

A folder of HTML and CSS pages in; a shared global kit and per-page JSON out, packaged for manual import.

Deploy

A design project and a live site in; everything pushed through the bridge and verified. The project follows the design-project standard the skill defines.

Re-run on a finished project

A fresh skeleton of what is actually live, or a regenerated report, without converting or deploying again.

// what-it-knows

What it knows

The rules a model does not have unless someone gives them to it. Each one is a defect we shipped once.

The first rule

Native widgets, never HTML widgets.

Each element maps to a real Elementor widget from a catalogue of dozens, free and Pro. The HTML widget is a last resort, and every place one had to stand in is flagged in the report with the page, the widget and the reason. Forms are always the Elementor Form widget, never raw markup. Composite widgets are never decomposed: an icon beside a heading and text is one icon box with a position setting, not two containers and three widgets.

Everything becomes a token

Every colour becomes a global colour and every text style a global typography. Tokens the design does not define, such as heading levels, body, button, input and link, are derived from it and flagged. Change the kit, change the site.

Native controls over custom CSS

Flex grow and shrink, widths, order, gaps and spans map to real Elementor controls. Custom CSS for any of them is forbidden, and every surviving custom CSS block is reported.

Flex first

Flexbox by default. CSS grid only for four or more structurally identical items that wrap to multiple rows. Grid used to be everywhere; it is not anymore.

Never a hardcoded width

The root container is full-bleed and boxed containers inherit the kit's global width. A literal pixel width on a container is treated as a defect.

Menus are menus

Headers and footers use the navigation widget bound to real WordPress menus, never hand-built link lists. Footer menus never collapse into a hamburger.

Reuse over duplication

A section that repeats three or more times becomes one saved template. Products, portfolio and blog become one dynamic loop template with field bindings, never a layout per item.

Animations converted, not dropped

Hover states, transitions and entrance animations map to hover tabs and motion effects, or you strip them at the interview. Nothing is silently lost.

The design's own artwork survives

Every SVG is exported as a file, uploaded to the media library and referenced by id and URL. Never swapped for a font-icon lookalike.

Three breakpoints, unless you ask

Desktop, tablet and mobile. Elementor's extra breakpoints stay off unless the design truly needs them and you opt in.

Padding that never collapses

A source that sets no padding leaves Elementor's default in place. An omitted padding is not zero, and content is never pushed flush against a container edge.

// the-bridge

The bridge

Deploy mode needs a way into your WordPress site. The Pigment Elementor Bridge is a small plugin that gives the agent that way in, and takes it away again when it is done.

  1. Connect

    Install, activate, click Set up now. The plugin creates an application password and hands you a connection file for the skill. No copying tokens by hand.

  2. Deploy, in order

    Fonts, then the global kit, then every media item, then custom post types and their loop items, then pages, menus, header and footer. Page slugs in plain ASCII, derived when the design does not supply one.

  3. Leave

    When the job is done the skill can revoke its own passwords and delete the plugin remotely. The door it came through closes behind it.

Headers that actually render

The bridge fixes a theme-builder conditions cache that otherwise left bridge-created headers and footers invisible on the front end.

What the agent can do through it

Read site state and the endpoint documentation, proxy the WordPress REST API, and run code and queries or write must-use plugins when a conversion needs a fix WordPress will not expose otherwise.

An activity log

Every privileged call is written down.

Treat it like SSH

Everything is gated by an administrator's application password over HTTPS. Treat it like SSH access, because that is what it is.

// verification

Verify against the render, not the CSS

A stylesheet audit tells you what the rules declare. It cannot tell you what the cascade, a theme stylesheet or an Elementor default actually produced. So the skill photographs both sides and measures.

  1. Photograph both sides

    Read the site's own breakpoints from the bridge, then photograph the design and the live page at each one in a headless browser.

  2. Measure the type

    Walk every text-bearing element on both sides and record family, size, weight, line height and letter spacing, joining design to live on the text string itself, since content is ported verbatim.

  3. Measure spacing and icons

    The same way, with their own tools.

  4. Patch and photograph again

    Fix each mismatch at the widget and control that own it, then photograph again, until the two agree.

The empty-widget audit

After each round it walks the live page and flags any widget that rendered as blank space or never rendered at all, so a matching height is never mistaken for a correct page.

What eyes do not catch

A hamburger positioned off-screen, a font one weight off, an icon replaced by something similar. Invisible in the source, obvious in a computed-style diff.

Without eating your disk

Captures at one-times scale, re-encoded to width-capped WebP, intermediate rounds pruned. A twenty-page verification leaves tens of megabytes where retina PNGs used to leave gigabytes.

The report

One consistent HTML report, every run, compiled from compact data rather than hand-written, so it is the same shape every time and costs a fraction of the tokens.

Everything uploaded

Every media item, never sampled. Every token, every page, and every deviation from the design, with where and why.

What it cost

Model and reasoning level, cumulative tokens read from the session transcript, elapsed time, and a cache-aware cost estimate.

Where it ran

PHP, server and Elementor version, plus a sidebar for side-by-side screenshot comparison.

// our-stance

Our stance on AI

Most studios use AI the way you use electricity. It is on, it helps, nobody thinks about it. We think about it.

We noticed something early: the model is only as good at our work as what it knows about our work, and almost none of what we know was written down anywhere it could read.

So we write it down. A skill is a body of knowledge an agent loads before it starts: rules, references, tools, and the reasons behind them. html2elementor is a decade of Elementor experience in that form. The lessons file in the repository is the raw case record, and every entry in it has been converted into a rule the skill follows, at the exact point where it bites.

Teaching a model a discipline is engineering work. It has a specification, a test loop, versioned releases and a changelog. When the model gets better, the skill gets better with it, because the knowledge was never in the prompt. It was in the folder.

Why it does not care which agent reads it

The knowledge is ours. The model is whichever one is best this month.

The same practice produced an image pipeline for a client store, and the toolkit that ships with every site we build.

// developers

For developers

The parts that make a skill more than a long prompt.

Compile, do not hand-write

Elementor JSON is authored as shorthand and expanded by a compiler, so the boilerplate is always correct and each run spends far fewer tokens on it. Minimal JSON: non-default settings only.

Tools that ship with it

Headless screenshot and contact-sheet tools, typography, spacing and icon measurers, a widget auditor, a capture optimiser, a progress reporter, and a session-cost reader with a pricing table.

Seventeen references, loaded by phase

The widget catalogue, widget selection, layout decisions, native controls, kit and dynamic styling, header and footer, templates, animations, the JSON shorthand, deploy, verification, the report, the skeleton, re-runs, the design-project standard, the model plan, and the traps.

The traps file is the field record

Every rule in it was measured on a live site, not inferred from documentation.

Everyone is holding the same release

A release is a set of files that travel to different people, and every one of them carries the same version number.

File, and who gets itWhat it is
The skillThe developerIts references, its tools and the handoff prompt. The only one you unzip.
The bridge pluginThe WordPress administratorInstalled as it is.
The design handoff promptThe designerPackages a finished design into the folder shape the skill converts: tokens, project notes, pages, partials, fonts, assets, and an assembled preview of every page.

The version file is the single source of truth. The build script stamps it into the skill title, the plugin header, the prompt's first line and every filename, then checks it landed. A mismatch fails the build instead of shipping drift.

branch main 6 active projects ↑ 113 releases products/html2elementor.md Sari --:-- UTC+3:30 its@amirhp.com