Skip to the page

You set the rules.

The editor renders your own React components, so what people build is what ships. Marketers and agents build on your components, and nothing goes live until it passes the checks.

Your components define what everyone else can build

Marketers, developers and AI agents work in the same governed environment, on the same components, with the same guardrails. You write the components and the rules. Everyone else builds inside them.

Agents create and execute work against your standards, not around them. Nothing goes live until it’s ready for primetime. Content publishes without a deploy. Code changes still go through your normal review.

A block is a component and its fields

Describe the fields an editor can change, give the block defaults, and point it at your component. Add ai.instructions to a field and agents get the same brief an editor would.

The block’s name is its type in every document. Ship the component before content uses it.

components/callout.block.tsx
import type { ComponentConfig } from "@puckeditor/core";
import { CalloutRender, type CalloutProps } from "./callout";

export const CalloutBlock: ComponentConfig<CalloutProps> = {
  fields: {
    variant: {
      type: "select",
      options: [
        { label: "Note", value: "note" },
        { label: "Tip", value: "tip" },
      ],
    },
    title: {
      type: "text",
      contentEditable: true,
      ai: { instructions: "Short label. 2–4 words." },
    },
    body: {
      type: "text",
      contentEditable: true,
      ai: { instructions: "1–2 sentences of plain prose." },
    },
  },
  defaultProps: { variant: "tip", title: "Try this", body: "" },
  render: CalloutRender,
};

One route renders every page

Content is a P1 document per page, and its path is the URL. A single catch-all route reads the document, renders your blocks and maps the root props to metadata.

Keep it static: no searchParams, cookies() or headers() in the public route. Any one of them makes the whole site dynamic.

app/(site)/[...puckPath]/page.tsx
import { createPublishedPage } from "@pantheon-systems/p1-next-sdk/server";

const published = createPublishedPage({
  Client,
  Unavailable: ContentUnavailable,
  Fallback: ContentUnavailable,
});

// A backstop. Publishing revalidates the route.
export const revalidate = 300;

export const generateStaticParams = published.generateStaticParams;
export const generateMetadata = published.generateMetadata;
export default published.Page;

Install a block, then make it yours

The P1 code registry installs blocks as source files in your repo: React and plain CSS, no Tailwind. The files are yours to edit.

Add the @p1 registry to your components.json, then review an upstream update with --diff before you take it.

Terminal
# Install a block from the P1 code registry
npx shadcn@latest add @p1/callout

# Review an upstream update before taking it
npx shadcn@latest add @p1/callout --diff

The code stays yours

  1. Components live in code

    The editor renders your registered React components, so the canvas is production. There is no admin screen where the schema lives and no second copy of the design to keep in step.

  2. The registry syncs from CI

    Your repo syncs the component registry to P1 on push. Code is the source of truth.

  3. Typed fields and annotations

    Fields define what an editor can change. Annotations tell agents how to fill them.

  4. Pre-publish checks

    Contrast, palette distance, alt text and sanitized rich text run before anything publishes.

  5. Static render, revalidated on publish

    One catch-all route renders any published document. Publish writes to main and revalidates the route, so there is no deploy.

What developers ask

Which framework does P1 work with?

The P1 front end described here is Next.js (App Router) with React, using the P1 SDKs. Ask the P1 team about other stacks.

Where does content live?

In P1, as one document per page. The document’s path is the URL, and its content is root props plus an ordered list of blocks, each with a type and props. Code lives in your repo.

Does publishing need a deploy?

No. Publishing writes the document to main and revalidates the route. Code changes still deploy through your own pipeline.

What happens if content names a block I haven’t registered?

A block type has to match a registered component name exactly. The editor drops a type it doesn’t know, so register and ship the component before content uses it.

What can an agent touch?

Agents work over MCP on a content branch, not on your code. They build with your registered blocks, fix what the pre-publish checks catch and open a merge request. A person executes it.

Do I have to start from the registry?

No. Register your own components, or install blocks from the P1 code registry and edit them. Either way the code is in your repo.

Go ahead. Break it.

Join the waitlist for first access to the P1 beta.

Join the P1 waitlist

Be first in when the beta opens.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.