← Back to all how-tos

Page Types, Templates and Custom Fields

Add custom fields

Add page-level custom fields to a page type and access their values inside bricks with usePageValues.

Estimated time: 6 minRaw Markdown

In this how-to, you'll learn how to add custom fields to a page type in React Bricks.

Custom fields are edited like sidebar controls, but they live at page level rather than inside a single brick.

Why custom fields are useful

Bricks are great for visual content, but sometimes a page also needs structured values that are not tied to one specific brick.

For example, a product page may need:

  • a product SKU
  • a product ID for external APIs
  • a price
  • a short subtitle

These values belong to the page as a whole, not to one individual block.

That is where custom fields help.

Custom fields are page-level sidebar controls

Custom fields are configured on the page type, not on a brick schema.

Conceptually, they work like brick sideEditProps, but at page level.

That means:

  • editors edit them from the "page" UI tab
  • their values belong to the page
  • any brick on that page can read and render them

Docs reference: Custom Fields

Add customFields to a page type

Let's imagine a product page type.

We can add customFields like this:

{
  name: 'product',
  pluralName: 'products',
  defaultStatus: types.PageStatus.Published,
  customFields: [
    {
      name: 'productId',
      label: 'Product ID',
      type: types.SideEditPropType.Text,
    },
    {
      name: 'price',
      label: 'Price',
      type: types.SideEditPropType.Number,
    },
    {
      name: 'featured',
      label: 'Featured',
      type: types.SideEditPropType.Boolean,
    },
  ],
}

This works very much like sideEditProps on a brick.

Each field has:

  • name: the key used to store the value
  • label: the label shown to editors
  • type: the kind of control to render

Use custom field values inside a brick

To read page-level values inside a brick, use the usePageValues hook.

Docs reference: usePageValues

Here is a simple example:

const [page] = usePageValues()

The returned page object contains page-level data, including:

page.customValues

So you can read custom fields like this:

page.customValues.productId
page.customValues.price
page.customValues.featured

Example brick using usePageValues

Here is a simple example of a brick that reads a custom field:

import { Text, types, usePageValues } from 'react-bricks/frontend'
 
interface ProductHeroProps {
  title: types.TextValue
}
 
const ProductHero: types.Brick<ProductHeroProps> = ({ title }) => {
  const [page] = usePageValues()
 
  return (
    <div>
      <Text
        propName="title"
        value={title}
        placeholder="Product title..."
        renderBlock={({ children }) => <h1>{children}</h1>}
      />
 
      {page.customValues?.productId ? (
        <p className="text-sm text-slate-500">
          Product ID: {page.customValues.productId}
        </p>
      ) : null}
    </div>
  )
}

In this example, the brick displays the page-level productId custom field below the title.

Why usePageValues is powerful

Because the values live on the page, multiple bricks can read the same custom field.

For example:

  • one brick may show the subtitle
  • another brick may use the product ID to fetch external data
  • another brick may render a badge if featured is true

So custom fields are a good way to combine structured page data with visual bricks.

Bind visual components to custom fields

Besides reading custom fields with usePageValues, you can also bind visual components directly to page-level custom fields.

Docs reference: Text: bind to meta data or custom fields

Instead of using propName, use customFieldName.

For example, a Text component can be bound directly to a page custom field:

import { Text, types } from 'react-bricks/frontend'
 
interface ProductHeroProps {
  subtitle: types.TextValue
}
 
const ProductHero: types.Brick<ProductHeroProps> = ({ subtitle }) => {
  return (
    <Text
      value={subtitle}
      customFieldName="subtitle"
      placeholder="Product subtitle..."
      renderBlock={({ children }) => <p>{children}</p>}
    />
  )
}

And an Image component can be bound in the same way:

import { Image, types } from 'react-bricks/frontend'
 
interface ProductHeroImageProps {
  coverImage: types.IImageSource
}
 
const ProductHeroImage: types.Brick<ProductHeroImageProps> = ({
  coverImage,
}) => {
  return (
    <Image
      source={coverImage}
      alt="Product image"
      customFieldName="coverImage"
      aspectRatio={1.91}
      maxWidth={1200}
    />
  )
}

This creates a two-way binding between the visual component and the custom field configured on the page type.

So editors can manage page-level structured values, while still editing some of them visually in the content.

A note about headlessView

If a page type does not use frontend visual editing, but only structured data in custom fields, you can set:

headlessView: true

on the page type.

In that case, the custom field controls are not shown in the sidebar.

Instead, they are shown directly in the page, more like a traditional headless CMS editing experience.

This is useful for page types that are mostly data-driven rather than visually composed with bricks.