Skip to content
themeforge
EN
Start free
Menu

AI Generation Guide

This guide explains how to place ThemeForge attributes on HTML elements so the generator can create a WordPress theme with a fully functional admin panel.

You can share this page with any AI assistant (ChatGPT, Claude, Gemini, etc.) so it can read the rules and correctly place attributes on your HTML.

Share this link with your AI: https://themeforge.pro/ai

Point your AI assistant at this address and it reads the placement rules from the source — the same ones the generator judges your markup by. It answers with a short index first, then serves each rule module on request.

Workflows

There are several ways to use ThemeForge attributes depending on your starting point and tooling.

1. AI generates a site with attributes

For: users with a design (Figma, sketch, reference site)

Share this page link with your AI assistant along with your design. The AI generates HTML with ThemeForge attributes already in place. You review the attribute report, request corrections, and generate the WordPress theme.

  1. Give your AI the link to this guide + your design (Figma URL, screenshots, reference)
  2. AI generates HTML with all attributes placed according to the rules
  3. Review the attribute report — adjust if needed
  4. Generate WordPress theme via ThemeForge

2. AI adds attributes to existing HTML

For: developers with a ready HTML site (from Webflow export, a template, or hand-coded)

You already have HTML without ThemeForge attributes. Share this guide with your AI and ask it to analyze the HTML and place attributes on the right elements. Then review and generate.

  1. Give your AI the link to this guide + your HTML files
  2. AI analyzes the structure and adds attributes to text, images, links
  3. Review the attribute report — the AI doesn't always know which elements are decorative
  4. Run validation, fix any issues, generate the theme

3. Manual placement in Webflow Designer

For: experienced Webflow users who prefer full control

Add custom attributes directly in Webflow Designer (Element Settings → Custom Attributes). Export the site and run validation before generating the theme.

  1. Select an element in Webflow → Settings → Custom Attributes
  2. Add the attribute name (e.g. fld-text) and value (e.g. Heading)
  3. Export the site (Code Export or .webflow.io)
  4. Run validation and generate the theme

Full Cycle

Regardless of the method, the review cycle is fast — no need to import into Webflow or install on WordPress just to check attributes:

  1. Place attributes (AI or manually)
  2. Run attribute report — review the tree in seconds
  3. Not happy? → tell AI what to fix → run report again
  4. Run validation — check for errors
  5. Generate WordPress theme

Ready-Made AI Prompts

Copy a prompt below and paste it into your AI assistant (ChatGPT, Claude, Gemini) along with the link to this guide. The AI will follow the attribute rules automatically.

Prompt A: Add attributes to existing HTML

Use this when you already have an HTML site and need to add ThemeForge attributes.

I have a finished HTML website that I want to convert into a WordPress theme with an editable admin panel, using ThemeForge.

Read the placement rules and follow them exactly. Start here — it names the rule modules and tells you what to do first:
https://themeforge.pro/ai
Always pull the `core` module; if you are generating the site from scratch, pull `build` too. Then add what this site needs (pages, blog, cpt, woocommerce, deploy).

Then add ThemeForge attributes to every piece of editable content in my HTML:
- Each visual section = a tab + group pair; short headings/labels = text, paragraphs and long wrapping headings = textarea, images on  tags, links as a URL + text pair.
- Repeating cards (features, team, FAQ) = a repeater with 2+ rows.
- Header, footer, navigation, logo and contacts = site-wide options.
- If my site is multilingual, mark the language switcher with wp-menu="Language" and do NOT hardcode any visible text — every label must be a field (each language has its own value).
- Keep image/file paths as they are; do not skip any visible text.

[Add your specific requirements here: which pages, WooCommerce / blog support, languages, etc.]

When done, follow the Final Delivery steps: create the theme-options page with ALL option fields, serve the files locally, and give me the complete list of page URLs to paste into ThemeForge.

Prompt B: Generate HTML with attributes from scratch

Use this when you want the AI to create an HTML site from a design (Figma, screenshot, description) with ThemeForge attributes already included.

I need you to generate an HTML website with ThemeForge attributes already in place, ready for WordPress theme generation.

Read the placement rules and follow them exactly. Start here — it names the rule modules and tells you what to do first:
https://themeforge.pro/ai
Always pull the `core` module; if you are generating the site from scratch, pull `build` too. Then add what this site needs (pages, blog, cpt, woocommerce, deploy).

Here is my design: [ATTACH YOUR FIGMA LINK / SCREENSHOTS / DESCRIPTION]

