Skip to content
Skip to main contentWhere does your team stand on AI adoption?
CONTACT SALESSTART BUILDING

Preview Private Models

When you have private models in Builder.io, you can securely enable preview functionality using the builder.authToken property in the Gen1 SDK. This approach keeps your private API key secure on the server while allowing content editors to preview draft content in the Visual Editor.

The builder.authToken property authenticates your server-side requests to access private model content without exposing your private API key to client-side code. This is essential for maintaining security while providing a seamless editing experience.

Note: Setting builder.authToken is only needed if using the Gen 1 SDK. Gen 2 SDKs are stateless, and therefore do not require this additional step.

Prerequisites

Before you begin, ensure you have:

  1. A private model configured in Builder.
  2. A private API key generated in your Organization Settings.
  3. A Next.js project with the React Gen 1 SDK (@builder.io/react) installed.
  4. Server-side rendering setup using getStaticProps or similar.

Step 1: Configure your private model

If you haven't already created a private model, follow the instructions in Creating a Private Model to set up your model with the Public Readable toggle switched off.

Step 2: Set up server-side authentication

Configure your private API key on your server using builder.authToken. This property should only be set in server-side contexts like getStaticProps, API routes, or server components.

Add your private API key to your environment variables:

# .env.local BUILDER_PRIVATE_API_KEY=your_private_api_key_here

In your page component, set authToken during server-side data fetching:

// pages/[[...index]].tsx import type { GetStaticProps } from "next"; builder.init("your-public-api-key"); const modelName = "private-landing-pages"; export const getStaticProps: GetStaticProps = async (opts) => { let pathName = "/" + ((opts.params?.index as string[])?.join("/") || ""); // Set private key for server-side access only builder.authToken = process.env.BUILDER_PRIVATE_API_KEY; const page = await builder .get(modelName, { userAttributes: { urlPath: pathName } }) .promise(); return { props: { page: page || null }, revalidate: 5, }; };

Important: Never set builder.authToken in client-side code or expose your private API key in your front-end compiled code.

Step 3: Implement secure preview functionality

Use the useIsPreviewing() hook to detect when content is being previewed in the Visual Editor. This ensures your page renders correctly even when no published content exists:

export default function Page({ page }: { page: BuilderContent | null }) { const isPreview = useIsPreviewing(); // Show content if it exists or if in preview mode if (!page && !isPreview) { return <DefaultErrorPage statusCode={404} />; } return <BuilderComponent model={modelName} content={page || undefined} />; }

For static generation, configure your paths to include fallback handling:

export async function getStaticPaths() { return { paths: ["/private-page-example"], // Add your known private page paths fallback: "blocking", // Enable fallback for new pages }; };

Step 4: Handle client-side rendering

The BuilderComponent receives the pre-fetched content from your server-side function. Since the private API key was used server-side, the content is safely passed to the client without exposing sensitive credentials:

export default function Page({ page }: { page: BuilderContent | null }) { const isPreview = useIsPreviewing(); if (!page && !isPreview) { return <DefaultErrorPage statusCode={404} />; } return ( <> <BuilderComponent model={modelName} content={page || undefined} /> </> ); }

Complete example

Here's a full implementation for a private model page:

// pages/[[...index]].tsx import { BuilderComponent, builder, useIsPreviewing } from "@builder.io/react"; import type { BuilderContent } from "@builder.io/sdk"; import type { GetStaticProps } from "next"; import DefaultErrorPage from "next/error"; import React from "react"; builder.init("db60bf3db7fa4db7be81ef05b72bd720"); const modelName = "private-landing-pages"; export const getStaticProps: GetStaticProps = async (opts) => { let pathName = "/" + ((opts.params?.index as string[])?.join("/") || ""); // Set private key for server-side access only builder.authToken = process.env.BUILDER_PRIVATE_API_KEY; const page = await builder .get(modelName, { userAttributes: { urlPath: pathName } }) .promise(); return { props: { page: page || null }, revalidate: 5, }; }; export async function getStaticPaths() { return { paths: ["/private-landing-page-example"], fallback: "blocking", }; } export default function Page({ page }: { page: BuilderContent | null }) { const isPreview = useIsPreviewing(); if (!page && !isPreview) { return <DefaultErrorPage statusCode={404} />; } return <BuilderComponent model={modelName} content={page || undefined} />; }

What's next

Now that you have secure private model previewing set up, you can:

Was this article helpful?