Deployment & Environments
How a P1 site’s Next.js code actually gets from a local branch to a live domain. Confirmed directly from Pantheon’s own documentation (Test and Live Environments for Next.js , Configuring CORS for Your P1 Site ), not assumed from how WordPress/Drupal deployment on Pantheon works. The Next.js flow is genuinely different in one important way (see below).
Environments: Dev, Test, Live, Multidev
Every Pantheon site (P1’s Next.js sites included) gets at least three environments
by default, each on its own subdomain (<environment>-<site>.pantheonsite.io):
- Dev: the primary development environment.
- Test: a staging environment for review before Live.
- Live: production. This is the only environment that commonly gets a custom domain connected to it; Dev/Test/Multidev subdomains are for the team, not visitors.
- Multidev: additional environments corresponding to Git branches or pull requests, for parallel work-in-progress review.
The Next.js-specific part: deployments to Test/Live are Git tags, not clicks
This is the one place Next.js sites on Pantheon genuinely diverge from WordPress/ Drupal sites there. On WP/Drupal, triggering a Test or Live deployment is a dashboard action (or a Terminus command) that auto-creates the underlying tag for you. For Next.js sites, you create that Git tag yourself: there’s no dashboard button that does it on your behalf today.
Deployments to Test and Live are triggered by specially-named, incrementing Git tags pushed to the connected GitHub repository:
git tag pantheon_test_1 -a -m "Deploying to Test"
git push origin --tags
# next one is pantheon_test_2, then _3, and so ongit tag pantheon_live_1 -a -m "Deploying to Live"
git push origin --tagsThree ways to create these tags: directly via git locally (above), through GitHub’s
Releases UI, or automated via GitHub Actions (or another CI/CD tool) on a push to
main. Automating this is worth doing early: manually tracking “what’s the next
tag number” via git tag --list 'pantheon_live_*' --sort=v:refname | tail -1 doesn’t
scale past the first few deploys on a real project.
Monitor a deployment’s build progress via Terminus:
terminus node:logs:build:list my-site-machine-name.testPantheon’s own guidance on why this matters less than it sounds: for a Next.js site sourcing content from P1/CCR rather than a database Pantheon hosts, the blast radius of a bad deploy is much smaller than on WordPress/Drupal: “the remediation for deploying broken code to Live is often as simple as pushing a fix … and triggering a new deployment,” since there’s no database to restore. Still worth a Test-environment review step before Live for anything non-trivial; just don’t expect the same recovery cost as a broken WP/Drupal deploy.
Getting from zero to a first deployment
See Getting Started for the
full walkthrough (repository setup, secrets, connecting the Pantheon-hosted Next.js
site). Short version: push to GitHub, create the Next.js site on
dashboard.pantheon.io from that repository, paste in
the same NEXT_PUBLIC_CSS_SITE_ID/CSS_API_KEY secrets used locally, deploy. That
gets you Dev. Test and Live are the Git-tag flow above, and a custom domain only
matters once you’re pointing Live at it.
CORS across environments
Each environment (Dev, Test, Live, every Multidev) is a different origin talking to the same P1 backend API, so cross-environment CORS is a real, live concern the moment you have more than one.
Default behavior works out of the box. The P1 API accepts requests from any
origin (Access-Control-Allow-Origin: *) until you configure otherwise, and
localhost/127.0.0.1 on any port are always accepted regardless of configuration;
this is the correct starting point for most sites and needs no setup.
Locking down to specific origins, if required, is a PATCH to the site’s
allowedOrigins:
PATCH https://ccr.p1.pantheon.io/api/sites/{your-site-id}
{ "allowedOrigins": ["https://www.mysite.com", "https://*.mysite.pantheonsite.io"] }Each entry needs a full protocol; a single * wildcard is allowed per pattern and
matches exactly one DNS label (so https://*.mysite.com covers app.mysite.com but
not a.b.mysite.com). Up to 50 patterns per site. Changes take about 5 minutes to
propagate across all regions. To recover from a broken configuration immediately,
reset to the open default with "allowedOrigins": [].
For a site with production, preview, and Pantheon platform subdomains all needing access, Pantheon’s own example covers exactly this case:
{
"allowedOrigins": [
"https://www.mysite.com",
"https://*.mysite.com",
"https://*.mysite.pantheonsite.io"
]
}Open questions for this page now live on Outstanding Questions, tracked centrally across all pages rather than repeated per page. Confirmed already, so it’s not carried over as open: Pantheon has no official GitHub Actions template for the tag-creation flow above, their own docs explicitly solicit community feedback on it rather than pointing to an existing one.