Publishers · Catalog

How to build great Store components

A practical playbook for component authors: choose the right shape, design for hosted buyers, wire fields and slots correctly, and package a bundle that scores well.

Start here if you ship to the Store
This page is the publisher-facing companion to Custom components. Implement locally first, then package with the listing wizard.

1. Pick the right product shape

NameTypeDescription
Primitive on the pagepreferSingle heading, image, link, or form value — do not package as a Store component.
Content blockpresentationStructure + behavior; inherits host design. Best default for reusable sections.
Styled widgetpresentationShips its own look via design fields / CSS variables. Be honest in the listing.
Items slot componentpatternEditors grow a list (slides, cards). Shell settings stay in fields[].
One listing = one presentation
Do not mix “inherits the site” and “ships its own skin” in a single listing. If you need both, publish two listings (or two typeIds). Buyers see Macro Score reasons when the scanner disagrees with your presentation claim.

2. Design for hosted buyers first

Most Store installs run your hosted bundle. Buyers cannot fork your CSS unless they purchase code access. Design through:

  • fields[] the overlay can edit (content + optional design group).
  • CSS variables / tokens the host can override when you document them.
  • Items slots for structure editors must grow (slides, cards, FAQ rows).
  • Project slots only when the site developer must drop arbitrary HTML into a region (rare for pure Store widgets).

3. Recommended architecture

  1. Shell settings in fields

    Autoplay, interval, layout mode, density — small JSON payload. Keep labels buyer-friendly; they appear in the overlay.

    typescript
    fields: [
      { key: 'autoplay', label: 'Autoplay', input: 'boolean', group: 'content' },
      { key: 'intervalMs', label: 'Interval (ms)', input: 'number', group: 'content' },
    ]
  2. Repeating content in items slots

    Each slot field becomes a real primitive node (inline editable). Editors get Add / Remove / Reorder for free — no custom sidebar required.

    typescript
    slots: [
      {
        name: 'slides',
        kind: 'items',
        label: 'Slides',
        min: 1,
        max: 12,
        fields: [
          { field: 'image', type: 'image', label: 'Image' },
          { field: 'headline', type: 'text', label: 'Headline' },
          { field: 'body', type: 'richtext', label: 'Body' },
          { field: 'cta', type: 'link', label: 'Call to action' },
        ],
      },
    ]
  3. render() builds chrome + mounts regions

    Use mountSlotRegion for items. Cache-aware: safe to clear the host and re-append the returned region. Observe [data-macro-repeater-item] if you need nav dots derived from the DOM.

    typescript
    import { macroSlotField, mountSlotRegion } from '@macrocontent/sdk'
    
    function buildSlide(doc: Document): HTMLElement {
      const article = doc.createElement('article')
      const img = doc.createElement('img')
      Object.entries(macroSlotField('image', 'image')).forEach(([k, v]) =>
        img.setAttribute(k, v),
      )
      const h3 = doc.createElement('h3')
      Object.entries(macroSlotField('headline', 'text')).forEach(([k, v]) =>
        h3.setAttribute(k, v),
      )
      article.append(img, h3)
      return article
    }
    
    const region = mountSlotRegion({
      host,
      mountTarget: viewport,
      name: 'slides',
      kind: 'items',
      seed: 3,
      max: 12,
      buildItem: () => buildSlide(host.ownerDocument),
    })
  4. Inline affordances on visible content

    Apply macroSlotField / macroFieldAttr / macroAssetFieldAttr so editors click on the page. For carousels, mark the visible item so image context actions hit the right slide.

4. Content-block CSS rules

content-block.css
.my-block {
  color: inherit;
  font: inherit;
}

.my-block__accent {
  color: var(--macro-accent, currentColor);
}

.my-block__card {
  border-radius: var(--macro-radius, 0.5rem);
}

Do

  • Inherit typography and color from the host.
  • Expose 1–3 tokens max (--macro-accent, --macro-radius).
  • Use currentColor for icons and borders when possible.

Don’t

  • Don’t hardcode brand purples/oranges that fight the customer site.
  • Don’t ship a full design system inside a “content” listing.
  • Don’t hide critical content behind hover-only UI without keyboard access.

5. Styled-widget rules

  • Put theme / accent / radius (and similar) in group: 'design' so editors find them under a Design sub-tab.
  • Drive the look from CSS variables set in render() from the payload.
  • Still avoid baking customer content into the bundle — images and copy come from Macro assets / fields / slots.
styled-fields.ts
fields: [
  { key: 'title', label: 'Title', input: 'text', inline: true, group: 'content' },
  {
    key: 'theme',
    label: 'Theme',
    input: 'select',
    group: 'design',
    options: [
      { value: 'light', label: 'Light' },
      { value: 'dark', label: 'Dark' },
    ],
  },
  { key: 'accent', label: 'Accent', input: 'text', group: 'design' },
  { key: 'radius', label: 'Radius', input: 'text', group: 'design' },
]

6. typeId, tag, and packaging

  • Declare a namespaced typeId (@your-brand/my-slider). Macro derives the custom element tag for Store bundles.
  • Keep defaultPayload demo-ready — empty installs should still look intentional.
  • Ship gallery / preview assets that match the runtime. The Store can embed website + editor demos so buyers try inline edit before installing.
  • Run the bundle through validation before publish — see Bundles & Macro Score.

7. Quality bar (what buyers notice)

NameTypeDescription
Honest presentationscoreListing claim matches CSS reality (content vs styled).
Editable structureuxItems slots (or clear fields) instead of frozen placeholder copy.
Inline where it mattersuxHeadlines and images editable on the page, not only in a JSON dump.
Clean bundlesecurityNo secrets, no forbidden scanner patterns, no surprise network calls.
Preview fidelitystoreGallery and demos match what install + editor actually show.

8. Local → Store workflow

  1. Build and register locally with Custom components.
  2. Exercise draft/live, locales, assets, and slots with a real editor account.
  3. Package the bundle; fix Macro Score findings (forbidden patterns, presentation drift).
  4. Complete the listings wizard (presentation, pricing, previews).
  5. Publish a release — Releases & updates.

Reference components