Behio Storefront SDK
Catalog & Products

Content pages

Terms, privacy, about us and other merchant pages as ready, sanitised HTML with downloadable attachments

Content pages are the texts a merchant (or an AI agent) writes in Behio: terms and conditions, privacy policy, returns, about us, contact. Each page has a slug, a title, SEO fields, the body and optional downloadable attachments (price lists, forms, PDFs). They work with both e-shop keys and website keys.

List pages

const { data } = await client.pages.list('cs');
// data.pages: [{ slug, title, isActive, updatedAt }]

Use the list for the footer navigation and the sitemap (updatedAt is epoch ms for lastmod). Only published pages are returned.

One page

import { RichText } from '@behio/storefront-sdk/react';

const { data: page, error } = await client.pages.get('obchodni-podminky', 'cs');

if (error?.status === 404 || !page) {
  // unknown or unpublished page: render your 404
}

<h1>{page.title}</h1>
<RichText html={page.contentHtml} as="article" />

contentHtml (SDK 2.20.0) is always a string with ready, sanitised HTML, empty when the page has no body. You never have to know how the page was stored:

  • pages written in the admin editor or by an AI agent are HTML,
  • older pages written in markdown are converted on the server,
  • headings start at <h2>, because your page renders the single <h1> from title (a leading markdown heading that repeats the title is dropped),
  • scripts, event handlers, javascript: links and unsafe inline styles are removed before the response leaves the API.

Render it as is. RichText wraps it in an element with the class behio-rich-text, so style headings, lists, tables, images and the story blocks (.bh-figure, .bh-callout, .bh-button and the other bh-* classes) under that one class.

content is deprecated. It is the body as a string: sanitised HTML, or markdown for older pages written in markdown. It stays for storefronts built before 2.20.0. New code reads contentHtml, which is always ready HTML.

In a Next.js server component you can skip the client component and render the string directly; the HTML is already sanitised by the API:

<article className="behio-rich-text" dangerouslySetInnerHTML={{ __html: page.contentHtml }} />

Attachments

{page.attachments.length > 0 && (
  <ul>
    {page.attachments.map((file) => (
      <li key={file.url}>
        <a href={file.url} download>
          {file.name}
        </a>
        {file.description && <p>{file.description}</p>}
        <small>{Math.ceil(file.fileSize / 1024)} kB</small>
      </li>
    ))}
  </ul>
)}

Each attachment is { name, description, url, mimeType, fileSize }. The field is url (not fileUrl); Behio hosts the file.

SEO

seoTitle and seoDescription fall back to title when empty; ogTitle, ogDescription and ogImage are for social previews.

React hooks

import { usePages, usePage, RichText } from '@behio/storefront-sdk/react';

const { data: pages } = usePages('cs');
const { data: page, isLoading } = usePage(slug, 'cs');

if (page) return <RichText html={page.contentHtml} as="article" />;

RichText

import { RichText } from '@behio/storefront-sdk/react';

<RichText html={product.longDescription} />
<RichText html={post.content.html} as="article" className="prose" />
PropTypeDefault
htmlstring | null | undefinedRenders nothing when empty
classNamestringAdded next to behio-rich-text
as"div" | "article" | "section""div"Wrapper element

Use it only for fields the Behio API sanitises: page.contentHtml, a blog post's content.html and product shortDescription / longDescription. Never pass HTML from a visitor, a query string or another service.

On this page