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-keyAnd 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=webThis 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.