Vercel’s build step runs in Node, regardless of whether your deployed functions run on Node or Edge. That means you can capy run -- next build during build, and Next.js inlines the decrypted values into the output bundle as string literals. Request-time functions read the literals - no runtime decryption, no service hop, nothing to load.
Setup (once per project)
-
Add Capy’s CLI as a dep so Vercel installs it during build:
-
Wrap your build (and dev) in
package.json:
{
"scripts": {
"dev": "capy run -- next dev",
"build": "capy run -- next build"
}
}
-
Point
next.config.js at the generated env map. capy run emits .capy/next-env.js during build, containing every secret name it decrypted from SECRETS_BLOB. Import it once:
const capyEnv = require(
"./.capy/next-env"
);
module.exports = {
env: capyEnv,
};
That’s it - no hand-maintained list. Add a secret to Capy, redeploy, Next picks it up automatically.
-
Run
capy deploy and pick Vercel. Capy prints two env vars - SECRETS_BLOB and PROJECT_KEY - and the setup page shows you the exact values. Paste them into Settings → Environment Variables in the Vercel dashboard (or vercel env add SECRETS_BLOB production / vercel env add PROJECT_KEY production). Repeat for Preview and Development if you want Capy to decrypt there too.
-
Deploy. Vercel clones your branch, installs
@capysc/cli, runs capy run -- next build, and the resulting bundle has your runtime values baked in. Both Node and Edge routes read them normally.
Vercel builds each git branch independently. Production, staging, and PR preview branches each get whichever secrets you’ve pasted into their respective Vercel environments with no manual sync step.
What happens during the build
Why this beats runtime decryption:
- Runtime functions do zero crypto - they read already-inlined constants.
- Edge / Node / any framework - the mechanism is just
process.env.
- One service call per build, not per request.
- Revocation = redeploy. Intentional; no caches to chase.
PROJECT_KEY never leaves the build step. Only the outer-wrapped portion of SECRETS_BLOB travels to Capy’s service; the service verifies the deploy token isn’t revoked and returns a one-way derived service_key. That’s combined locally with PROJECT_KEY to derive the key that actually opens the encrypted env. See Cryptography → Deploying for the exact construction.
Local development
Same wrapper, different command:
capy run resolves the project key from your local keyring (populated by capy sync) - no SECRETS_BLOB / PROJECT_KEY required locally. See Getting started → Next.js for the end-to-end local loop. Last modified on June 10, 2026