Skip to Content
API Keys & Secrets

API Keys & Secrets

Where third-party credentials (Google Maps, Salesforce, Postmark, Cloudflare Turnstile, a future GTM container ID) actually live. It works like Vercel, not like a CMS. Confirmed from this project’s own .env.example, Pantheon’s own docs, and the installed SDK, not assumed from how WordPress plugins usually do it.

Confirmed: secrets are Next.js environment variables, set at the hosting layer

Every credential this documentation has covered so far (Salesforce org credentials, Turnstile’s secret key, OneTrust’s domain-script ID, the future Postmark API key) is described the same way: “server env vars,” never a value stored in Puck/CCR document content. That’s not a convention we invented; it’s confirmed directly from this project’s own .env.example:

# --- P1 backend --- NEXT_PUBLIC_CSS_SITE_ID=site-123 CSS_API_KEY=your-api-key

And from Pantheon’s own documented mechanism for setting secrets on a deployed environment (.env.example’s own comment, quoting the real command):

terminus secret:site:set <site>.live P1_SITE_URL "https://www.yoursite.com" \ --type=env --scope=web

This is Pantheon’s native per-environment secrets mechanism: set once per environment (Dev/Test/Live/Multidev each need their own value; see Deployment & Environments), read at runtime via process.env in server-side code (API routes, Server Components). Third-party keys (Google Maps, Salesforce, Postmark, Turnstile) follow the exact same path: set as an environment variable on the Pantheon-hosted Next.js environment (via Terminus, and presumably also a dashboard.pantheon.io UI equivalent; see “Open questions” below), never through content.pantheon.io.

This is the Vercel model, not the WordPress model. There’s no “Settings → API Keys” screen inside the P1 content editor, and no plugin-style options table storing credentials as editable content. If you’re coming from WordPress (where a plugin often stores its API key in wp_options, editable from wp-admin), don’t look for the equivalent inside P1’s dashboard: it isn’t there, deliberately.

Confirmed: content.pantheon.io has no secrets concept

Grepped @pantheon-systems/css-client, the SDK client for the P1 content backend (what content.pantheon.io talks to), for secret, credential, and env. Zero matches. The content dashboard manages Sites, branches, documents, templates, checkpoints; it has no field, endpoint, or concept for storing a third-party API key. That confirms the split is deliberate, not an oversight: content.pantheon.io is for content; secrets live on the Next.js hosting environment, a structurally separate system (see Deployment & Environments for how those two systems relate).

What Puck config is for (and isn’t)

Every “config shape” documented across this site so far (AgeGateConfig, SalesforceFormsConfig, MediaPluginOptions) is behavioral configuration passed as code, not something an editor fills in through the Puck canvas. A component like

<OneTrustConsent domainScriptId={process.env.NEXT_PUBLIC_ONETRUST_DOMAIN_ID!} />

reads the actual secret from process.env server-side (or a NEXT_PUBLIC_ var when the value is genuinely safe to expose client-side, like a public site ID) and passes it down as a prop. Never put a real secret in a Puck field. Puck field values are CCR document content, readable by any authenticated editor and visible in the editor’s own “View page content (JSON)” panel (see Known Issues for that panel’s existence). That’s the wrong storage layer for anything that shouldn’t be broadly readable. A NEXT_PUBLIC_* var is the closest thing to “safe to expose,” and even that’s for genuinely public identifiers (a site ID, a Turnstile site key), never a secret half of a keypair.

Open questions for this page now live on Outstanding Questions, tracked centrally across all pages rather than repeated per page.

Last updated on