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.
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.
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.
01Design
<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>
02Skeleton
03Live
Typography, spacing and icons match the design
7 stages From interview to report, with a progress bar printed after each one.
Treated as defects, not shortcuts
// works-with
A skill is a folder. Whichever agent reads it gets the same rules, the same references and the same tools.
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.
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.
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
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
What the skill produces
The model knew Elementor the way the documentation describes it. It did not know Elementor the way it actually behaves.
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
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.
Interview
A fixed question set, including whether to keep or strip animations.
Refinement
A free-text brief: house rules, exceptions, what matters most.
Skeleton gate
Never skipped. You approve a sample first: home, about, contact and one list page.
Convert
Elementor JSON authored as shorthand and compiled, so the boilerplate is always correct.
Deploy
Fonts, kit, media, post types, loop items, pages, menus, header, footer.
Verify
The design and the live page photographed at the site's breakpoints and diffed.
Report
One fixed HTML report, every run, with telemetry and cost.
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.
One snippet, page or section in; one or more import files out, or paste-ready JSON.
A folder of HTML and CSS pages in; a shared global kit and per-page JSON out, packaged for manual import.
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.
A fresh skeleton of what is actually live, or a regenerated report, without converting or deploying again.
// what-it-knows
The rules a model does not have unless someone gives them to it. Each one is a defect we shipped once.
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.
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.
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.
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.
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.
Headers and footers use the navigation widget bound to real WordPress menus, never hand-built link lists. Footer menus never collapse into a hamburger.
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.
Hover states, transitions and entrance animations map to hover tabs and motion effects, or you strip them at the interview. Nothing is silently lost.
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.
Desktop, tablet and mobile. Elementor's extra breakpoints stay off unless the design truly needs them and you opt in.
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
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.
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.
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.
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.
The bridge fixes a theme-builder conditions cache that otherwise left bridge-created headers and footers invisible on the front end.
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.
Every privileged call is written down.
Everything is gated by an administrator's application password over HTTPS. Treat it like SSH access, because that is what it is.
// verification
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.
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.
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.
Measure spacing and icons
The same way, with their own tools.
Patch and photograph again
Fix each mismatch at the widget and control that own it, then photograph again, until the two agree.
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.
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.
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.
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.
Every media item, never sampled. Every token, every page, and every deviation from the design, with where and why.
Model and reasoning level, cumulative tokens read from the session transcript, elapsed time, and a cache-aware cost estimate.
PHP, server and Elementor version, plus a sidebar for side-by-side screenshot comparison.
// our-stance
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.
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
The parts that make a skill more than a long prompt.
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.
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.
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.
Every rule in it was measured on a live site, not inferred from documentation.
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 it | What it is |
|---|---|
| The skillThe developer | Its references, its tools and the handoff prompt. The only one you unzip. |
| The bridge pluginThe WordPress administrator | Installed as it is. |
| The design handoff promptThe designer | Packages 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.
// products/
Plugins, apps and internal systems. Each one is shipped, documented, and still looked after.