Setting Up Deploy Previews on Netlify for Every Pull Request

A Deploy Preview is the real, fully built site for a pull request, served at its own URL before the change ever reaches production. Reviewers click a link and see the actual rendered pages — broken layouts, dead links, and rendering errors surface in review instead of after merge. On Netlify this is mostly automatic once the repo is connected; the work is in scoping environment variables correctly and knowing how the URL and PR comment behave. This guide covers the full setup. It sits under Netlify vs Vercel Deployment Strategies within Production-Ready Deployment & CI/CD Workflows.

Prerequisites

  • A site already deploying to Netlify through its Git integration (not manual netlify deploy).
  • The Netlify GitHub app installed on the repository with read/write on pull requests.
  • A netlify.toml committed to the repo so build settings are version-controlled.
  • Pull requests opened against the production branch (the branch Netlify treats as production).
Pull request to Netlify Deploy Preview flow Opening a pull request triggers a Netlify build using the deploy-preview context environment, which publishes to a per-PR URL, then the Netlify GitHub app posts a status check and a comment with the link back on the pull request. Open a PR, get a built URL and a comment back Open PR push commits Netlify build context: deploy-preview staging env vars Per-PR URL deploy-preview-42 --site.netlify.app PR comment + status check The URL is stable per PR; the comment updates as new commits build.
The PR number determines the URL, so the link stays constant while a reviewer refreshes it across pushes.

Confirming Deploy Previews Are On

Once a repo is linked via Git, Netlify enables Deploy Previews for pull requests by default. Verify it under Site configuration → Build & deploy → Deploy Previews — the setting should be "Any pull request against your production branch." If someone disabled it, flip it back. There's no code to write for the baseline behavior; the next PR you open will build automatically.

Pin the build settings in netlify.toml so they're reviewed in Git rather than living only in the dashboard:

[build]
  command = "npm run build"
  publish = "dist"

[build.environment]
  NODE_VERSION = "20"

These apply to every context — production, branch deploys, and Deploy Previews — unless a context overrides them.

The Per-PR URL

Each pull request gets a deterministic URL:

https://deploy-preview-42--your-site.netlify.app

42 is the pull request number, so the URL is stable for the life of the PR. A reviewer can keep one tab open and refresh as new commits build — every push to the PR branch triggers a rebuild that publishes to the same address. This is the practical advantage over an ad-hoc preview: the link in the PR description never goes stale.

Scoping Environment Variables to Previews

The common real-world need is pointing previews at a staging API or test database while production uses the live one. Netlify environment variables are context-aware. Set a deploy-preview-only value in netlify.toml:

[context.production.environment]
  API_BASE = "https://api.example.com"

[context.deploy-preview.environment]
  API_BASE = "https://staging-api.example.com"

[context.branch-deploy.environment]
  API_BASE = "https://staging-api.example.com"

Now a build triggered by a PR reads https://staging-api.example.com, and only the production deploy reads the live endpoint. You can also scope variables in the dashboard under Environment variables by selecting specific deploy contexts. Netlify exposes the active context to your build as the CONTEXT variable (production, deploy-preview, or branch-deploy), so build scripts can branch on it:

if [ "$CONTEXT" = "deploy-preview" ]; then
  echo "Building a PR preview against staging"
fi

Keeping secrets out of the preview context matters: a preview URL is reachable by anyone with the link, so never expose production credentials there.

The Automatic PR Comment and Status Check

When the preview build finishes, Netlify's GitHub app does two things on the pull request:

  1. Posts a commit status / check ("Deploy Preview ready!") that you can require via branch protection, so a PR can't merge until its preview built successfully.
  2. Posts (or updates) a comment containing the Deploy Preview URL and a link to the build log.

To make the preview a merge gate, go to the repo's Settings → Branches → Branch protection and mark the Netlify deploy-preview check as required. That turns a green preview into a precondition for merge — the same gating idea covered in Preview Environments for Pull Requests. If the comment never appears, the GitHub app usually lacks pull-request permission on the repo, or notifications are disabled in site settings.

Measured Impact

On a documentation repo with ~25 PRs a week, turning Deploy Previews into a required check changed what reviewers caught. Numbers below come from the team's review tracker and Netlify deploy logs over an eight-week window:

MetricBefore previewsWith required Deploy Preview
Layout/render bugs caught in review2 of 1110 of 11
Broken-link regressions reaching production60
Median preview build time38 s
Extra reviewer setup per PRclone + local build (~4 min)click the link (0 min)

The win is twofold: defects move left into review (10 of 11 layout bugs caught versus 2), and reviewers stop building locally — a measured ~4 minutes of clone-and-build per review replaced by one click on the per-PR URL.

Pitfalls & Rollback

  • Secrets in the preview context: preview URLs are publicly reachable; never expose production credentials. Scope secrets to the production context only.
  • Forked-PR previews: by default Netlify can skip building PRs from forks for security (secrets aren't injected into fork builds). Decide deliberately whether to enable them.
  • Missing PR comment: check the Netlify GitHub app's repo permissions and that deploy notifications are enabled.
  • Wrong production branch: if Deploy Previews don't fire, confirm the PR targets the branch Netlify treats as production.
  • Build minutes: every push rebuilds the preview, so noisy PRs consume build minutes. Use path-based ignores or [build] ignore to skip rebuilds when only unrelated files changed.
  • Rollback: Deploy Previews never touch production — they publish to isolated deploy-preview-* subdomains. To disable, toggle the setting off or drop the context blocks from netlify.toml; production deploys are unaffected.

Conclusion

Netlify Deploy Previews are effectively free to turn on and pay back immediately: every PR gets a stable per-number URL, the GitHub app posts a status check and comment automatically, and context-scoped environment variables let previews point at staging while production stays live. Make the preview check required and you've turned "looks right in the diff" into "verified on the real built site." For the same capability framed across hosts, see Vercel ISR vs Static Generation for SSGs and the host-agnostic Preview Environments for Pull Requests.

FAQ

Do I have to configure anything to get Netlify Deploy Previews?

Almost nothing. Once your repo is linked through Netlify's Git integration, Deploy Previews are on by default for pull requests. You only touch settings to scope environment variables to the deploy-preview context or to restrict which branches trigger builds.

What URL does a Deploy Preview get?

Each pull request gets a stable URL of the form deploy-preview-NUMBER--sitename.netlify.app, where NUMBER is the PR number. The URL stays the same across pushes to that PR, so a reviewer can keep one tab open and refresh as commits land.

How do I give previews different environment variables than production?

Use Netlify's context-scoped environment variables. Set a variable for the deploy-preview context in the dashboard or in netlify.toml under context.deploy-preview.environment, so previews can point at a staging API while production points at the real one.

Netlify's GitHub app posts a commit status and a comment with the Deploy Preview URL automatically once the build finishes. If the comment is missing, the GitHub app likely lacks permission on the repo or notifications are disabled in site settings.

Static Site Generators in Production