Skip to Content
ConceptsOverview

P1 Concepts, Mapped to WordPress & Drupal

P1’s own docs describe it as “decoupled and API-first, not headless and even less monolithic.” In practice: a Next.js frontend (the P1 Client) talks to a hosted backend (the Collaborative Content Repository, or CCR) that stores your content as structured documents, with Cloudflare (Pantheon Edge) caching and routing in front of both.

None of that maps perfectly onto WordPress or Drupal: P1 has no themes directory, no wp_posts table, no .info.yml files. But the concepts underneath rhyme closely enough that naming the closest analog is the fastest way to get oriented, so long as you remember it’s an analogy, not an equivalence.

Quick comparison

P1WordPressDrupal
Site (one P1 dashboard entry)A WP installA Drupal site
CCR document (a page)A Post / PageA Node
Template (_registry/templates/*)Custom Post Type + ACF Field GroupContent Type + Field UI
Puck componentGutenberg blockParagraph type / Block plugin
Puck field (on a component)ACF fieldDrupal field (Field UI)
Puck visual editor (/p1)Block editorLayout Builder
Site Structure (dashboard tab)Pages screen + menu editorContent list + Menu UI
Branch / Workstream(closest: staging site + merge, but a real branch/merge, not a plugin)Content moderation workflow
Pantheon EdgeCloudflare sitting in front of WP (via your host or the Cloudflare plugin)Drupal’s internal page cache + Cloudflare

If you’re coming from one platform specifically, the quick table above is a starting point, not the full picture: Concepts for WordPress Developers and Concepts for Drupal Developers go deeper: a fuller terminology mapping, the concrete workflow differences (not just the closest analog), and the platform-specific habits worth unlearning. And since Puck and Gutenberg are both React-based, block/component-oriented visual editors (the closest pairing in this whole comparison), Puck vs. Gutenberg goes deep on just that one comparison specifically.

Sites, branches, and workstreams

A Site in the P1 dashboard is the rough equivalent of one WordPress or Drupal install: one content backend, paired with one Next.js codebase.

Content lives on a branch: main is the default/live one, and it’s what your local .env.local reads from unless you override NEXT_PUBLIC_CSS_BRANCH_ID. The dashboard’s workstream is a branch by another name. Editing has its own draft-autosave-vs-publish distinction independent of branches; see Workflows for the full mechanics of both, confirmed directly from the SDK source: how autosave and Publish differ, how a workstream gets merged into Live, checkpoints, and template migrations.

We’ve observed a real gap between a page existing in the dashboard and that page actually rendering through the public/local read path. Workflows explains the publish mechanism that’s almost certainly behind it; see Known Issues for the specific incident before you assume something’s broken.

Documents, pages, and templates

Every page, template, and redirect is stored as a document in the CCR: the closest single concept to a WordPress Post/Page or a Drupal Node. A document lives at a path (/about, /events/us/go-live), and the URL-to-document relationship is one-to-one for static pages.

A Template, stored at _registry/templates/{name}, is the closest thing to a WordPress Custom Post Type combined with an ACF Field Group, or a Drupal Content Type with its fields: it defines a Content Type (name, label, description) plus a component tree that pages created from it inherit. Templates distinguish:

  • Pinned components: locked into place by whoever built the template; a content editor can’t move, remove, or restructure them. Think of these like a Drupal “required” field, or an ACF field group locked to specific block positions.
  • Editorial components: everything else; freely configurable within the guardrails the template sets.

Dynamic routes (/company/leadership/:name) are P1’s answer to what WordPress does with a CPT archive/single template, or what Drupal does with a Views page + node template: one template renders many URLs, each resolved against a data record at request time, rather than one document per URL.

Changing a template’s structure after real pages already exist against it (the thing that’s usually painful in WordPress or Drupal) has dedicated, self-serve tooling in P1: dry-run previews, async migration jobs, and rollback. See Templates.

Components: Puck’s answer to blocks

Puck is P1’s visual, drag-and-drop editor, closest to the WordPress block editor (Gutenberg) or Drupal’s Layout Builder. What Gutenberg calls a “block” and Drupal calls a “Paragraph type,” Puck calls a component.

Concretely, a component is a plain JS/TS object with four parts:

export const quoteBlock = { label: "Quote", // shown in the component picker fields: { // the editor sidebar's inputs quote: { type: "textarea", label: "Quote" }, attribution: { type: "text", label: "Attribution" }, }, defaultProps: { // what a fresh instance starts with quote: "A short quotation goes here.", attribution: "", }, render: ({ quote, attribution }) => ( // the actual React output <blockquote> <p>{quote}</p> {attribution ? <footer>— {attribution}</footer> : null} </blockquote> ), };

Components live in components/puck/*.tsx and get registered (plus assigned to a sidebar category) in puck.config.tsx at the project root. There’s no separate “block registration” API call and no PHP-side register_block_type equivalent: the object above is the registration; importing it into puck.config.tsx’s components map is what makes it appear in the editor.

See Fields Reference for the full list of field types available inside fields, and Components Reference for what ships out of the box. Puck is a third-party library P1 builds its editor on top of; its own docs on Component Configuration  cover the same object shape in more depth, independent of anything P1-specific.

Naming trap: “CSS” doesn’t mean stylesheets here

Across P1’s SDK and env vars, CSS stands for Content and Site Services (the backend API), not Cascading Style Sheets. CSS_API_KEY, NEXT_PUBLIC_CSS_SITE_ID, @pantheon-systems/css-client are all this. It reads oddly the first few times; worth knowing up front so you don’t go looking for a stylesheet config.

Last updated on