A field in Builder is a piece of data on a model. For example, the built-in Page model comes with two fields, a Title and a Description. These two fields help define what a Page is. Any time you make or edit any kind of model in Builder, you have the option of editing fields or adding custom fields.
Custom fields are fields that you add to a model. You can add custom fields to models you create or to an existing model, such as the built-in Page model. All kinds of Builder models accept custom fields, so you can add the fields you need to Page models, Section models, and Data models.
Examples of custom fields include data such as title, URL, name, timestamp, or any piece of data you want to define on a model. You define and specify aspects of your custom fields such as:
Type: There are many types available in Builder. Refer to Custom field types for more detail.
Localization: Translate fields according to region settings.
Default value: Pre-populate the custom fields you create.
Helper text: Give your users a helpful hint about what to enter into the field.
Required: Make a field required or optional.
Enum: Give users a predefined list of options.
Hidden: Make a given field hidden when editing content.
The following video shows where to find the Fields menu on a Data model with several different types of custom fields.
Configure any other settings for the field and add additional fields as needed.
Scroll to the top and click Save.
The following video shows adding a custom field called artistsName and reviewDate to a model.
For Pages and Sections, the custom fields you create display in the content entry on the Options tab.
For Data, the custom fields you create on the Data model are available in the Data entry.
By default, Data content entries appear as a form, but it is possible to preview them in a particular format. For more details, visit Live previewing Data models.
When you have custom fields on your model you can add specific values to the content and use those values however you want in your code. This example queries the Builder API to get the SEO image and a Canonical URL fields.
To interactively explore the data that is sent from the Builder API, check out the Builder API Explorer where you can query the Builder API using your actual data.
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
import { BuilderComponent, builder } from '@builder.io/react'
// Initialize once with your public API key (often done app-wide, not per-page)
builder.init('YOUR_PUBLIC_API_KEY')
export const getStaticProps = async () => {
// Fetch the page and resolve it with .promise()
const page = await builder
.get('page', { userAttributes: { urlPath: '/' } })
.promise()
return { props: { page: page || null } }
}
export default function Page({ page }) {
return (
<MyLayout seoImage={page?.data?.seoImage} canonicalUrl={page?.data?.canonicalUrl}>
{/* Your layout component that you pass the custom fields into */}
<MyLayoutComponent
showNavigation={page?.data?.showNavigation}
layoutWidth={page?.data?.layoutWidth}
>
{/* Render the rest of the Builder page content */}
<BuilderComponent model="page" content={page} />
</MyLayoutComponent>
</MyLayout>
)
}
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
<!-- Page.vue -->
<script setup>
import { Content, fetchOneEntry, isPreviewing } from '@builder.io/sdk-vue'
import { ref, onMounted } from 'vue'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
const page = ref(null)
onMounted(async () => {
page.value = await fetchOneEntry({
model: MODEL,
apiKey: BUILDER_PUBLIC_API_KEY,
userAttributes: { urlPath: window.location.pathname || '/' },
})
})
</script>
<template>
<MyLayout
v-if="page || isPreviewing()"
:seo-image="page?.data?.seoImage"
:canonical-url="page?.data?.canonicalUrl"
>
<!-- Your layout component that you pass the custom fields into -->
<MyLayoutComponent
:show-navigation="page?.data?.showNavigation"
:layout-width="page?.data?.layoutWidth"
>
<!-- Render the rest of the Builder page content -->
<Content :content="page" :model="MODEL" :api-key="BUILDER_PUBLIC_API_KEY" />
</MyLayoutComponent>
</MyLayout>
<div v-else>Content Not Found</div>
</template>
<!-- pages/[...slug].vue -->
<script setup>
import { Content, fetchOneEntry, isPreviewing } from '@builder.io/sdk-vue'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
const route = useRoute()
// Runs on the server during SSR, so custom fields like seoImage and
// canonicalUrl are resolved before the HTML is sent to the browser.
const { data: page } = await useAsyncData('builderPage', () =>
fetchOneEntry({
model: MODEL,
apiKey: BUILDER_PUBLIC_API_KEY,
userAttributes: { urlPath: route.path },
})
)
</script>
<template>
<MyLayout
v-if="page || isPreviewing()"
:seo-image="page?.data?.seoImage"
:canonical-url="page?.data?.canonicalUrl"
>
<MyLayoutComponent
:show-navigation="page?.data?.showNavigation"
:layout-width="page?.data?.layoutWidth"
>
<Content :content="page" :model="MODEL" :api-key="BUILDER_PUBLIC_API_KEY" />
</MyLayoutComponent>
</MyLayout>
<div v-else>Content Not Found</div>
</template>
import { Content } from '@builder.io/sdk-react'
const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'
const MODEL = 'page'
// `content` is what is returned from Builder.
export function BuilderPage({ content }) {
return (
<MyLayout seoImage={content?.data?.seoImage} canonicalUrl={content?.data?.canonicalUrl}>
<MyLayoutComponent
showNavigation={content?.data?.showNavigation}
layoutWidth={content?.data?.layoutWidth}
>
<Content content={content} model={MODEL} apiKey={BUILDER_PUBLIC_API_KEY} />
</MyLayoutComponent>
</MyLayout>
)
}
<builder-component
model="page"
(load)="contentLoaded($event)"
>
<!-- Default content inside the tag shows while the builder content is fetching -->
<div class="spinner"></div>
</builder-component>
The example below shows how to fetch a page from the Builder API on the client-side and handle the SEO image and canonical URL returned in the response.
The next example demonstrates how to handle a request to a /page/** route on the server-side using Express.js. It fetches the corresponding page data from the Builder API and renders the HTML, SEO image, and canonical URL in the response.
You can also filter content by using queries with your custom field values. This technique is useful if you want to retrieve content that only has a certain custom attribute. For example, you could filter for only entries that have a certain Canonical URL. For more information on how to use queries on your API calls, refer to Content API and the HTML API or in the options object of any JS SDK.
The following table describes each Type in Builder along with an image of how each Type renders in the Builder UI.
This section covers the built-in types for models, but you can also make your own with plugins. For more information, see Make your own plugins overview.
The Rick text/HTML Type provides a rich text interface with styling options and a toggle to write directly in HTML. Click the code icon, <>, at the upper right to toggle the HTML editor.
Use the Timestamp Type to accept a date from the user. When the user clicks on the input, a date picker opens with a time picker. Though the Date and Timestamp Types appear similar, prefer Timestamp querying.
Use the Reference type when you have Data entries that users choose from. For example, you could have a Blog Author custom field and when you click the Choose Entry button, all Blog Author Data entries display.