> ## Documentation Index
> Fetch the complete documentation index at: https://docs-loja.usecorvex.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime API (@corvex/runtime)

> Fronteira pública entre temas e a plataforma — o que importar, quando usar e boas práticas para agências e agentes de código.

# `@corvex/runtime`

Bundle host que a **plataforma injeta** ao compilar temas. **Não** é um pacote npm — importe `@corvex/runtime` nos arquivos do tema.

Contrato de dados da loja: [`@corvex/theme-sdk`](https://docs-loja.usecorvex.com.br/sdk/overview). Esta página cobre **vitrine**, **integração com o Editor** e **boas práticas** para quem implementa sections com blocks.

## Runtime como proxy do builder

O editor usa um motor interno de árvore de blocos (implementação da plataforma). **Temas não importam esse motor.** `@corvex/runtime` é o **proxy Corvex**: hooks e componentes que leem o estado da section no builder, espelham `blocks` / `block_order` nos props e permitem preview ao vivo na vitrine do canvas.

Quem cria o tema **escolhe** como compor a section — Padrão A (`{children}`), B (marquee / settings), C (grade com `RepeatedBlockCard`), ou layout customizado montado com os mesmos exports desta página. Não há lista fechada de “permitido”: há **ferramentas** documentadas e contratos (`blocks`, `block_order`, `schema.json`).

**Limite de fronteira (código do tema):** não importe o motor do editor, não declare propriedade estática no componente e não importe caminhos internos da plataforma. Fora isso, combine os símbolos desta página como o plano do tema exigir.

> [!WARNING]
>
> Importe **somente** os símbolos listados em **PUBLIC\_THEME\_API** e **PUBLIC\_EDITOR\_INTEGRATION**. APIs marcadas como INTERNAL podem quebrar entre versões do editor.

***

## Regras de ouro (agências e LLMs)

1. **Dados da loja** → `@corvex/theme-sdk` (`usePage`, `useCorvexCart`, `defineSectionData`, …).
2. **Chrome do Editor e blocks ao vivo** → `@corvex/runtime` (esta página).
3. **Nunca** importe paths internos da plataforma, hooks não documentados aqui ou pacotes que o host já substitui (`react` continua vindo do host no bundle).
4. **Mesma árvore visual** no canvas do builder, em `/preview` e na vitrine — o inspect do editor **não** deve trocar layout, grid ou carrossel.
5. Sections com **blocks** têm **dois padrões** (A e B abaixo) — **nunca misture** `{children}` no editor com cards montados manualmente a partir de `blocks`/`block_order`.
6. **Integração com o builder** só via `@corvex/runtime` e `@corvex/theme-sdk`. Não importe o motor do editor nem código interno da plataforma.
7. Depois de alterar JSX de section/block: `corvex validate .` → `corvex build .` → `corvex sync .` → hard refresh no builder.

***

## Onde o tema roda

| Ambiente | Como identificar | Integração runtime |
| - | - | - |
| **Canvas do builder** | iframe com `?theme=` | Hooks de blocks ao vivo; `useEditorPreviewCanvas()` → `true` |
| **Preview em aba** | `/preview?theme=` | Mesmo JSX da vitrine; sem hooks exclusivos do canvas |
| **Vitrine publicada** | domínio da loja | Só **PUBLIC\_THEME\_API** + props `blocks` / `block_order` serializados |

Use `useEditorPreviewCanvas()` para saber se está no iframe do builder — **não** confunda com “qualquer preview”.

***

## PUBLIC\_THEME\_API (vitrine)

Use na loja publicada, em `/preview` e sempre que não precisar de estado ao vivo do editor:

| Import | Uso |
| - | - |
| `useCorvexCart()` | Carrinho — [Cart Contract](https://docs-loja.usecorvex.com.br/reference/contracts/cart.md) |
| `useStorefrontMenus(handles)` | Menu por handle — [menus](https://docs-loja.usecorvex.com.br/data/menus-blog.md) |
| `StorefrontNav` | Links de `menu.items` |
| `ColorSchemeScope` | CSS vars de `color_scheme` id |
| `useThemeSettingsReader()` | Settings globais no subtree |
| `useThemeSetting(key)` | Um setting global (ex.: `@theme.color_primary`) |
| `usePage()` | Contexto da página aberta. O argumento é ignorado |
| `useStorefrontBlog` | Blog e artigo quando o contexto de página não basta |
| `useCaptureLead`, `getLeadTrackingContext` | Formulário de lead. O mesmo módulo está em `@corvex/theme-sdk` |
| `ProductCard`, `Link`, `Image` | Componentes SDK re-exportados |
| `formatPrice`, `getProductImage`, … | Helpers SDK re-exportados |

Preferir hooks direto de `@corvex/theme-sdk` quando não precisa do re-export runtime.

***

## PUBLIC\_EDITOR\_INTEGRATION (Builder)

### Componentes

| Import | Quando usar |
| - | - |
| `SectionChrome` | Envolver a section quando usa `isEditing` / `onSettingsChange` ou blocks |
| `InlineText` | Campo `text` editável no canvas. A prop é `propKey`, igual ao `id` do schema |
| `BlockInlineText` | Texto inline **dentro de um block** |
| `SectionBlockCanvas` | Wrapper de layout para `{children}` em sections com blocks (classe + estilo do track/grid) |
| `BlockCanvas` | Wrapper de layout para `{children}` **dentro de um bloco contêiner** (grupo). Irmão de `SectionBlockCanvas` |
| `useThemePortalTarget()` | Destino de `createPortal`. Não use `document.body` |

`SectionBlockCanvas` e `BlockCanvas` são `<div>` de layout — a plataforma garante que os blocks filhos participem do flex/grid do tema. Renderize `{children}` **uma vez** dentro do canvas correspondente. `BlockCanvasRoot` é INTERNAL.

Bloco contêiner ≠ grupo de layout (`layoutGroups`). Contrato: [Block Contract](https://docs-loja.usecorvex.com.br/reference/contracts/block.md#bloco-contêiner-grupo). Cookbook: [Colunas agrupadas](https://docs-loja.usecorvex.com.br/cookbook/grouped-columns.md).

### Hooks — qual usar?

| Cenário da section | Import recomendado | Retorno / efeito |
| - | - | - |
| Grid/lista/carrossel — **cada block é um card visual** (depoimentos, FAQ, slides) | `{children}` + `useEditorPreviewCanvas()` | Editor: **sempre** `{children}`; vitrine: fallback com `block_order` |
| Carrossel/grid que renderiza `{children}` | `useSectionBlockCount()` | `number` — quantidade real de blocks |
| Marquee/ticker — **não** renderiza `{children}` | `useSectionBlockMessages()` | `{ text, link? }[]` dos blocks |
| Carrossel montado só a partir de settings (ex.: vídeo-reel) — **sem** card block no DOM | `useSectionLiveBlocks()` | `{ liveItems, blocks, block_order }` — leitura ao vivo do molde sem montar `{children}` |
| **Grade de produtos** — mesmo molde de blocos em **cada** produto | `useSectionBlockTemplate()` + `RepeatedBlockCard` (+ seu `renderCatalogProductBlocks`) | Preview ao vivo no builder; vitrine: loop com `block_order`. Ver [Padrão C](#padrão-c--grade-de-produtos-card-repetido-por-bloco). Composição manual equivalente: `useSectionLiveBlocks()` + `SectionBlockCanvas` + espelho por produto |
| Faixa animada infinita | `useCorvexMarqueeLoop({ trackRef, measureRef, active, replayKey })` | `boolean` — loop pronto (`.is-ready`) |
| Inspecionar ativo no canvas | `useInspectMode()` | `boolean` |
| Iframe do builder vs preview/vitrine | `useEditorPreviewCanvas()` | `boolean` |
| URL/contexto de preview dinâmico | `useEditorPreviewState()` | estado de página do preview |

> [!NOTE]
>
> `useBuilderBlockEditLayout()` existe por compatibilidade e **sempre retorna `false`**. Não altere layout, autoplay ou carrossel com base nele — o tema é WYSIWYG.

***

## Padrão A — blocks renderizados com `{children}`

Slides, FAQ, **grid de depoimentos**, qualquer layout onde **cada block é um componente React** (`blocks/testimonial-card/block.jsx`, etc.).

> [!WARNING]
>
> **Blocks fantasma:** se no canvas do editor você montar cards com `blocks.map()` / `block_order` porque `{children}` veio vazio, esses cards **não pertencem ao editor**. A reordenação na árvore lateral pode funcionar, mas **arrastar no canvas não persiste** e seleção/inline edit quebram. No iframe do builder use **sempre** `{children}` — a plataforma gerencia blocks e drag-and-drop.
>
> O mesmo vale para **banners padrão no JSX** (`if (!children) return DEFAULT_SLIDES`). Isso não é Theme Default: some no primeiro block real e não é inspecionável. Looks iniciais = `templates/*.json`. [theme-defaults](https://docs-loja.usecorvex.com.br/guides/theme-defaults.md).

### Grid de depoimentos (canônico)

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useMemo } from 'react';
import {
  SectionBlockCanvas,
  SectionChrome,
  useEditorPreviewCanvas,
} from '@corvex/runtime';

export default function TestimonialsSection({
  children,
  blocks = {},
  block_order = [],
  settings = {},
}) {
  const inEditorCanvas = useEditorPreviewCanvas();

  const orderedBlocks = useMemo(() => {
    const order = block_order?.length ? block_order : Object.keys(blocks);
    return order
      .map((id) => ({ id, ...(blocks[id] || {}) }))
      .filter((entry) => entry.type);
  }, [blocks, block_order]);

  return (
    <SectionChrome label="Depoimentos" settings={settings}>
      <SectionBlockCanvas className="testimonials__grid">
        {inEditorCanvas
          ? children
          : orderedBlocks.map(({ id, settings: blockSettings = {} }) => (
              <article key={id} className="testimonials__card">
                {/* fallback vitrine/preview quando não há {children} */}
                <p>{blockSettings.quote}</p>
                <cite>{blockSettings.author}</cite>
              </article>
            ))}
      </SectionBlockCanvas>
    </SectionChrome>
  );
}
```

| Ambiente | O que renderizar |
| - | - |
| **Canvas do builder** (`useEditorPreviewCanvas()` → `true`) | **Sempre** `{children}` — única forma de drag-and-drop e persistência |
| **Preview / vitrine** | `{children}` se a plataforma montar blocks; senão fallback com `block_order` + `blocks` |

### Carrossel com slides (blocks)

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useMemo, useState } from 'react';
import {
  SectionBlockCanvas,
  SectionChrome,
  useSectionBlockCount,
} from '@corvex/runtime';

export default function SliderSection({ children, settings = {} }) {
  const blockCount = useSectionBlockCount();
  const slideCount = Math.max(blockCount, 1);
  const useCarousel = slideCount > 1;
  const [index, setIndex] = useState(0);

  const trackStyle = useMemo(
    () =>
      useCarousel
        ? { transform: `translateX(-${index * 100}%)` }
        : undefined,
    [useCarousel, index]
  );

  return (
    <SectionChrome label="Slider">
      <SectionBlockCanvas
        className="my-slider__track"
        style={trackStyle}
      >
        {children}
      </SectionBlockCanvas>
      {useCarousel && (
        <div className="my-slider__dots" role="tablist">
          {Array.from({ length: slideCount }).map((_, i) => (
            <button
              key={i}
              type="button"
              aria-selected={i === index}
              onClick={() => setIndex(i)}
            />
          ))}
        </div>
      )}
    </SectionChrome>
  );
}
```

**Boas práticas**

* **Editor canvas:** `{children}` sempre — **nunca** `blocks.map()` quando `useEditorPreviewCanvas()` é `true`.
* Contagem: `useSectionBlockCount()` — **não** `Children.count(children)`.
* Renderize `{children}` **uma única vez** — sem cópia oculta para “modo editor”.
* Classe de card/slide no **block**, não em wrapper manual em cima de `{children}`.
* Autoplay e gestos: implemente no tema; a plataforma não fornece carrossel global.

Cookbooks: [Slider](https://docs-loja.usecorvex.com.br/cookbook/slider.md) · [FAQ](https://docs-loja.usecorvex.com.br/cookbook/faq.md)

***

## Padrão B — blocks lidos **sem** `{children}` (marquee / faixa)

**Somente** quando a section **nunca** monta cada block como filho React — ex.: promo-bar que lê textos e desenha uma faixa animada, ou carrossel de vídeo onde o JSX monta `<video>` a partir de `settings` do block.

> [!WARNING]
>
> Se cada block tem `block.jsx` visível (depoimento, slide, FAQ item), isso é **Padrão A** — use `{children}` no editor. `useSectionLiveBlocks()` **não** substitui `{children}` nesses casos.

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { useMemo, useRef } from 'react';
import {
  SectionChrome,
  useCorvexMarqueeLoop,
  useSectionLiveBlocks,
} from '@corvex/runtime';

export default function VideoCarouselSection({ settings = {} }) {
  const { liveItems } = useSectionLiveBlocks();
  const items = useMemo(
    () =>
      liveItems.length
        ? liveItems
        : fallbackItemsFromSettings(settings),
    [liveItems, settings]
  );

  const trackRef = useRef(null);
  const measureRef = useRef(null);
  const replayKey = items.map((item) => item.id).join('|');

  const loopReady = useCorvexMarqueeLoop({
    trackRef,
    measureRef,
    active: items.length > 0,
    replayKey,
  });

  return (
    <SectionChrome label="Vídeos">
      <div
        ref={trackRef}
        data-corvex-marquee-track=""
        className={loopReady ? 'is-ready' : ''}
      >
        <div ref={measureRef} data-corvex-marquee-measure="" data-corvex-marquee-sequence="">
          {items.map((item) => (
            <article key={item.id} className="my-carousel__card">
              {/* render a partir de item.settings */}
            </article>
          ))}
        </div>
        <div data-corvex-marquee-sequence="" aria-hidden="true">
          {/* cópia para loop infinito */}
        </div>
      </div>
    </SectionChrome>
  );
}
```

***

## Padrão C — grade de produtos (card repetido por bloco)

Quando o lojista monta o **card** (imagem, título, preço…) com blocos e cada **produto da grade** deve repetir a mesma composição:

1. A section busca produtos (`useCorvexData` ou `defineSectionData`).
2. Por produto: `Provider` de contexto + função que itera `block_order` e renderiza o componente de cada `blocks[id].type`.
3. No builder: `RepeatedBlockCard` (`editorHost` no primeiro card + `renderMirror` nos demais) e `useSectionBlockTemplate(blocks, block_order)` para o molde ao vivo.
4. Blocks de catálogo **não** fazem fetch — leem o produto do contexto.
5. **No tema:** `@corvex/runtime` e `@corvex/theme-sdk`. Não importe o motor do editor.

Não confunda com [Product Card (snippet)](https://docs-loja.usecorvex.com.br/cookbook/product-card.md) nem com seções `product-list` que importam snippet fixo.

Cookbook completo: [Grade com blocos de catálogo](https://docs-loja.usecorvex.com.br/cookbook/catalog-product-grid.md).

### `useSectionBlockTemplate(blocks, block_order)`

Retorno: `{ blocks, block_order }` — no builder, settings e ordem ao vivo (proxy sobre o estado interno da section); na vitrine, os props serializados. Atalho para grades e qualquer loop que repete o molde de blocos. Equivalente de baixo nível: `useSectionLiveBlocks()` + merge com os props da section.

### `RepeatedBlockCard`

Props: `editorHost` (boolean), `className`, `children` (repasse da section), `renderMirror` (função que retorna o JSX espelhado). Encapsula o par **card âncora no builder** + **cards espelhados** em listas repetidas (ex.: grade de produtos). Se o layout do tema for atípico, monte o mesmo comportamento com `SectionBlockCanvas`, `{children}` e `useSectionBlockTemplate` — a plataforma continua responsável pelo espelho nos props.

***

### `useSectionLiveBlocks()`

Retorno:

| Campo | Tipo | Descrição |
| - | - | - |
| `liveItems` | `{ id, settings }[]` | Blocks da section na ordem do editor, settings mesclados |
| `blocks` | `object` | Mapa `type` + `settings` por id (no builder, espelhado da árvore de blocos quando possível) |
| `block_order` | `string[]` | Ordem dos IDs |

Use quando a section monta UI a partir de **settings de cada block** (vídeo, texto+link, **ou grade que repete blocks por produto**) e **não** repassa `{children}` na vitrine visível.

Na vitrine/publicado, leia `blocks` + `block_order` das props (ou defaults do template) — `liveItems` reflete o estado ao vivo **no editor**.

Cada entrada em `blocks` deve ter `type` estável (ex.: `catalog-product-title`). O `name` do `schema.json` do block é label no editor, não substitui `type` na serialização.

### `useSectionBlockMessages()`

Retorno: array estável de `{ text, link? }` extraído dos blocks — ideal para promo-bar / ticker com blocks só de texto.

### Marquee — atributos obrigatórios

| Atributo | Função |
| - | - |
| `data-corvex-marquee-track` | Trilho animado (recebe `.is-ready`) |
| `data-corvex-marquee-measure` | Sequência medida para largura |
| `data-corvex-marquee-sequence` | Cópias repetidas no trilho |

CSS do tema: `@keyframes` + variável `--marquee-duration`. Guia: [Carrossel de vídeos](https://docs-loja.usecorvex.com.br/guides/video-carousel.md).

***

## Blocks — adicionar, remover e reordenar

A plataforma oferece o painel **Itens** no inspetor lateral quando a section tem `sections/{id}/blocks.json`. O lojista:

* clica em **Adicionar** para criar um block (respeitando `max_blocks`);
* arrasta pelo ícone **≡** para reordenar;
* clica em um item para selecioná-lo no canvas;
* remove com o botão de lixeira.

**Responsabilidade do tema:** refletir a ordem na UI — **não** implemente drag-and-drop próprio no canvas. No canvas, com inspecionar ativo, a plataforma desenha a linha de soltura e persiste o movimento. A árvore lateral (**Itens** / seções) e o canvas devem produzir o **mesmo** `block_order` / ordem de sections.

> [!WARNING]
>
> **Sintoma clássico (ex.: grid de depoimentos):** reordenar na árvore lateral funciona, mas arrastar cards no canvas **não salva**. Causa: cards montados manualmente com `blocks`/`block_order` no editor em vez de `{children}` (blocks fantasma). Correção: [Padrão A — grid de depoimentos](#grid-de-depoimentos-canônico). Antes de culpar o editor, confirme que o canvas do builder renderiza `{children}` dentro de `SectionBlockCanvas`.

### Manifest da section

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "blocks": [{ "type": "faq-item" }],
  "max_blocks": 24
}
```

Registre cada `type` em `theme.json` → `blocks[]`. Ver [Blocks](https://docs-loja.usecorvex.com.br/sections/blocks.md).

### Ordem persistida

Cada instância na página guarda:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "blocks": {
    "b1": { "type": "faq-item", "settings": { "question": "Envio?" } },
    "b2": { "type": "faq-item", "settings": { "question": "Trocas?" } }
  },
  "block_order": ["b1", "b2"]
}
```

| Onde renderiza | Como respeitar a ordem |
| - | - |
| **Canvas do builder** | **Sempre** `{children}` dentro de `SectionBlockCanvas` — drag-and-drop e persistência |
| **Preview / vitrine** | `{children}` se existir; senão iterar `block_order` + `blocks[id].settings` |
| **Marquee/faixa (sem card block no DOM)** | `useSectionLiveBlocks()` ou `useSectionBlockMessages()` — [Padrão B](#padrão-b-—-blocks-lidos-sem-children-marquee-/-faixa) |

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Preview / vitrine — fallback quando {children} não está montado
const order = block_order?.length
  ? block_order
  : Object.keys(blocks || {});

const items = order.map((id) => ({
  id,
  settings: blocks?.[id]?.settings || {},
}));
```

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Padrão B apenas — marquee / faixa que NÃO usa {children}
import { useSectionLiveBlocks } from '@corvex/runtime';

const { liveItems } = useSectionLiveBlocks();
```

### Defaults no template

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "sections": {
    "faq": {
      "type": "faq",
      "settings": { "title": "Perguntas frequentes" },
      "blocks": {
        "b1": { "type": "faq-item", "settings": { "question": "Como comprar?" } }
      },
      "block_order": ["b1"]
    }
  }
}
```

Após reordenar no builder, **salve** o rascunho — a aba Preview lê o `block_order` persistido.

***

## Edição inline — duplo clique no canvas

Campos `text` / `textarea` podem ser editados **direto no canvas** com duplo clique, além do inspetor lateral.

### Pré-requisito no builder

1. Ative o modo **Inspecionar / Selecionar** na barra do editor.
2. Selecione a section ou o block desejado (opcional, mas recomendado).
3. **Duplo clique** no texto — entra em edição; **Esc** cancela; **Enter** confirma (linha única); clique fora (**blur**) salva.

Fora do builder (`/preview`, vitrine) os componentes renderizam texto estático — sem placeholder de edição.

### Settings da **section** — `InlineText`

Use `propKey` = `id` do field no `schema.json` (gravado nos props da section no editor).

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { SectionChrome, InlineText } from '@corvex/runtime';

export default function HeroSection(props) {
  const settings = props.settings ?? props;
  const title = settings.title ?? 'Título do hero';
  const subtitle = settings.subtitle ?? '';

  return (
    <SectionChrome label="Hero" settings={settings}>
      <InlineText
        propKey="title"
        tag="h1"
        className="hero__title"
        value={title}
        placeholder="Duplo clique para editar"
      />
      <InlineText
        propKey="subtitle"
        tag="p"
        className="hero__subtitle"
        value={subtitle}
        multiline
        placeholder="Subtítulo"
      />
    </SectionChrome>
  );
}
```

| Prop | Descrição |
| - | - |
| `propKey` | **Obrigatório** — mesmo `id` do field no `schema.json` |
| `tag` | Elemento HTML (`h1`, `p`, `span`, …) |
| `value` | Texto atual (leia de `settings` ou props flat) |
| `multiline` | `true` para `textarea` — Enter insere quebra em vez de fechar |
| `placeholder` | Texto quando vazio (só no builder com inspecionar) |
| `className` | Classes CSS do tema |

> [!NOTE]
>
> Leia settings dos **props flat** (`props.title`) ou de `props.settings` — a plataforma pode passar ambos conforme o ambiente. Normalize no topo da section como no exemplo.

### Settings do **block** — `BlockInlineText`

Use **dentro** de `blocks/{id}/block.jsx`. Grava em `settings[fieldKey]`.

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { BlockInlineText } from '@corvex/runtime';

export default function FaqItemBlock({ settings = {} }) {
  const question = settings.question ?? 'Pergunta';

  return (
    <div className="faq-item">
      <BlockInlineText
        fieldKey="question"
        tag="span"
        className="faq-item__question"
        value={question}
      />
      {/* answer: use inspetor (richtext) ou BlockInlineText multiline se for text puro */}
    </div>
  );
}
```

| Prop | Descrição |
| - | - |
| `fieldKey` | **Obrigatório** — `id` do field no `blocks/{id}/schema.json` |
| Demais | Igual a `InlineText` |

### Quando **não** usar inline

| Caso | Use |
| - | - |
| `select`, `color`, `image`, `product`, `video` | Inspetor lateral (`schema.json`) |
| `richtext` com HTML | Inspetor ou render `dangerouslySetInnerHTML` na vitrine |
| Texto que não deve editar no canvas | JSX estático + field só no inspetor |

Campos editáveis no inspetor **sempre** funcionam — `InlineText` / `BlockInlineText` são opcionais para UX de duplo clique.

***

## Padrão C — texto inline (resumo)

Ver seção [Edição inline — duplo clique](#edição-inline-—-duplo-clique-no-canvas) acima. Envolva a section com `SectionChrome` e declare os mesmos `id`s no `schema.json`.

## Checklist antes de publicar

1. **Canvas do builder** — section visível; blocks adicionáveis na sidebar.
2. **`/preview` em nova aba** — mesmo visual; sem classes exclusivas de “modo editor” forçadas no JSX.
3. **Vitrine** — conteúdo vem de `blocks`/`block_order` ou settings, não só de estado ao vivo do editor.
4. **`corvex validate .`** — schemas e manifest OK.
5. **`corvex build .`** — bundle compila sem erro.
6. **`corvex sync .`** — código sobe para a loja vinculada.
7. Hard refresh no builder após deploy de **nova API** do runtime no editor.

***

## Anti-padrões

| Evite | Faça |
| - | - |
| `blocks.map()` no canvas do editor quando `{children}` está vazio | `useEditorPreviewCanvas()` → `{children}` sempre no builder |
| Cards “fantasma” montados de `block_order` no editor | Padrão A — plataforma monta blocks via `{children}` |
| Pacote ou helper que esta página não lista | `@corvex/runtime` + `{children}` + `useEditorPreviewCanvas()` |
| `useSectionLiveBlocks()` em grid com `block.jsx` por card | Padrão A — `{children}` no editor |
| `Children.count(children)` em section com blocks | `useSectionBlockCount()` |
| Montar `{children}` duas vezes (visível + oculto) | Uma árvore; hooks ao vivo para dados extras |
| Branch de layout com `useBuilderBlockEditLayout()` | Mesmo layout em todos os ambientes |
| `SectionBlockCanvas` só no “modo inspecionar” | Wrapper consistente ou `{children}` direto no track |
| Ler blocks só de props no editor | `useSectionLiveBlocks()` ou `useSectionBlockMessages()` |
| Ordem dos blocks com `Object.keys(blocks)` | Iterar `block_order` na vitrine; hooks ao vivo no editor |
| Drag-and-drop de blocks no tema | Painel **Itens** do editor — tema só reflete a ordem |
| `InlineText` sem `propKey` / `BlockInlineText` sem `fieldKey` | IDs iguais aos fields do `schema.json` |
| Duplo clique não funciona | Ativar **Inspecionar** no builder; conferir `propKey`/`fieldKey` |
| `contentEditable` manual no block | Preferir `BlockInlineText` de `@corvex/runtime` |
| `setState` dentro de updater de `useState` | Sincronizar pai em `useEffect` |
| Importar APIs não listadas nesta página | Só PUBLIC\_\* documentadas |
| Republicar tema sem editor atualizado | Deploy do editor primeiro quando o erro citar export ausente em `@corvex/runtime` |

Sintomas comuns (banner vazio, carrossel com 1 slide, loop infinito de render): [Section Contract — blocks](https://docs-loja.usecorvex.com.br/reference/contracts/section.md) · cookbooks acima.

***

## INTERNAL (não usar em temas)

Sem garantia de compatibilidade — **não importe** estes símbolos no tema:

`GenericInspector`, `SectionInspector`, `BlockSettingsInspector`, `BlockCanvasRoot`, hooks internos de edição legados, `useEditorViewport`, …

Prefira arquitetura declarativa (React + CSS) documentada nos cookbooks.

***

## Referência rápida de imports

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
// Vitrine + preview
import {
  useCorvexCart,
  useStorefrontMenus,
  StorefrontNav,
  ColorSchemeScope,
  useThemeSettingsReader,
  useThemeSetting,
  ProductCard,
  Link,
  Image,
} from '@corvex/runtime';

// Editor + sections com blocks
import {
  SectionChrome,
  InlineText,
  BlockInlineText,
  SectionBlockCanvas,
  BlockCanvas,
  useSectionBlockCount,
  useSectionLiveBlocks,
  useSectionBlockMessages,
  useCorvexMarqueeLoop,
  useInspectMode,
  useEditorPreviewCanvas,
  useEditorPreviewState,
} from '@corvex/runtime';
```

Dados e loaders continuam em `@corvex/theme-sdk`:

```jsx theme={"theme":{"light":"github-light","dark":"github-dark"}}
import {
  usePage,
  defineSection,
  defineSectionData,
  useTranslation,
} from '@corvex/theme-sdk';
```

***

## Veja também

* [SDK overview](https://docs-loja.usecorvex.com.br/sdk/overview.md)
* [Section Contract](https://docs-loja.usecorvex.com.br/reference/contracts/section.md)
* [Block Contract](https://docs-loja.usecorvex.com.br/reference/contracts/block.md)
* [Cookbooks](https://docs-loja.usecorvex.com.br/cookbook/overview.md)
* [Carrossel de vídeos](https://docs-loja.usecorvex.com.br/guides/video-carousel.md)
* `AGENTS.md` na pasta da documentação — regras para agentes de código


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.