Generate clean, semantic HTML + CSS and place ThemeForge attributes on all editable content as you build each section (not as a separate pass):
- Each section = a tab + group pair; text vs textarea by line count; images on ; links as a URL + text pair; repeating cards as a repeater with 2+ rows.
- Header/footer/navigation/contacts = site-wide options.
- For a multilingual site, mark the language switcher with wp-menu="Language" and keep every visible string as a field (no hardcoded text).
Use real placeholder content (not lorem ipsum) so data import populates real fields.

[Add your specific requirements here: colors, fonts, number of pages, WooCommerce / blog, languages, etc.]

When done, follow the Final Delivery steps: create the theme-options page with ALL option fields, serve the files locally, and give me the complete list of page URLs to paste into ThemeForge.

Tips for Better Results

  • For Prompt B: attach as much visual context as possible — screenshots, Figma links, reference sites. The more context, the better the result.
  • You can extend the prompts with your own requirements: color scheme, fonts, specific sections, number of pages, WooCommerce or blog support, multiple languages, etc.
  • After the AI is done, ask it to deploy the site to a local folder and serve it — then paste the local URL into ThemeForge to generate the WordPress theme.
  • The guide link is already included in the prompt. The AI will read the full attribute rules directly from the page.
  • Multilingual site? Mark content normally — one field name stores all languages; wire the switcher with wp-menu=“Language”. See the Multilingual section.
  • Give every field a UNIQUE name within its scope — never reuse a section’s name for a repeater inside it, or a link and its image won’t both survive.

Attribute Prefixes

PrefixScopeDescription
fld-*Per-pagePer-page fields — content unique to ONE page (hero text, page images)
opt-*Site-wideSite-wide options — content shared across ALL pages (phone, email, logo)
tax-*TaxonomyTaxonomy fields — content on category/tag archive pages
wp="..."WP CoreWordPress core — dynamic WP data (post title, date, featured image)
wp-fields-group="..."SectionsSection grouping — groups fields into admin panel sections (metaboxes)

Field Type Mapping

AttributeFieldHTML ElementExample
fld-textText<h1>-<h6>, <p>, <div><h2 fld-text="Heading">
fld-areaTextarea<p>, <div><p fld-area="Description">
fld-imageImage<img> only<img fld-image="Photo">
fld-bg-imageBG ImageAny element<div fld-bg-image="BG">
fld-linkLink<a> only<a fld-link="Button">
fld-editorRich editor<div><div fld-editor="Content">
fld-loopRepeaterWrapper <div><div fld-loop="Items">
fld-groupGroupContainer<div fld-group="Hero">
fld-layoutsSection builderWrapper <div><div fld-layouts="Page Sections">
fld-layoutSection typeDirect child<section fld-layout="Hero">
layout-previewPreview controlOn fld-layoutlayout-preview="off"
fld-tabTabEmpty <div><div fld-tab="Hero" wp="delete-element">
fld-showToggle (show)Wrapper <div><div fld-show="Show CTA">
fld-hideToggle (hide)Wrapper <div><div fld-hide="Hide CTA">
fld-galleryGalleryWrapper <div><div fld-gallery="Photos">

Replace fld- with opt- for site-wide options. Full reference: Attribute Reference

Placement Rules

Sections & Tabs

fld-tab must be on a separate empty <div>, NOT on the same element as fld-group. Place it as a sibling BEFORE the group.

<!-- ONE wp-fields-group per page on <body> -->
<body wp-fields-group="Home Page">

  <!-- Tab = empty sibling BEFORE the group -->
  <div fld-tab="Hero" wp="delete-element" class="tab-div"></div>
  <section fld-group="Hero" class="hero">
    <h1 fld-text="Heading">Welcome</h1>
    <p fld-area="Description">...</p>
  </section>

  <div fld-tab="Features" wp="delete-element" class="tab-div"></div>
  <section fld-group="Features" class="features">
    ...
  </section>

</body>

Links — Always a Pair

Every link MUST have both a link attr and a text attr, under TWO names — fld-link="X" on <a>, fld-text="X text" on a child <div>. One name for both makes one field feed the URL and the caption. Phone/email: opt-phone-link / opt-email-link alone — one attribute fills both the href and the visible text. Exception: icon-only or decorative links without visible text.

<!-- CORRECT: fld-link on <a>, fld-text on child, two names -->
<a fld-link="CTA" href="/shop" class="btn w-inline-block">
  <div fld-text="CTA text">Shop Now</div>
</a>

<!-- Phone/email: one attribute fills both href and text -->
<a opt-phone-link="Phone" href="tel:...">+1 234 567</a>

Images

