Deploying to Vercel
Before you start, have the services created and your environment variables ready.
Import the repository
Create a new Vercel project from your fork of the monorepo and set its Root
Directory to apps/app. The framework preset is Next.js.
Connect storage
On the project’s Storage tab, connect two Blob stores: a public one
with the env var prefix PUBLIC_BLOB, which injects
PUBLIC_BLOB_READ_WRITE_TOKEN, and a private one with the prefix
PRIVATE_BLOB, which injects PRIVATE_BLOB_READ_WRITE_TOKEN (see
File store). Vercel Sandbox authenticates with Vercel’s OIDC
token, which is also injected automatically.
Push the sandbox image
Chat sandboxes boot from a custom image in the project’s Vercel Container
Registry. Set up the Vercel Sandbox image workflow or push it by hand, as
Sandbox image
describes.
Add environment variables
Add each variable in the right scope. See the table below.
Deploy
The build runs drizzle-kit migrate against DATABASE_URL, then
next build, so schema migrations land before the new code serves traffic.
Point your domain
Add your custom domain. BETTER_AUTH_URL and BETTER_AUTH_PRODUCTION_URL
must match it.
Environment variable scopes
Preview deploys sign users in through production: the auth proxy signs state on production and verifies it on the preview that started the sign-in. That’s why some values must be identical everywhere.
Preview deploys run migrations too. If Preview points at the production database, a PR’s migration reaches production before the PR merges. To keep them apart, give previews their own database. For example, Neon’s Vercel integration creates a database branch per preview automatically.
Pull request checks
The app’s vercel.json adds a Vercel Cron job that calls
/app/api/pr-watch/tick every five minutes. It checks each canvas with an open
pull request on GitHub and adds what changed (failing checks, a conflict, the
merge) to the chat, even when no one has the canvas open. Set CRON_SECRET in
Production so the route accepts the call. If you serve the app at the domain
root rather than under /app, change the job’s path to /api/pr-watch/tick.
Vercel’s Hobby plan only runs cron jobs once a day, so the job needs a Pro plan.
Preview deploys are opt-in
Each app’s vercel.json sets an ignored build step
(scripts/vercel-ignore-build.sh) so previews don’t spend build credits on
every push. Production deploys always build. A preview builds only when you
opt in, for every app or for one:
Adding a label doesn’t start a deploy on its own: push afterwards, or redeploy from Vercel. Only the subject line counts, so a commit body that mentions a token doesn’t opt in.
The label check calls the GitHub API unauthenticated, which works for a
public repository. For a private fork, add a GITHUB_TOKEN environment
variable (Preview scope) with read access to its pull requests.
Serving under a path
The reference deployment serves the marketing site at the domain root, the
product at /app, and these docs at /docs. The marketing app
(apps/homepage/vercel.json) rewrites /app/* and /docs/* to the other two
Vercel projects, and the product project sets NEXT_PUBLIC_BASE_PATH=/app.
To serve Screenplay from its own domain instead, leave NEXT_PUBLIC_BASE_PATH
unset. See Mount path.