8/21 demo: Building component libraries from Figma with AI

Announcing Visual Copilot - Figma to production in half the time

Builder logo
builder.io
Contact sales

8/21 demo: Building component libraries from Figma with AI

Announcing Visual Copilot - Figma to production in half the time

Builder logo
builder.io

Blog

Home

Resources

Blog

Forum

Github

Login

Signup

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

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.

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.

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.

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.

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
  };
};

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}
      />
    </>
  );
}

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} />;
}

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

Was this article helpful?

Product

Visual CMS

Theme Studio for Shopify

Sign up

Login

Featured Integrations

React

Angular

Next.js

Gatsby

Get In Touch

Chat With Us

Twitter

Linkedin

Careers

© 2020 Builder.io, Inc.

Security

Privacy Policy

Terms of Service

Get the latest from Builder.io

By submitting, you agree to our Privacy Policy

  • Fusion

  • Publish

  • Product Updates

  • Figma to Code Guide

  • Headless CMS Guide

  • Headless Commerce Guide

  • Composable DXP Guide

Security

Privacy Policy

SaaS Terms

Compliance

Cookie Preferences

Gartner Cool Vendor 2024