Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.capy.sc/llms.txt

Use this file to discover all available pages before exploring further.

Cloudflare Pages builds run in Node. Workers and Pages functions run in V8 isolates (no Node fs / crypto). Same pattern as Vercel: decrypt at build time, let the framework inline values into the bundle or push them to CF’s secret store. Runtime isolates see pre-baked constants - no crypto at request time.

Pages (framework build)

For Next.js on Pages via @cloudflare/next-on-pages, SvelteKit via the SvelteKit adapter, or any framework with a Pages adapter:
  1. Add Capy CLI as a dep so Cloudflare installs it during build:
    bun add -D @capy/cli
    
  2. Wrap the framework build command in your Pages project’s Build command setting (Cloudflare dashboard → Pages → Settings → Builds & deployments):
    capy run -- <framework build>
    
    Examples:
    • Next.js: capy run -- bunx @cloudflare/next-on-pages
    • SvelteKit: capy run -- bun run build
    • Astro: capy run -- bun run build
  3. Set SECRETS_BLOB and PROJECT_KEY as Pages environment variables (Settings → Environment Variables), per environment (Production / Preview).
  4. Point your framework’s env config at the generated map. For Next on Pages this is next.config.js’s env field (same as the Vercel flow). For SvelteKit use $env/static/private. For Astro use import.meta.env. capy run emits .capy/next-env.js for Next; other frameworks read process.env during the build and inline via their own mechanism.
  5. Deploy. Cloudflare runs your build command (wrapped by capy run), decrypts during build, inlines values, ships the bundle. Workers and Pages functions read the inlined constants at request time.

Workers (wrangler-only projects)

Pure Workers don’t have a framework build step, so values can’t be inlined the same way. Instead, bulk-upload the decrypted vars to Cloudflare’s Worker secret store from inside a capy run step, then wrangler deploy:
# Decrypt locally (via capy run), then pipe every non-Capy env var to
# `wrangler secret bulk`, which uploads them as Worker secrets.
capy run -- node -e '
  const skip = new Set(["SECRETS_BLOB", "PROJECT_KEY", "PATH", "HOME", "PWD"]);
  const env = Object.fromEntries(
    Object.entries(process.env).filter(([k]) => !skip.has(k) && !k.startsWith("CAPY_"))
  );
  console.log(JSON.stringify(env));
' | wrangler secret bulk

wrangler deploy
Your Worker reads values the standard way via the env parameter on the fetch handler:
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const db = env.DATABASE_URL;   // populated from Worker secret store
    // ...
  }
};
Wrap both lines in a deploy script for reproducibility:
// package.json
{
  "scripts": {
    "deploy": "capy run -- ./scripts/deploy-worker.sh"
  }
}
#!/usr/bin/env bash
# scripts/deploy-worker.sh
set -euo pipefail

node -e '
  const skip = new Set(["SECRETS_BLOB", "PROJECT_KEY", "PATH", "HOME", "PWD"]);
  const env = Object.fromEntries(
    Object.entries(process.env).filter(([k]) => !skip.has(k) && !k.startsWith("CAPY_"))
  );
  console.log(JSON.stringify(env));
' | wrangler secret bulk

wrangler deploy

Why the two paths differ

  • Pages: the framework adapter generates a server bundle during build. Your framework’s env config inlines decrypted values as string literals. Runtime reads literals - no CF storage of plaintext, no runtime crypto.
  • Workers: no framework build to hook into. Decryption still happens in Node (via capy run), but the results land in CF’s Worker secret store. The Worker reads them via env.X. CF holds plaintext.
Both are zero-trust on the Capy service side - PROJECT_KEY never leaves your machine, only the outer-wrapped portion of SECRETS_BLOB traverses the wire. The Worker path adds Cloudflare to the trust circle (same as pasting secrets into the CF dashboard directly), Pages does not.

Revocation

  • Pages: revoked deploy token → next Pages build fails; already-deployed bundles keep their inlined values until you redeploy.
  • Workers: revoked deploy token → next wrangler deploy fails, but the CF secret store still has the last-uploaded values, so the Worker keeps running. To purge, delete the secrets (wrangler secret delete <NAME>) or overwrite them with a fresh deploy.
Rotate the project key if you need immediate revocation everywhere.