fld-image goes on <img> tags ONLY. fld-bg-image goes on any element with a background image.

<img fld-image="Hero Image" src="images/hero.jpg" alt="Hero" />
<div fld-bg-image="Background" style="background-image:url('img/bg.jpg')"></div>

Repeaters

ALL children inside fld-loop MUST have the SAME ThemeForge attributes. Use different text and images in each row.

<div fld-loop="Team" class="team-grid">
  <div class="card">
    <img fld-image="Photo" src="images/avatar-1.jpg" />
    <h3 fld-text="Name">John Doe</h3>
  </div>
  <!-- Row 2: SAME attributes, DIFFERENT content -->
  <div class="card">
    <img fld-image="Photo" src="images/avatar-2.jpg" />
    <h3 fld-text="Name">Jane Smith</h3>
  </div>
</div>

Site-Wide Options

Elements on every page (phone, email, logo, address) should use opt-* instead of fld-*.

<!-- Header: site-wide, use opt-* -->
<img opt-image="Logo" src="images/logo.png" />

<!-- Navigation: a repeater of link + caption rows (NOT wp-menu) -->
<nav opt-loop="Nav links" class="nav">
  <div class="nav-item">
    <a opt-link="Link" href="/about" class="nav-link w-inline-block">
      <div opt-text="Link text">About</div>
    </a>
  </div>
  …
</nav>

<!-- Footer: contacts — one attribute each -->
<a opt-phone-link="Phone" href="tel:...">+1 234 567</a>
<a opt-email-link="Email" href="mailto:...">info@site.com</a>
<p opt-text="Address">123 Main St</p>

Menus

<!-- Navigation: an opt-loop of link + caption rows (preferred) -->
<nav opt-loop="Nav links" class="nav">
  <div class="nav-item">
    <a opt-link="Link" href="/" class="nav-link w-inline-block">
      <div opt-text="Link text">Home</div>
    </a>
  </div>
  <div class="nav-item">
    <a opt-link="Link" href="/about" class="nav-link w-inline-block">
      <div opt-text="Link text">About</div>
    </a>
  </div>
</nav>

<!-- Language switcher (Polylang): use wp-menu -->
<div wp-menu="Language" class="lang-switcher">
  <a href="/en" class="lang-link">EN</a>
  <a href="/ua" class="lang-link">UA</a>
</div>

Naming — Keep Every Name Unique

Within one scope each field name must be unique. ThemeForge keys fields by name, so two different fields that share a name collide and one is silently lost.

  • NEVER give a repeater (fld-loop) the same name as the section or group it sits inside — name the repeater for its rows (e.g. “Counter cards”), not the section (“Counters”).
  • A link and its image or text in the same place need DISTINCT names — e.g. opt-link=“Logo link” + opt-image=“Logo”, not both “Logo”.
  • Reuse the SAME name only on purpose (repeater rows, show/hide toggles). The converter flags accidental name clashes in the project Logs.
<!-- WRONG: repeater reuses its section/group name -->
<section fld-group="Counters">
  <div fld-loop="Counters"> ... </div>
</section>

<!-- RIGHT: distinct names -->
<section fld-group="Counters">
  <div fld-loop="Counter cards"> ... </div>
</section>

Multilingual Sites (Polylang / WPML)

If the source has two or more languages (a switcher, locale codes like ua/ru/en, or pages duplicated per language) it is multilingual. ThemeForge auto-detects Polylang or WPML — the markup is identical. Only two things differ from a single-language site:

  1. The language switcher uses wp-menu=“Language” — the language plugin injects the locale links.
  2. Every content field stores a value PER language. Use ONE field name (e.g. fld-text=“Heading”) — do NOT create “Heading EN” / “Heading RU”. The owner edits each language in the admin and the importer seeds every locale.

Language switcher — the recipe

<!-- Dropdown: toggle shows the CURRENT language (an options field),
     the list is a connected wp-menu="Language" (locales injected) -->
<div opt-hide="Hide language switcher" class="lang-drop w-dropdown">
  <div class="lang-dt w-dropdown-toggle">
    <div opt-text="Current language">UA</div>
  </div>
  <nav class="lang-drop-list w-dropdown-list">
    <div wp-menu="Language" class="lang-switcher">
      <a href="/en"><div>ENG</div></a>
      <a href="/ru"><div>РУС</div></a>
    </div>
  </nav>
</div>

<!-- Simple variant: a flat list of language links -->
<ul wp-menu="Language" class="header__languages">
  <li><a href="/">UA</a></li>
  <li><a href="/ru/">RU</a></li>
  <li><a href="/en/">EN</a></li>
