> [Agent navigation index](/llms.txt)

# Contentful Live Preview

Give editors a protected, standalone preview for adapter-backed entries, with inspector attributes and live updates from Contentful's official SDK.

## Enable the preview entry

Enable the generated browser integration:

```ts
// vite.config.ts
import { defineBrixConfig } from "brix/vite";

export default defineBrixConfig({ contentfulPreview: true });

```

Configure credentials only on the server:

```ts
export const brixServer = defineBrixServer(brix, {
  env,
  contentfulPreview: (c) => ({
    accessToken: c.env.CONTENTFUL_PREVIEW_TOKEN,
    secret: c.env.CONTENTFUL_PREVIEW_SECRET,
    spaceId: c.env.CONTENTFUL_SPACE_ID,
    targetOrigin: "https://app.contentful.com",
  }),
});

```

Use static options for one space or a callback for request-specific tenants. The callback runs only on the preview route. `environment` defaults from the URL. Set `host` only for a trusted Preview API endpoint; custom token hosts require the same explicit trusted-host opt-in as the Delivery client. `targetOrigin` accepts one HTTPS origin or an array when editors use another Contentful host.

## Configure Contentful preview URLs

Configure each supported content type with its literal content type ID:

```text
https://example.com/_/contentful/preview/{locale}/{env_id}/card/{entry.sys.id}?secret=<CONTENTFUL_PREVIEW_SECRET>

```

Contentful replaces `{locale}`, `{env_id}`, and `{entry.sys.id}`. Replace `card` yourself for each model. The route verifies the secret and adapter support before fetching the entry through the Preview API. Responses use `no-store` and `no-referrer`, and only the preview route relaxes framing for configured Contentful origins.

Never put the Preview API token in the URL, browser props, or adapter fallback data. The URL contains only the separate preview secret and should still be treated as sensitive.

## Make adapters preview-ready

Use `preview.getProps(fieldName)` to add inspector attributes to the element that displays a field. Normal production rendering has no preview context, so no inspector attributes or controls are emitted.

Adapters with required extra props or loader data provide deterministic standalone fallbacks:

```tsx
import { propsOf } from "brix/contentful/rendering";

export const CardListAdapter = createAdapter({
  contentType: "cardList",
  props: propsOf<{ appearance: "light" | "dark" }>(),
  load: async (entry, c, signal) => loadCards(entry, c, signal),
  preview: {
    props: { appearance: "light" },
    data: { cards: [] },
    layout: "padded",
  },
  component: ({ entry, loaded, preview, props }) => (
    <CardList
      heading={entry.fields.heading}
      headingAttributes={preview?.getProps("heading")}
      appearance={props.appearance}
      cards={loaded.status === "ok" ? loaded.data.cards : []}
    />
  ),
});

```

The standalone preview uses fallback data rather than server loader results. Keep it nonsecret and deterministic. The generated integration subscribes to untransformed entry updates, applies inspector mode, and can render adapter-defined select controls.
