Deploy on Vercel
Ship a MainSDK app on Vercel with secrets as references, a production overlay, mainsdk check on every pull request and a second network wall.
Deploy Pinecart, a Next.js app on MainSDK, to Vercel with no key in your code and a check that blocks unsafe changes before they ship. MainSDK is a library, not a host, so Vercel still deploys it; Ship with deploy config writes vercel.json from main.yaml. This guide adds secrets as references, a production overlay, mainsdk check in CI and a second network wall.
Before you start:
- A Next.js App Router app with a
main.yaml(see Adopt an existing app if you don't have one yet). - A Vercel project linked to the repo, and the Vercel CLI.
npx mainsdk checkpassing locally (see Your first check).
1. Keep keys as references
main.yaml never holds a key. It names one with secret:NAME, and the secrets driver resolves it on the server at startup. On Vercel, the env driver reads Vercel environment variables.
schema: 1
project: prj_01JC8Q4W7ZK3M5N8P2R6T9V0XY
baseline: main27
targets: { web: { framework: nextjs } }
secrets:
driver: env # reads Vercel environment variables
auth:
driver: github
db:
driver: postgres
regions: { us: secret:DATABASE_URL_US, eu: secret:DATABASE_URL_EU }
ai:
driver: bedrock # IAM role, no key in code
config:
driver: vercel-global-config # settings change without a deploy
schema: ./config.schema.json
jobs:
driver: vercel-queues
overlays: { order: [market, segment, env] }Add the values in Vercel, per environment:
vercel env add DATABASE_URL_US production
vercel env add DATABASE_URL_EU productionIf your keys live in Vault, AWS, Google Cloud, Azure, Doppler or Infisical, change secrets.driver and keep the same secret: references. See Secrets.
2. Add a production overlay
Put production-only values in main.env.prod.yaml. Environment resolves at build time, so the production build carries only that layer. See main.yaml and overlays.
network:
default: deny
allow: ["*.pinecart.dev"]3. Check the production config
mainsdk check --env prod refuses any interface that still resolves to a local driver. If an earlier setup left secrets.driver: local, you see:
npx mainsdk check --env prodmainsdk check · pinecart · env prod · Main 27
config 1 finding
MAIN-CHECK-0026 critical main.yaml
fix: local driver in production: secrets. Set secrets.driver to env or a key service.
secrets
policy
network
data
1 gate failed · exit 1Set secrets.driver: env as in step 1 and run it again until it ends with all gates passed · exit 0.
4. Check every pull request
Run the check in CI on each pull request, before Vercel promotes anything. The check is free and runs on your own runner.
name: mainsdk
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci
- run: npx mainsdk check --env prod --sarif mainsdk.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: { sarif_file: mainsdk.sarif }SARIF puts each finding inline on the pull request. Make the job a required status check, so a failed gate blocks the merge and the deploy that follows it. Exit codes are explained in The check.
5. Add a second network wall
network.allow is enforced in the SDK for every outbound call. Export the same list as a firewall rule for an independent wall. The CLI writes Kubernetes rules with --to k8s and AWS security-group rules with --to aws-sg. Vercel and Cloudflare exports are planned, so on Vercel the SDK check is the wall for now:
npx mainsdk network export --to k8sSee Network permissions.
6. Verify the deploy
Open a pull request. The mainsdk job runs, and a red check blocks the merge. Once it is green and merged, Vercel deploys as usual. To confirm nothing secret reached the browser, run the check against the production build output:
npx mainsdk check --env prodA secret value in a client chunk fails with MAIN-SECRET-0004 and names the chunk.
Optional: OIDC instead of a stored key
When you send telemetry to MainSDK Cloud, each environment normally needs an ingest key in MAINSDK_KEY (msk_live_… for prod, msk_test_… for dev and stage). On Vercel and in GitHub Actions the platform's OIDC token for the linked project or repo is accepted in place of the key.
telemetry:
to: [terminal, mainsdk]
sample: 0.2The Vercel-side setup for that OIDC trust (which audience and issuer to register) is not decided yet. Until it is, store MAINSDK_KEY as a sensitive Vercel variable.
Next
Was this page helpful?