</ul>

Site-wide opt-* fields (phone, address, nav labels) are per-language too, so each locale’s header/footer can differ. Mark them with opt-* as usual — no extra work.

On a multilingual site, do NOT:

  • hardcode any visible text — it becomes untranslatable; everything gets a field;
  • create one field per language — use one name, the CMS stores it per locale;
  • attribute the links inside wp-menu=“Language” — the plugin replaces them with its own locale links.

Detection tip: a header/footer language switcher (flags or ua/ru/en codes), or /ru/… and /en/… URL prefixes, means the site is multilingual — wire the switcher with wp-menu=“Language” and expect per-locale content. A single-language site needs none of this.

What NOT to Mark

  • Decorative elements: dividers, spacers, background overlays, SVG icons
  • Structural wrappers: grid containers, flex wrappers, layout scaffolding
  • Navigation links inside wp-menu (WordPress manages these)
  • Static UI labels: "Price:", "Quantity:", table headers
  • UI icons: search, cart, chevrons, arrows
  • Footer boilerplate: "All rights reserved", copyright year

Rule of thumb: if the site owner would want to change this from the admin panel, add an attribute. If it's UI chrome, skip it.

Checklist

  1. Every wp-fields-group section has a clear, unique name
  2. All repeater children have identical attributes with different content
  3. Images use <img> tags where possible
  4. Every link has BOTH a link attr + text attr (fld-link + fld-text, opt-phone-link + opt-text, etc.)
  5. Footer contacts use opt-* (options), not fld-*
  6. Tab divs are empty siblings with wp="delete-element"
  7. No attributes on decorative/structural elements
  8. Labels are human-readable English

Required Pages & Slugs

The file name (slug) determines which WordPress template is generated. Some pages are required, others depend on the site type (blog, shop).

theme-options.html — REQUIRED

You MUST create this page. It contains ALL opt-* fields used across the site (logo, navigation, phone, email, address, social links, copyright). Add wp-fields-group="Theme Options" on <body> and organize fields with opt-tab. Without this page, option fields will NOT appear in the WordPress admin panel.

<!-- theme-options.html -->
<body wp-fields-group="Theme Options">
  <div opt-tab="Header" wp="delete-element" class="tab-div"></div>
  <img opt-image="Logo" src="images/logo.png" />
  <nav opt-loop="Nav links" class="nav">
    <div class="nav-item">
      <a opt-link="Link" href="/about" class="nav-link w-inline-block">
        <div opt-text="Link text">About</div>
      </a>
    </div>
    <div class="nav-item">
      <a opt-link="Link" href="/contacts" class="nav-link w-inline-block">
        <div opt-text="Link text">Contacts</div>
      </a>
    </div>
  </nav>

  <div opt-tab="Footer" wp="delete-element" class="tab-div"></div>
  <a opt-phone-link="Phone" href="tel:...">+1 234 567</a>
  <a opt-email-link="Email" href="mailto:...">info@site.com</a>
  <p opt-text="Address">123 Main St</p>
  <div opt-text="Copyright">&copy; Company</div>
</body>

Slug → Template Mapping

Use these exact file names. Custom pages (about, services, contacts, etc.) can use any slug that doesn't conflict with the reserved names below.

File nameWP templateWhen to use
index.htmlindex.phpHome page (required)
about.htmlabout.phpCustom page — any slug
single.htmlsingle.phpSingle blog post (blog sites)
archive.htmlarchive.phpBlog posts list (blog sites)
404.html404.phpNot found page
search-page.htmlsearch.phpSearch results
single-product.htmlsingle-product.phpSingle product (WooCommerce)
archive-product.htmlarchive-product.phpProduct catalog (WooCommerce)
taxonomy-product-cat.htmltaxonomy-product-cat.phpProduct category archive (WooCommerce)
page-cart.htmlpage-cart.phpCart (WooCommerce)
page-checkout.htmlpage-checkout.phpCheckout (WooCommerce)
page-wishlist.htmlpage-wishlist.phpWishlist (WooCommerce)
page-my-account.htmlpage-my-account.phpMy account (WooCommerce)
single-{type}.htmlsingle-{type}.phpCustom post type — single / archive
theme-options.html—Site-wide options (admin panel only, no template)

Final Delivery — Do NOT Skip

