Environment variables

Per-project secrets encrypted at rest and injected into every preview container at start.

Setting variables

Open a project and click the Variables tab. Add a key/value pair, save, then redeploy — the next build has the new env. No rebuild of existing previews; variables are read when the container boots.

Values are encrypted
Every value is encrypted with AES-256-GCM before it hits the database. The dashboard decrypts server-side only for the owning workspace. Ciphertext never reaches the browser. If the encryption key rotates and a value fails to decrypt, the field shows blank rather than raw ciphertext so you can safely re-enter it.

Built-in variables

PreviewDrop sets these for every container, on top of whatever you add:

VariableWhat it holds
PORTTCP port your app must listen on. Do not hardcode a port — this value changes per container.
NEXTAUTH_URLAutomatically set to the live preview URL. NextAuth / Auth.js picks this up with no extra config.
AUTH_URLSame as NEXTAUTH_URL — set for frameworks that use AUTH_URL instead.

Scope

Variables are set per project and apply to every preview of that project, whatever the branch. There are no per-branch overrides: if a value must differ per branch (for example a branch database), resolve it in your app or start command.

Importing and exporting

Paste or upload a .envfile into the Variables tab to import many variables at once. There is no bulk export, so keep your source of truth in a secrets manager or your team's vault.

Secrets-in-Git? Don't.

Don't commit secrets
PreviewDrop builds and runs whatever's in your repo, including .envfiles if you commit them. Secrets committed to Git are already leaked — PreviewDrop can't un-leak them. Put real secrets only in the Variables tab.

Common recipes

Branch-isolated databases with Neon

Neon branch integration
# Project variable: every preview gets the shared staging DB DATABASE_URL=postgres://u:p@ep-shared.neon.tech/app # For a DB per branch, create the Neon branch in CI (Neon's GitHub # integration or API) and have your start command look up its URL # before booting. PreviewDrop variables are the same for every branch.

Auth callbacks (NextAuth / Auth.js)

NextAuth / Auth.js
# NEXTAUTH_URL and AUTH_URL are set automatically — no variable needed. # Add *.previews.previewdrop.dev as an allowed redirect URI in your OAuth provider.

CORS for a separate frontend calling a preview API

Django / Rails / Express
# Hardcode the preview subdomain pattern in your CORS config: ALLOWED_ORIGINS=https://*.previews.previewdrop.dev

Feature flag SDK key scoped to previews

GrowthBook / LaunchDarkly
# Use a dedicated preview-env SDK key so flag changes don't affect production LD_SDK_KEY=sdk-preview-...

Debugging a missing variable

If your app can't see a variable you set, try in order:

  • Redeploy the preview — variables are injected at container start, not hot-reloaded.
  • Check the variable name for typos against what your app reads. A value hardcoded in your start command (e.g. PORT=8080 node server.js) overrides PreviewDrop's injected value.

If a variable still looks blank in the Variables tab after you saved it, it may have failed to decrypt (encryption key rotation, envelope corruption). Re-enter the value; the next save re-encrypts under the current key.