Set up a preview environment for every pull request

A preview environment is a full copy of your app, deployed from a pull request, at its own URL. Reviewers click a link instead of pulling the branch, and product and design can check a change before it merges. This guide sets one up in about ten minutes.

Install the CLI

You need the CLI to link the repository and to test the setup locally.

npm install -g @cloud/cli

Then log in and link the project in the root of your repository:

bash
cloud login
cloud link --project web-frontend

Turn on previews

The project file sits in the root of the repository, next to package.json:

  • db/
    • seed.sql
  • src/
    • …
  • cloud.config.tspreviews and services
  • package.json

Previews are configured in the project file. The previews block says which branches get one, which environment variables they use, and how long they live after the pull request closes.

cloud.config.ts
import { defineConfig } from "@cloud/cli";

export default defineConfig({
  service: "web-frontend",
  previews: {
    branches: ["*", "!main"],
    env: "preview",
    expireAfter: "3d",
  },
});

Commit the file and open a pull request. The first preview builds in the same time as a normal deploy, and the bot comments the URL on the pull request.

Open the preview from the dashboard

Press ⌘ K in the dashboard and type the pull request number to jump straight to its preview.

Give each preview its own data

A preview that writes to the staging database is not really isolated. Add a database branch so every preview starts from a copy of the schema and a small seed:

cloud.config.ts
previews: {
  branches: ["*", "!main"],
  env: "preview",
  database: { branchFrom: "staging", seed: "./db/seed.sql" },
},

Database branches are copy-on-write, so creating one takes a few seconds, whatever the size of the parent.

Clean up

When the pull request merges or closes, the preview and its database branch are deleted after expireAfter. To delete one sooner, run:

bash
cloud previews delete --pr 142

That is all. From now on, every pull request gets a link, and nothing is left running after it closes.

Share:

Written by

Sam Carter

Developer advocate

Sam writes the guides and turns support questions into step-by-step tutorials for previews, deploys, and team workflows.

Newsletter

Engineering notes, once a month

Release highlights, deep dives from the platform team, and guides you can use the same day. No spam.

gats-fo-lex

Unsubscribe anytime. Read our Privacy Policy.

Free tier · No credit card

Push code today. Be live before your coffee cools.

Connect a repository, pick a region, and get a production URL with HTTPS, logs, and autoscaling already switched on.

$ git push origin main

  1. Build34 s
  2. Deploy12 s
  3. Health checks3 s

your-app.example.com

Buy NowTheme Details