After generating all pages with attributes, you MUST complete these steps:

  1. Create theme-options.html with ALL opt-* fields (see above)
  2. Save all HTML files to a single folder. Tell the user the folder name
  3. Give the user the complete list of ALL page slugs (filenames without .html), ready to paste into the ThemeForge generator page list:
  4. In ThemeForge, create a project, tick "The source will be uploaded on the site", paste the page list and download the blank theme. Install it on WordPress, upload the ZIP of your site in ThemeForge → Site source (its own item in the admin menu), and press "Update theme from project".
index, about, services, contacts, theme-options

tf-cors.php

Optional: if your site is already served from a localhost URL, you can point the project at that URL instead of uploading the archive on the site (see "Source on your site"). Create this file in the site root and start the server with: php -S localhost:8080 tf-cors.php. Only themeforge.pro is allowed — no other site can access your files.

<?php
// ThemeForge CORS Router — place in site root, run: php -S localhost:8080 tf-cors.php
$allowed = ['https://themeforge.pro', 'https://www.themeforge.pro', 'http://localhost:8081'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed, true)) header('Access-Control-Allow-Origin: ' . $origin);
elseif (empty($origin)) header('Access-Control-Allow-Origin: https://themeforge.pro');
header('Access-Control-Allow-Methods: GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$file = __DIR__ . $path;
if (is_dir($file)) $file = rtrim($file, '/') . '/index.html';
if (!is_file($file) && is_file($file . '.html')) $file .= '.html';
if (is_file($file)) {
    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
    $types = ['html'=>'text/html','css'=>'text/css','js'=>'application/javascript','json'=>'application/json',
        'png'=>'image/png','jpg'=>'image/jpeg','jpeg'=>'image/jpeg','gif'=>'image/gif','svg'=>'image/svg+xml',
        'webp'=>'image/webp','ico'=>'image/x-icon','woff'=>'font/woff','woff2'=>'font/woff2','ttf'=>'font/ttf'];
    if (isset($types[$ext])) header('Content-Type: ' . $types[$ext]);
    readfile($file); return true;
}
http_response_code(404); echo '404 Not Found';

Quick Reference

PAGE:        <body wp-fields-group="Page Name">  (ONE per page)
TAB:         <div fld-tab="Section" wp="delete-element" class="tab-div"></div>
GROUP:       <section fld-group="Section">  (ALWAYS after each tab)

TEXT:        <h2 fld-text="Heading">...</h2>
TEXTAREA:    <p fld-area="Description">...</p>
IMAGE:       <img fld-image="Photo" src="..." />
BG IMAGE:    <div fld-bg-image="BG" style="background-image:url(...)">
LINK+TEXT:   <a fld-link="Btn"><div fld-text="Btn text">Click</div></a>
REPEATER:    <div fld-loop="Items">  (all children = same attrs)
BUILDER:     <div fld-layouts="Page Sections"><section fld-layout="Hero">
             (client picks section types; previews are automatic)
             optional: layout-preview="off" | layout-preview="images/x.jpg"
TOGGLE:      <div fld-show="Show X">  or  <div fld-hide="Hide X">

NAV LINKS:   <nav opt-loop="Nav links"><div><a opt-link="Link"><div opt-text="Link text">...</div></a></div>…</nav>
OPTIONS:     opt-text, opt-image, opt-link, opt-phone-link, opt-email-link
LANG SWITCH: <div wp-menu="Language">  (Polylang only)
POST LOOP:   <div wp-query="'post_type'=>'post','posts_per_page'=>3">
PRODUCTS:    <div wp-product-query="'post_type'=>'product','posts_per_page'=>4">
CONDITION:   <div wp-if="on_sale">

Check the markup

Before you hand the site over, send all its pages to the free checker. It runs the real generator's parser — no account, nothing is stored — and lists what the generator would object to: error breaks the theme, warning means something is silently dropped, hint is worth knowing. Repeat until the reply says "ok": true.

POST /api/validate-markup

Send the whole set in one request: some checks are about the set rather than one file — whether theme-options.html exists, whether the home page is there.

POST https://themeforge.pro/api/validate-markup
Content-Type: application/json

{"pages":[
  {"name":"index.html","html":"<!doctype html>…"},
  {"name":"about.html","html":"…"},
  {"name":"theme-options.html","html":"…"}
]}

Advanced — AI Agent + Webflow MCP

The two prompts above work with any AI on a finished HTML page. If you build in Webflow, you can place the same attributes directly in the Designer with an AI agent (e.g. Claude Code) connected to the Webflow MCP — same rules, no copy-paste.

  • Same canon: the placement rules on this page are the single source of truth for both routes.
  • Either way the result is a set of attributed pages you hand to the ThemeForge generator (a published *.webflow.io URL or a local HTML folder).