PayloadSolutions

Configuration

Every plugin option with its default — targets, tracked collections and globals, automatic deploys, ticks, access, retention, hooks, admin surfaces, slugs.

vercelPlugin({
  targets: [{ slug: 'production', label: 'Website', hook: process.env.VERCEL_DEPLOY_HOOK, url: 'https://example.com' }],
  token: process.env.VERCEL_TOKEN,
  teamId: process.env.VERCEL_TEAM_ID,
  webhookSecret: process.env.VERCEL_WEBHOOK_SECRET,
  collections: { pages: true, posts: { targets: ['production'], on: 'change' } },
  globals: { header: true },
  autoDeploy: { quietPeriod: '60s', maxWait: '10m' },
  tick: { adminHeartbeat: true, beacon: true, job: { cron: '* * * * *', queue: 'vercel' }, secret: process.env.VERCEL_TICK_SECRET },
  access: { read, deploy, rollback },
  retention: { days: 90, keep: 200 },
  recordExternalDeployments: true,
  hooks: { onTriggered, onStateChange, onReady, onError, shouldTrack },
  admin: { header: true, view: true, documentPill: true, group: 'Vercel' },
  slugs: { deployments: 'vercel-deployments', changes: 'vercel-changes', targets: 'vercel-targets' },
  apiBase: 'https://api.vercel.com',
  disabled: false,
})

Only targets is required. Everything below lists each option with its default.

targets

One entry per site or environment.

FieldDefaultMeaning
slugletters, digits, - and _; used in URLs, the ledger and collections[].targets
labelthe slugshown in the admin
hookthe deploy hook URL. undefined (an unset env var) registers the target as not configured: shown greyed, never triggered, never an error
urlpublic site URL for the Open site link
projectIdparsed from hookVercel project id used by the status API
token, teamIdplugin-level valuesper-target overrides for projects on another team
buildCachetruefalse appends ?buildCache=false to every trigger of this target

A hook that is present but is not a …/v1/integrations/deploy/<projectId>/<hookId> URL throws at config time. A missing hook does not — so a fresh clone with no .env boots, and the admin explains what is missing.

token, teamId

Optional. Without a token the plugin triggers and tracks changes but cannot read status, cancel or roll back. Vercel tokens are account- or team-scoped, never project-scoped; for a team project pass teamId too. Prefer a dedicated token from a service account — the plugin uses only the deployments and rollback endpoints.

webhookSecret

Optional. When set, POST /api/vercel/webhook is registered and verifies x-vercel-signature (HMAC-SHA1 of the raw body). When unset the endpoint does not exist. Account webhooks need a Pro or Enterprise team.

collections, globals

Which content reaches which targets.

collections: {
  pages: true,                                        // all targets, default semantics
  posts: { targets: ['production'] },                 // one target
  previews: { on: 'change' },                         // count drafts too
},
globals: { header: true, footer: { targets: ['production'] } },
OptionDefaultMeaning
targetsevery targetwhich targets a change to this collection or global reaches
on'publish' when the collection has versions.drafts, else 'change'publish: only saves that leave the document published, plus unpublish and delete. change: every save

Globals count every save. Deletes always count. Each change is one row per target per document; a document saved twenty times before the next deploy is one pending change with saves: 20, titled from the collection's admin.useAsTitle.

Slugs that do not exist in the config, and targets that are not declared, throw at config time.

autoDeploy

{ quietPeriod: '60s', maxWait: '10m' }. Durations take a number of milliseconds or a string ('45s', '2m', '1h'). maxWait must be at least quietPeriod. false disables automatic deployments; the button, the API and flush still work. Details in Automatic deploys.

tick

Who is allowed to fire due windows and refresh statuses.

OptionDefaultMeaning
adminHeartbeattruethe header widget's status poll runs a tick on the server
beacontruenavigator.sendBeacon('/api/vercel/flush') when an admin tab closes fires pending targets at once
job{ cron: '* * * * *', queue: 'vercel' }the vercel:tick scheduled task; false registers no task
secretaccepted in the x-vercel-plugin-secret header by POST /api/vercel/tick, for external crons

access

Three access functions, each ({ req }) => boolean | Promise<boolean>, all defaulting to "any logged-in user of the admin collection".

FunctionGates
readstatus, pending changes, history, the document pill, the Deployments view, the collection
deploytrigger, flush, pause and resume
rollbackcancel, rollback, deleting ledger rows

retention

{ days: 90, keep: 200 } per target: finished rows older than days, and finished rows beyond the keep newest, are deleted on the hourly retention pass. In-flight rows are never deleted.

recordExternalDeployments

true. Deployments seen on Vercel that Payload did not trigger — git pushes, dashboard redeploys, other hooks — become rows with cause Git / Vercel, so the history and the Live pointer are complete. They never clear pending changes.

hooks

hooks: {
  onTriggered: ({ record, target, cause }) => {},
  onStateChange: ({ record, previousState }) => {},
  onReady: ({ record }) => {},
  onError: ({ record }) => {},
  shouldTrack: ({ collection, global, doc, previousDoc, operation, req }) => true,
}

All hooks are awaited; their errors are logged, never thrown into the request that caused them. shouldTrack returning false skips a change; so does req.context.vercelSkip = true on the operation.

admin

OptionDefaultMeaning
headertruethe header widget on every admin page
viewtruethe Deployments view at /admin/deployments and its nav link; { path: '/deploys' } moves it; false removes it
documentPilltruethe Not deployed yet / Live pill on tracked collections and globals
group'Vercel'nav group of the vercel-deployments collection

slugs

{ deployments: 'vercel-deployments', changes: 'vercel-changes', targets: 'vercel-targets' }. Change them when they collide with your own collections. Changing them after the first boot is a schema change.

apiBase

'https://api.vercel.com'. Only change it to point the plugin at the mock server (pnpm dev:mock-vercel, http://localhost:3399).

disabled

false. When true the collections are still added (so migrations stay consistent) but no hooks, endpoints, task or admin components are registered.

Environment variables the dev app reads

VariablePurpose
VERCEL_DEPLOY_HOOK_PRODUCTION, VERCEL_DEPLOY_HOOK_STAGINGdeploy hook URLs
VERCEL_TOKEN, VERCEL_TEAM_IDstatus, cancel, rollback
VERCEL_WEBHOOK_SECRETwebhook receiver
VERCEL_TICK_SECRETexternal cron authentication
VERCEL_API_BASEpoint the plugin at the mock server
VERCEL_QUIET_PERIOD, VERCEL_MAX_WAITshorter windows while developing

On this page