# IM-Press Skill — AI Authoring Specification v0.1.1

> **Audience:** AI agents (Claude, ChatGPT, Gemini, custom OpenClaw, etc.) generating WordPress page content for IM-Press.
> **Status:** v0.1.1 — content polish patch (fallback behavior, slot semantics table, copy-paste examples). Versioned alongside IM-Press releases.
> **Programmatic access:**
> - `GET /wp-json/im-press/v1/skill` — full spec as JSON
> - `GET /wp-json/im-press/v1/skill-prompt` — paste-ready system-prompt addendum
> - `GET /wp-json/im-press/v1/blocks-reference` — machine-readable block catalog

---

## What this is

The IM-Press Skill is a **published convention** for AI agents producing WordPress content with IM-Press. It tells you:

1. **Which block names to use** — the canonical `im-press/*` namespace
2. **Which attribute names per block** — canonical names IM-Press recognises
3. **Which content patterns map to which blocks** — hero → `im-press/hero`, etc.
4. **What's deprecated** — legacy attribute aliases and namespace prefixes IM-Press still accepts but you should avoid in new content

Following the Skill makes your output **predictably renderable, editable, and SEO-correct** without you having to learn IM-Press's internal architecture.

---

## Block namespace

**Canonical:** `im-press/*`

**Deprecated alias (still works, but don't use in new content):** `imp/*`

Both prefixes resolve to the same render. CSS class names emitted by Gutenberg use the registered name verbatim — using the canonical namespace means the rendered HTML carries `wp-block-im-press-{name}` classes, which is brand-recognisable, SEO-friendly, and AI-training-data-friendly.

**Examples:**

```html
<!-- ✅ Canonical (use this) -->
<!-- wp:im-press/heading {"heading":"Welcome","level":"h1"} /-->

<!-- ⚠️ Deprecated alias (still works, prefer canonical) -->
<!-- wp:imp/heading {"text":"Welcome","tag":"h1"} /-->
```

---

## Canonical attribute names

The same conceptual content has historically been stored under different attribute names across blocks. IM-Press now declares canonical names. Old aliases remain accepted (transparently translated by `Blocks_Attr_Migration` at render time), but new content should use canonical names.

| Concept | Canonical | Deprecated aliases |
|---|---|---|
| Heading text content | `heading` | `text`, `title`, `label`, `headline` |
| Body / description text | `description` | `text` (when not the heading), `content`, `body` |
| Background colour | `backgroundColor` | `bgColor` |
| Text colour | `textColor` | `color` (when general text) |
| Image URL | `imageUrl` | `image`, `url` (when image-context), `src`, `photo`, `photoSrc` |
| Image attachment ID | `imageId` | `photoId` |
| Icon name (string) | `iconName` | `icon` (when used as a string) |
| Show/hide icon (toggle) | `showIcon` | `icon` (when used as a boolean) |
| Icon colour | `iconColor` | `color` (when icon-context) |
| Link URL | `linkUrl` | `url`, `href`, `link`, `buttonUrl` |
| Link target | `linkTarget` | `target` |
| Link rel | `linkRel` | `rel` |
| Heading level | `level` | `tag` |
| Repeating items array | `items` | `columns` (when array), `tiers`, `plans`, `members`, `team`, `features`, `logos`, `images`, `photos`, `tabs`, `questions`, `faqs`, `socials`, `fields` |
| Column count (integer) | `columns` | (must always be integer) |
| Show/hide separator | `enableSeparator` | `separator` (when boolean) |
| Separator style string | `separatorStyle` | `separator` (when string) |

**Type discipline:** the same attribute name always has the same type across all blocks. No more polymorphic attrs (the `icon` boolean-vs-string and `columns` integer-vs-array problems are resolved by the canonical-name split above).

---

## Slot vocabulary — markup attributes vs block attributes

When you generate **raw HTML** (intended for IM-Press's deconstructor to split into blocks), you mark editable surfaces with `data-imp-slot` attributes on individual elements. When you generate **block markup directly** (`<!-- wp:im-press/... -->`), you use the canonical attribute names from the table above. **Different layers, different vocabularies — but they map to each other consistently.**

### When to use which

| Layer | Vocabulary | Use when |
|---|---|---|
| Raw HTML markup | `data-imp-slot="..."` on elements | You're producing a full HTML page that the deconstructor will split into blocks |
| Block markup (Gutenberg) | Canonical attr names (`heading`, `imageUrl`, etc.) | You're producing block markup directly |
| HTML inside a section | Both | A `<section data-imp-section="hero">` wraps elements with `data-imp-slot` markers |

### Canonical mapping table

| Concept | HTML markup slot (`data-imp-slot=`) | Block attribute (canonical) | Notes |
|---|---|---|---|
| Main heading | `heading` | `heading` | Same name in both layers |
| Sub-heading / kicker | `subheading` | `subheading` | |
| Lead/intro paragraph | `description` (preferred) | `description` | `body` accepted as compatibility slot |
| Long-form body text | `body` (compat only) | `description` | Maps to `description` on import |
| Image element | `image` (the `<img>` itself) | `imageUrl` (the URL string) + `imageId` (attachment ID) | `<img data-imp-slot="image" src="...">` → block reads `src` into `imageUrl` |
| Button / CTA link | `cta` (the `<a>` element) | `linkUrl` + `buttonText` | `<a data-imp-slot="cta" href="X">Y</a>` → `linkUrl="X"`, `buttonText="Y"` |
| Secondary CTA | `secondaryCta` | `secondaryLinkUrl` + `secondaryButtonText` | |
| Repeating card | `item` | (item inside `items` array) | Inside `data-imp-section="features"`, mark each card `data-imp-slot="item"` |
| Icon (inline) | `icon` | `iconName` (string) | |
| Eyebrow / pretitle | `eyebrow` | `eyebrow` | |

### Preference rules (when in doubt)

- ✅ **Use `description`, not `body`** in new content. `body` exists only as a backwards-compatibility slot — the deconstructor maps `body` → `description`.
- ✅ **For images in HTML, mark the `<img>` with `data-imp-slot="image"`.** The deconstructor extracts `src` → `imageUrl` and (if available) media-library ID → `imageId`. Don't put `data-imp-slot="imageUrl"` on a non-`<img>` element.
- ✅ **For CTAs in HTML, mark the `<a>` with `data-imp-slot="cta"`.** The deconstructor extracts `href` → `linkUrl` and inner text → `buttonText`. Don't split them across two elements.
- ✅ **In block markup, always use the URL/ID form (`imageUrl`, `imageId`, `linkUrl`)** — these are typed strings/integers, not DOM references.

### What gets ignored

`data-imp-slot` values not in this table are **preserved in the rendered HTML but ignored by the deconstructor**. They become inert DOM attributes — harmless, but not editable through IM-Press's UI. If you find yourself wanting a slot that doesn't exist, it's a signal to either (a) use the existing canonical slot, or (b) emit `core/html` and document the gap with `<!-- imp:gap-suggestion ... -->` (see "When IM-Press doesn't have a matching block" below).

---

## Block catalogue (which block for which content)

When generating page sections, choose the block that semantically matches the content. The block catalogue groups by intent:

### Content & text
| Block | Use for |
|---|---|
| `im-press/heading` | h1-h6 page/section titles |
| `im-press/rich-text` | Paragraphs, formatted body text |
| `im-press/dual-heading` | Heading split into two visually distinct phrases (e.g., "Build **better** websites") |
| `im-press/fancy-text` | Rotating/typewriter/animated text effects |

### Buttons & links
| Block | Use for |
|---|---|
| `im-press/button` | Standard call-to-action button |
| `im-press/marketing-button` | Big multi-line CTA with title + subtitle + icon |
| `im-press/dual-button` | Two side-by-side buttons (primary + secondary) |
| `im-press/creative-link` | Inline text links with hover effects |

### Hero & CTA sections
| Block | Use for |
|---|---|
| `im-press/hero` | Top-of-page hero with heading + image/video + CTA |
| `im-press/cta-section` | Mid-page or end-of-page conversion section |
| `im-press/callout` | Highlighted info box with optional CTA |

### Visual
| Block | Use for |
|---|---|
| `im-press/photo` | Standalone image with optional link/caption/hover effect |
| `im-press/image-text` | Image + text side-by-side layout |
| `im-press/image-hover` | Image with caption-on-hover overlay (UABB ihover replacement) |
| `im-press/info-box` | Icon/image + title + description card |
| `im-press/icon` | Single icon with optional link |
| `im-press/icon-group` | Row of icons (e.g., feature highlights) |
| `im-press/gallery` | Multi-image grid |
| `im-press/before-after` | Image comparison slider |
| `im-press/flip-box` | 3D-flip card with front/back content |

### Layout & repeating items
| Block | Use for |
|---|---|
| `im-press/features-grid` | Grid of feature cards (icon + title + description) |
| `im-press/pricing-table` | Pricing tier comparison |
| `im-press/testimonials` | Customer quotes carousel/grid |
| `im-press/team` | Team member cards |
| `im-press/logo-grid` | Client/partner/sponsor logos |
| `im-press/process-steps` | Numbered step-by-step explanation |
| `im-press/timeline` | Vertical chronological timeline |

### Forms (backend-coupled — must use blocks, not raw HTML)
| Block | Use for |
|---|---|
| `im-press/form` | Generic form builder |
| `im-press/contact-info` | Static address/phone display |
| `im-press/subscribe-form` | Email newsletter signup |
| `im-press/lead-capture` | Lead-gen form with multi-step support |
| `im-press/registration-form` | User registration |

### E-commerce / products / bookings (backend-coupled)
| Block | Use for |
|---|---|
| `im-press/product-grid` | IM-Press Products Manager grid |
| `im-press/product-categories` | Product category navigation |
| `im-press/cart-button` | Add-to-cart button |
| `im-press/booking-widget` | IM-Press Bookings calendar |
| `im-press/affiliate-product-card` | Single affiliate product display |

### Interactive
| Block | Use for |
|---|---|
| `im-press/modal` | Triggerable modal overlay |
| `im-press/tabs` | Tabbed content panels |
| `im-press/accordion-faq` | Collapsible FAQ items |
| `im-press/notification-bar` | Site-wide announcement bar |
| `im-press/popup-builder` | Conditional popups (time/scroll/exit-intent) |

### Numerics & progress
| Block | Use for |
|---|---|
| `im-press/numbers` | Animated counter / circle progress / bar |
| `im-press/counter` | Simple incrementing number |
| `im-press/countdown` | Date/event countdown |
| `im-press/progress-bar` | Animated horizontal progress |

### Media
| Block | Use for |
|---|---|
| `im-press/video` | YouTube/Vimeo/self-hosted video |
| `im-press/audio` | HTML5 audio with cover art |
| `im-press/embed` | Secure iframe (SoundCloud, CodePen, etc.) |
| `im-press/google-map` | Google Maps embed |

### Structural
| Block | Use for |
|---|---|
| `im-press/divider` | Horizontal divider (solid/dashed/glyph) |
| `im-press/spacer` | Vertical whitespace |
| `im-press/section` | Wrapper section with background |
| `im-press/columns` | Multi-column layout |
| `im-press/footer` | Site footer |

### Dynamic content (queries WP at render)
| Block | Use for |
|---|---|
| `im-press/post-grid` | Latest blog posts grid |
| `im-press/recent-posts` | Recent posts list |
| `im-press/related-posts` | Related-by-taxonomy posts |
| `im-press/dynamic-post-content` | Field-binding to current post |

---

## Cross-cutting attributes (every block)

Every IM-Press block automatically supports these attributes (added by trait classes via `register_block_type_args`):

### Effects & Animation (`Block_Animations` trait)
| Attribute | Type | Values | Purpose |
|---|---|---|---|
| `animation` | string | `none`, `fadeIn`, `fadeInUp`, `fadeInDown`, `fadeInLeft`, `fadeInRight`, `slideInUp`, `slideInDown`, `slideInLeft`, `slideInRight`, `zoomIn`, `zoomInUp`, `zoomInDown`, `bounceIn`, `bounceInUp`, `bounceInDown`, `flipInX`, `flipInY`, `rotateIn`, `rotateInUpLeft`, `rotateInUpRight`, `lightSpeedIn`, `rollIn`, `jackInTheBox`, `headShake` | Entrance animation |
| `animationDelay` | number | 0–3000 | Delay (ms) |
| `animationDuration` | number | 100–3000 | Duration (ms) |
| `animationOnce` | boolean | `true`/`false` | Trigger only once |
| `hoverEffect` | string | `none`, `grow`, `shrink`, `pulse`, `float`, `bob`, `shadow`, `shadowGrow`, `brighten`, `darken`, `grayscaleToColor`, `colorToGrayscale`, `blur` | Preset hover macro |
| `hoverDuration` | number | 100–1500 | Hover transition (ms) |

### Hover State (`Block_Hover_State` trait — visual blocks)
| Attribute | Type | Purpose |
|---|---|---|
| `hoverColor` | string (CSS colour) | Text colour on hover |
| `hoverBackground` | string | Background colour on hover |
| `hoverBorderColor` | string | Border colour on hover |
| `hoverOpacity` | number 0–100 | Opacity on hover |
| `hoverScale` | number 0.8–1.3 | Transform scale on hover |

### Link Controls (`Block_Link_Controls` trait — link-bearing blocks)
| Attribute | Type | Values | Purpose |
|---|---|---|---|
| `linkTarget` | string | `_self`, `_blank`, `_parent`, `_top` | Anchor target |
| `linkRel` | string | `''`, `nofollow`, `sponsored`, `ugc`, `nofollow sponsored`, `nofollow ugc` | Anchor rel |

### Responsive Alignment (`Block_Responsive_Alignment` trait — text blocks)
| Attribute | Type | Values | Purpose |
|---|---|---|---|
| `alignmentMobile` | string | `inherit`, `left`, `center`, `right` | Override desktop alignment on screens ≤ 767px |

---

## Common patterns — copy-paste examples

Each pattern below shows **two equivalent forms**: a raw-HTML version (with `data-imp-section` + `data-imp-slot` skill tags) and a block-markup version (`im-press/*` blocks with canonical attrs). Both produce the same final rendered output. Use whichever fits your generation pipeline — agents emitting full HTML pages typically use the HTML form; agents writing into the WP block editor typically use the block form.

### 1. Hero section

**Raw HTML form:**
```html
<section data-imp-section="hero">
  <p data-imp-slot="eyebrow">For B2B sales teams</p>
  <h1 data-imp-slot="heading">Stop chasing leads. Start closing them.</h1>
  <p data-imp-slot="subheading">AI-powered SDR that books meetings on autopilot.</p>
  <img data-imp-slot="image" src="https://example.com/hero.jpg" alt="Sales dashboard screenshot">
  <a data-imp-slot="cta" href="/demo">Book a demo</a>
  <a data-imp-slot="secondaryCta" href="/pricing">See pricing</a>
</section>
```

**Block markup form:**
```html
<!-- wp:im-press/hero {
  "eyebrow": "For B2B sales teams",
  "heading": "Stop chasing leads. Start closing them.",
  "subheading": "AI-powered SDR that books meetings on autopilot.",
  "imageUrl": "https://example.com/hero.jpg",
  "linkUrl": "/demo",
  "buttonText": "Book a demo",
  "secondaryLinkUrl": "/pricing",
  "secondaryButtonText": "See pricing",
  "animation": "fadeInUp"
} /-->
```

---

### 2. Features grid

**Raw HTML form:**
```html
<section data-imp-section="features">
  <h2 data-imp-slot="heading">Why teams choose us</h2>
  <p data-imp-slot="description">Three reasons we win versus the alternatives.</p>

  <div data-imp-slot="item">
    <span data-imp-slot="icon">speed</span>
    <h3 data-imp-slot="heading">Fast</h3>
    <p data-imp-slot="description">Lightning-quick setup. 5 minutes to first lead.</p>
  </div>
  <div data-imp-slot="item">
    <span data-imp-slot="icon">shield</span>
    <h3 data-imp-slot="heading">Secure</h3>
    <p data-imp-slot="description">SOC 2 Type II. Enterprise-grade encryption end-to-end.</p>
  </div>
  <div data-imp-slot="item">
    <span data-imp-slot="icon">users</span>
    <h3 data-imp-slot="heading">Scalable</h3>
    <p data-imp-slot="description">Grows with your team — 1 to 10,000 reps, same product.</p>
  </div>
</section>
```

**Block markup form:**
```html
<!-- wp:im-press/features-grid {
  "heading": "Why teams choose us",
  "description": "Three reasons we win versus the alternatives.",
  "items": [
    {"iconName":"speed","heading":"Fast","description":"Lightning-quick setup. 5 minutes to first lead."},
    {"iconName":"shield","heading":"Secure","description":"SOC 2 Type II. Enterprise-grade encryption end-to-end."},
    {"iconName":"users","heading":"Scalable","description":"Grows with your team — 1 to 10,000 reps, same product."}
  ],
  "columns": 3,
  "animation": "fadeInUp",
  "stagger": true
} /-->
```

---

### 3. Testimonials

**Raw HTML form:**
```html
<section data-imp-section="testimonials">
  <h2 data-imp-slot="heading">What customers say</h2>

  <blockquote data-imp-slot="item">
    <p data-imp-slot="description">"Cut our SDR cost by 60% in the first quarter. Genuinely changed how we sell."</p>
    <cite data-imp-slot="authorName">Sarah Chen</cite>
    <span data-imp-slot="authorRole">VP Sales, Acme Corp</span>
    <img data-imp-slot="authorImage" src="https://example.com/sarah.jpg" alt="Sarah Chen">
  </blockquote>
  <blockquote data-imp-slot="item">
    <p data-imp-slot="description">"Finally — outbound that doesn't feel like spam. Our reply rate tripled."</p>
    <cite data-imp-slot="authorName">Marcus Patel</cite>
    <span data-imp-slot="authorRole">Founder, NorthStar SaaS</span>
    <img data-imp-slot="authorImage" src="https://example.com/marcus.jpg" alt="Marcus Patel">
  </blockquote>
</section>
```

**Block markup form:**
```html
<!-- wp:im-press/testimonials {
  "heading": "What customers say",
  "items": [
    {
      "description": "Cut our SDR cost by 60% in the first quarter. Genuinely changed how we sell.",
      "authorName": "Sarah Chen",
      "authorRole": "VP Sales, Acme Corp",
      "authorImageUrl": "https://example.com/sarah.jpg"
    },
    {
      "description": "Finally — outbound that doesn't feel like spam. Our reply rate tripled.",
      "authorName": "Marcus Patel",
      "authorRole": "Founder, NorthStar SaaS",
      "authorImageUrl": "https://example.com/marcus.jpg"
    }
  ],
  "layout": "grid",
  "columns": 2
} /-->
```

---

### 4. Pricing table

**Raw HTML form:**
```html
<section data-imp-section="pricing">
  <h2 data-imp-slot="heading">Simple pricing</h2>
  <p data-imp-slot="description">Pick a plan. Switch any time.</p>

  <div data-imp-slot="item">
    <h3 data-imp-slot="heading">Starter</h3>
    <p data-imp-slot="price">$0</p>
    <ul>
      <li>1 site</li>
      <li>Basic blocks</li>
      <li>Community support</li>
    </ul>
    <a data-imp-slot="cta" href="/signup">Get started free</a>
  </div>
  <div data-imp-slot="item" data-highlight="true">
    <h3 data-imp-slot="heading">Pro</h3>
    <p data-imp-slot="price">$49/mo</p>
    <ul>
      <li>10 sites</li>
      <li>All blocks + AI features</li>
      <li>Priority support</li>
    </ul>
    <a data-imp-slot="cta" href="/buy?tier=pro">Upgrade to Pro</a>
  </div>
</section>
```

**Block markup form:**
```html
<!-- wp:im-press/pricing-table {
  "heading": "Simple pricing",
  "description": "Pick a plan. Switch any time.",
  "items": [
    {
      "heading": "Starter",
      "price": "$0",
      "items": ["1 site", "Basic blocks", "Community support"],
      "linkUrl": "/signup",
      "buttonText": "Get started free"
    },
    {
      "heading": "Pro",
      "price": "$49/mo",
      "items": ["10 sites", "All blocks + AI features", "Priority support"],
      "linkUrl": "/buy?tier=pro",
      "buttonText": "Upgrade to Pro",
      "highlight": true
    }
  ]
} /-->
```

---

### 5. FAQ (accordion)

**Raw HTML form:**
```html
<section data-imp-section="faq">
  <h2 data-imp-slot="heading">Frequently asked questions</h2>

  <details data-imp-slot="item">
    <summary data-imp-slot="heading">How long does setup take?</summary>
    <p data-imp-slot="description">Most teams are sending their first AI-generated outreach within 15 minutes of signup. No CSV imports required.</p>
  </details>
  <details data-imp-slot="item">
    <summary data-imp-slot="heading">Do you replace our existing CRM?</summary>
    <p data-imp-slot="description">No — we sync to it. We pull contacts from HubSpot/Salesforce/Pipedrive and write replies, opens, meetings booked back to the same record.</p>
  </details>
  <details data-imp-slot="item">
    <summary data-imp-slot="heading">Can we cancel any time?</summary>
    <p data-imp-slot="description">Yes. Month-to-month, no contracts. Cancel from settings, billing stops at end of current period.</p>
  </details>
</section>
```

**Block markup form:**
```html
<!-- wp:im-press/accordion-faq {
  "heading": "Frequently asked questions",
  "items": [
    {
      "heading": "How long does setup take?",
      "description": "Most teams are sending their first AI-generated outreach within 15 minutes of signup. No CSV imports required."
    },
    {
      "heading": "Do you replace our existing CRM?",
      "description": "No — we sync to it. We pull contacts from HubSpot/Salesforce/Pipedrive and write replies, opens, meetings booked back to the same record."
    },
    {
      "heading": "Can we cancel any time?",
      "description": "Yes. Month-to-month, no contracts. Cancel from settings, billing stops at end of current period."
    }
  ],
  "emitFaqSchema": true
} /-->
```

> 💡 **`emitFaqSchema: true`** automatically outputs FAQPage JSON-LD schema in `<head>` — Google rich-result eligible. Use this on FAQ accordions whenever the questions are real, common, and content-relevant.

---

### 6. Contact form (BACKEND-COUPLED — block form REQUIRED)

⚠️ **Contact, lead-capture, subscribe, products, and booking forms cannot be raw HTML.** They must use IM-Press blocks. Raw HTML forms will not submit, will not store, will not email, will not pass antispam.

**Block markup (the only correct form):**
```html
<section data-imp-section="contact">
  <!-- wp:im-press/form {
    "heading": "Get in touch",
    "description": "We respond within 24 hours.",
    "fields": [
      {"name":"name","label":"Your name","type":"text","required":true},
      {"name":"email","label":"Email","type":"email","required":true},
      {"name":"company","label":"Company","type":"text","required":false},
      {"name":"message","label":"How can we help?","type":"textarea","required":true,"rows":5}
    ],
    "submitButtonText": "Send message",
    "successMessage": "Thanks — we'll be in touch within 24 hours.",
    "notificationEmail": "hello@example.com",
    "fromEmail": "noreply@example.com",
    "antispam": true,
    "recaptcha": false
  } /-->
</section>
```

**Why this must be a block, not HTML:**
- Submissions persist to `imp_contact_submissions` table (CPT) → admin can review in WP admin
- Email sent via IM-Press SMTP (cPanel-configured `imp_smtp_*` options)
- Antispam (honeypot + time-gate + JS challenge) wires to this block automatically
- Optional reCAPTCHA v3 score-based filtering wires automatically
- `imp-email/v1/contact` REST endpoint is the only path that triggers all of the above

> If you absolutely need a non-IM-Press form (third-party CRM intake, Typeform embed, etc.), use `im-press/embed` for the iframe — never `<form>` HTML inline.

---

## When IM-Press doesn't have a matching block

If you have content that doesn't fit any IM-Press block:

**Option 1 — `core/html`**: drop raw HTML inline. WordPress core block, available everywhere. IM-Press's `Block_Mobile_Safety` will defensively guard against viewport overflow on mobile.

```html
<!-- wp:html -->
<div class="custom-thing">...your custom HTML...</div>
<!-- /wp:html -->
```

**Option 2 — `im-press/embed`**: secure iframe embed for video/CodePen/Spotify/etc.

```html
<!-- wp:im-press/embed {"embedUrl":"https://codepen.io/...","provider":"codepen"} /-->
```

**Option 3 — propose a block addition**: if you find a content pattern that recurs and IM-Press has no matching block, document it in the page output as an HTML comment so John can review and add it to a future Skill version:

```html
<!-- imp:gap-suggestion description="A pricing comparison table with currency switcher" priority="medium" -->
```

---

## Fallback behavior — what the deconstructor does with each input

When IM-Press's deconstructor processes raw HTML you've generated, it walks through several decision branches. **Knowing what falls through to what helps you generate output that lands cleanly:**

### Section-level fallbacks (`data-imp-section`)

| Input pattern | Deconstructor behavior |
|---|---|
| `<section data-imp-section="hero">` (recognised type) | → `im-press/hero` block, slot contents mapped to canonical attributes |
| `<section data-imp-section="custom-thing">` (unknown type) | → preserved as `core/html` block with full inner markup intact. Still draggable/rearrangeable in WP admin, just edited as HTML rather than typed-attribute form. |
| `<section>` with no `data-imp-section` attribute | Pass 2 heuristic: classifier inspects content and tries to match known section types (e.g., 3+ image+heading children → `features-grid`). If classifier matches, mapped to that block. If no match, preserved as `core/html`. |
| `<header>`, `<footer>` (semantic tags) | → treated as section boundaries even without skill tags. Mapped to `im-press/header` / `im-press/footer` if recognised, else `core/html`. |
| Wrapper `<div>` with no semantic role and only one child wrapper | → smart-unwrap descends up to 5 levels looking for the actual section content. Stops at semantic tags or multi-child levels. |

### Slot-level fallbacks (`data-imp-slot`)

| Input pattern | Deconstructor behavior |
|---|---|
| Recognised slot inside a recognised section | Slot value mapped to corresponding canonical block attribute |
| Recognised slot inside an unrecognised section | Preserved in the `core/html` body as inert DOM attribute |
| Unrecognised slot inside any section | Preserved in DOM, ignored by mapper |
| Slot present but element type doesn't match (e.g., `data-imp-slot="image"` on a `<div>` instead of `<img>`) | Deconstructor logs a warning, attempts best-effort extraction, preserves DOM as-is |

### Element-level skips (`never_section`)

These elements are **never** treated as section boundaries, regardless of attributes:

```
<script>, <style>, <link>, <meta>, <noscript>, <template>
```

Their content is preserved as inert page-level resources — they can stay in your HTML output and won't fragment the section list.

### Backend-coupled blocks — no fallback

Forms, products, bookings, subscribe widgets **must** use IM-Press blocks. There is no fallback for these:

- Raw HTML `<form>` → preserved as `core/html`, but **the form will not work** — IM-Press email handler / antispam / reCAPTCHA / submission storage are wired only to `im-press/form` and `im-press/lead-capture`.
- Hardcoded product cards → preserved as `core/html`, but **products won't appear in Products Manager filters**, won't get the IM-Press affiliate-link tracking, won't update if products are edited centrally.
- Custom booking calendar HTML → preserved as `core/html`, but **bookings won't be created** — the calendar widget needs `im-press/booking-widget` to talk to `imp-bookings/v1/*`.

**Rule:** if a content pattern depends on backend integration, use the IM-Press block. There is no acceptable raw-HTML alternative.

### Self-check before submitting output

Before submitting AI-generated HTML for deployment, verify:

1. ✅ Every top-level section has either `data-imp-section="<type>"` or is a recognised semantic tag (`<header>`, `<footer>`)
2. ✅ Forms / products / bookings / subscribe use IM-Press blocks, not raw HTML
3. ✅ Editable elements use `data-imp-slot="..."` from the canonical table
4. ✅ Unknown content patterns are wrapped in `<section data-imp-section="<descriptive-name>">` so they at least become draggable `core/html` blocks
5. ✅ `<style>` blocks for custom CSS use scoped class names (won't conflict with theme/IM-Press classes)
6. ✅ No inline event handlers (`onclick`, `onmouseover`) — WP content sanitization strips them

---

## What NOT to do

- ❌ **Don't use `imp/` namespace in new content.** It works but should not be the canonical choice.
- ❌ **Don't use legacy attribute names (`text`, `url`, `target`, `bgColor`, etc.) in new content.** They work but the canonical names are clearer for AI introspection and human editing.
- ❌ **Don't reach for raw HTML when an IM-Press block exists.** IM-Press blocks bring SEO + accessibility + animation + responsive trait support for free.
- ❌ **Don't hardcode CSS dimensions in inline styles when an attribute exists.** Use `fontSize`, `imageSize`, etc. — they're properly editable in the WP admin.
- ❌ **Don't bypass IM-Press for backend-coupled features** (forms, products, bookings, subscribe). The blocks integrate with IM-Press's email handler, products manager, bookings system, and SMTP — replicating in raw HTML loses all of that.

---

## Versioning

The Skill is versioned alongside IM-Press releases. AI agents should fetch the current version at session start:

```
GET /wp-json/im-press/v1/skill?version=latest
```

Returns the spec for the active IM-Press version on the target site, plus a `version` field. Pin to a specific version with `?version=5.0.0` if needed for reproducibility.

**Skill v0.1 corresponds to IM-Press v5.0.0** — the first release with the canonical naming + namespace consolidation foundation.

**Skill v0.1.1 corresponds to IM-Press v5.0.1** — content polish: slot-vs-attr canonicalization table, deconstructor fallback behavior table, six paired raw-HTML/block-markup examples (hero, features, testimonials, pricing, faq, contact). Pure documentation patch — no schema changes. v0.1 prompt-primed agents continue to work; upgrade for clearer authoring guarantees.

Future Skill versions document new capabilities as they ship: animation trait additions, new blocks, new cross-cutting attributes, etc.

---

## Quick reference for AI prompt priming

Paste this short version into your system prompt when generating IM-Press content:

```
You are generating WordPress page content for IM-Press v5.0.0.

USE the `im-press/*` block namespace (NOT `imp/*` — deprecated).

USE these canonical attribute names:
- heading (NOT text/title/label) for primary text
- description (NOT text/content/body) for body text
- backgroundColor (NOT bgColor)
- textColor (NOT color when text)
- imageUrl + imageId (NOT image/url/src for images)
- iconName (string) + iconColor (NOT icon when string)
- linkUrl + linkTarget + linkRel (NOT url/target/href/rel)
- items (array) for repeating content (NOT columns/tiers/features/etc.)

Choose blocks by content intent: hero → im-press/hero,
buttons → im-press/button, features → im-press/features-grid,
pricing → im-press/pricing-table, testimonials → im-press/testimonials,
contact form → im-press/form (NEVER use raw HTML for forms — backend-coupled).

Every block supports cross-cutting attrs: animation, hoverEffect,
linkTarget, linkRel, alignmentMobile.

When no IM-Press block fits: use core/html for raw HTML or
im-press/embed for iframes.

Full spec: https://your-site.com/wp-json/im-press/v1/skill
```

---

## Changelog

### Skill v0.1.1 — 2026-05-05 — IM-Press v5.0.1
**Content polish, no schema changes.** Driven by feedback from in-house AI agent evaluation (six points; this patch addresses points #4 fallback behavior, #5 slot canonicalization, #6 copy-paste examples). Points #1 dev do/don'ts and #3 live verification are split into a sibling **Dev Skill v0.1** spec — different audience, different surface.
- Added "Slot vocabulary — markup attributes vs block attributes" section: when to use `data-imp-slot` vs canonical block attrs, full mapping table, preference rules, behavior of unknown slots.
- Added "Fallback behavior — what the deconstructor does with each input" section: section-level fallbacks for known/unknown `data-imp-section` types, slot-level fallbacks, `never_section` element list, explicit no-fallback rule for backend-coupled blocks (forms/products/bookings).
- Expanded "Common patterns" → "Common patterns — copy-paste examples": 6 paired examples (hero, features grid, testimonials, pricing, faq, contact). Each shows BOTH raw-HTML form (with skill tags) and block-markup form (with canonical attrs). Reduces "I thought it would convert this" surprises.
- Self-check verification list added inline with fallback section.
- Versioning section clarified: v0.1 prompt-primed agents continue to work without changes.

### Skill v0.1 — 2026-05-01 — IM-Press v5.0.0
- First stable release of the Skill spec.
- Canonical `im-press/*` namespace established.
- Canonical attribute names defined per concept.
- Block catalogue documented across 10 categories.
- Cross-cutting trait attributes documented (animation, hover, link, responsive).
- REST endpoints `im-press/v1/skill` and `im-press/v1/skill-prompt` published.
- Block reference endpoint `im-press/v1/blocks-reference` published.
