From 541d2a4378939fb3450422f79619153446b6f61c Mon Sep 17 00:00:00 2001 From: Alec Thomas <112640918+a-thomas-22@users.noreply.github.com> Date: Fri, 26 Jun 2026 11:25:58 -0500 Subject: [PATCH] fix(redirects): serve legacy redirects in production via render.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Production runs on Render (a manually-created static site), which ignores vercel.json — so the redirects wired up in #71 never applied in prod. The live service also had broad SPA-fallback rewrites (/sdk/*, /react/*, /smart-wallet/*, /meta-infra/*, /recovery-flow/*) that, under Render's first-match-by-priority routing, swallowed ~145 of the 201 legacy URLs into the app shell (-> in-app 404). - render.yaml: Render Blueprint that adopts the existing "docs" static site. Generated redirects sit ABOVE the SPA-fallback rewrites so they take priority. - redirects.config.js stays the single source of truth; folds in /magic-account (collapsing its stale /sdk/advanced/chain-abstraction hop). - scripts/sync-render-redirects.mjs splices the generated block between sentinels, preserving the hand-maintained service def + fallbacks. Output is prettier-clean by construction. - CI (redirects-in-sync) + npm scripts now target render.yaml. - Remove the unused vercel.json and its sync script. --- .github/workflows/redirects-in-sync.yml | 24 +- package.json | 4 +- redirects.config.js | 9 +- render.yaml | 683 +++++++++++++++ scripts/sync-render-redirects.mjs | 68 ++ scripts/sync-vercel-redirects.mjs | 45 - vercel.json | 1009 ----------------------- vocs.config.tsx | 4 +- 8 files changed, 774 insertions(+), 1072 deletions(-) create mode 100644 render.yaml create mode 100644 scripts/sync-render-redirects.mjs delete mode 100644 scripts/sync-vercel-redirects.mjs delete mode 100644 vercel.json diff --git a/.github/workflows/redirects-in-sync.yml b/.github/workflows/redirects-in-sync.yml index ee60792..ff00160 100644 --- a/.github/workflows/redirects-in-sync.yml +++ b/.github/workflows/redirects-in-sync.yml @@ -1,10 +1,10 @@ name: redirects-in-sync -# Guarantees vercel.json matches redirects.config.js (the single source of -# truth). Vercel reads vercel.json at the start of a deployment, so a commit -# that edits redirects.config.js without regenerating vercel.json would ship -# stale production redirects. This job regenerates the file and fails if it -# differs from what's committed. +# Guarantees render.yaml matches redirects.config.js (the single source of +# truth). Render reads render.yaml at the start of a deployment, so a commit +# that edits redirects.config.js without regenerating render.yaml would ship +# stale production redirects. This job regenerates the generated block and fails +# if it differs from what's committed. on: pull_request: @@ -22,14 +22,14 @@ jobs: # No `npm install` needed: the sync script uses only Node built-ins and # imports the local redirects.config.js. - - name: Regenerate vercel.json from redirects.config.js - run: node scripts/sync-vercel-redirects.mjs + - name: Regenerate render.yaml from redirects.config.js + run: node scripts/sync-render-redirects.mjs - - name: Fail if vercel.json is out of date + - name: Fail if render.yaml is out of date run: | - if [ -n "$(git status --porcelain vercel.json)" ]; then - echo "::error::vercel.json is out of sync with redirects.config.js. Run 'npm run sync-redirects' and commit the result." - git --no-pager diff vercel.json + if [ -n "$(git status --porcelain render.yaml)" ]; then + echo "::error::render.yaml is out of sync with redirects.config.js. Run 'npm run sync-redirects' and commit the result." + git --no-pager diff render.yaml exit 1 fi - echo "vercel.json is in sync with redirects.config.js." + echo "render.yaml is in sync with redirects.config.js." diff --git a/package.json b/package.json index d646469..e417e9f 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "type": "module", "scripts": { "dev": "vocs dev", - "sync-redirects": "node scripts/sync-vercel-redirects.mjs", - "prebuild": "node scripts/sync-vercel-redirects.mjs", + "sync-redirects": "node scripts/sync-render-redirects.mjs", + "prebuild": "node scripts/sync-render-redirects.mjs", "build": "vocs build", "preview": "vocs preview", "format": "prettier --write ." diff --git a/redirects.config.js b/redirects.config.js index 4a8a361..8c285d0 100644 --- a/redirects.config.js +++ b/redirects.config.js @@ -3,10 +3,10 @@ * * Single source of truth for redirects. Consumed in two places: * - the dev-server redirect middleware in vocs.config.tsx (local `vocs dev`) - * - `npm run sync-redirects`, which mirrors these into vercel.json so Vercel + * - `npm run sync-redirects`, which splices these into render.yaml so Render * serves them in production (Vocs has no build-time redirect support). * - * After editing, run `npm run sync-redirects` and commit the updated vercel.json. + * After editing, run `npm run sync-redirects` and commit the updated render.yaml. * * Follows the OffchainLabs/arbitrum-docs redirects.config.js pattern. Kept as a * `.js` module (types in redirects.config.d.ts) so it resolves natively in both @@ -128,6 +128,11 @@ export const redirects = [ { from: "/smart-routing-address", to: "/onramp/smart-routing-address" }, { from: "/global-address", to: "/onramp/smart-routing-address" }, + // Magic Account (legacy) → Chain Abstraction. Was a manual Render redirect to + // /sdk/advanced/chain-abstraction, itself now legacy; collapse the hop straight + // to the live page. (/magic-account/* subpaths are handled in render.yaml.) + { from: "/magic-account", to: "/smart-accounts/chain-abstraction/overview" }, + // Embedded Wallet docs live at /wallets/* (alpha — unlisted in sidebars). // React WaaS hooks → Advanced › React Hooks (legacy) diff --git a/render.yaml b/render.yaml new file mode 100644 index 0000000..865fd43 --- /dev/null +++ b/render.yaml @@ -0,0 +1,683 @@ +# Render Blueprint — adopts the existing, manually-created "docs" static site. +# +# Adoption is by `name`: it MUST stay "docs" to match the live service, or Render +# will spin up a suffixed duplicate instead of updating the real one. The service +# settings below mirror the Render dashboard export. +# +# Routing note: Render applies the FIRST matching rule by priority, top to bottom +# (https://render.com/docs/redirects-rewrites). The generated specific redirects +# MUST therefore stay ABOVE the broad SPA-fallback rewrites at the bottom — else +# `/sdk/*`, `/react/*`, `/smart-wallet/*` etc. would swallow ~145 legacy URLs into +# the app shell (which then 404s). The redirect block is generated from +# redirects.config.js by `npm run sync-redirects` — edit that file, not this one. +version: "1" +services: + - type: web + name: docs + runtime: static + repo: https://github.com/zerodevapp/docs + envVars: + - key: VITE_POSTHOG_HOST + sync: false + - key: VITE_POSTHOG + sync: false + - key: NODE_VERSION + sync: false + buildCommand: bun i; bun run build + staticPublishPath: ./docs/dist + domains: + - docs.zerodev.app + - new-docs.zerodev.app + autoDeployTrigger: commit + routes: + # >>> BEGIN GENERATED REDIRECTS — produced by `npm run sync-redirects`; do not edit by hand + - type: redirect + source: "/sdk/getting-started/quickstart" + destination: "/get-started/quickstart" + - type: redirect + source: "/sdk/getting-started/tutorial" + destination: "/get-started/quickstart" + - type: redirect + source: "/sdk/getting-started/tutorial-passkeys" + destination: "/onboarding/passkeys/tutorial" + - type: redirect + source: "/sdk/getting-started/quickstart-7702" + destination: "/get-started/eip-7702/quickstart" + - type: redirect + source: "/sdk/getting-started/quickstart-agentkit" + destination: "/smart-accounts/permissions/agentkit" + - type: redirect + source: "/sdk/getting-started/migration" + destination: "/advanced/migration" + - type: redirect + source: "/sdk/core-api/create-account" + destination: "/onboarding/create-a-smart-account" + - type: redirect + source: "/sdk/core-api/using-plugins" + destination: "/smart-accounts/use-plugins/overview" + - type: redirect + source: "/sdk/core-api/send-transactions" + destination: "/smart-accounts/send-transactions" + - type: redirect + source: "/sdk/core-api/batch-transactions" + destination: "/smart-accounts/batch-transactions" + - type: redirect + source: "/sdk/core-api/sponsor-gas" + destination: "/smart-accounts/sponsor-gas/evm" + - type: redirect + source: "/sdk/core-api/pay-gas-with-erc20s" + destination: "/smart-accounts/pay-gas-with-erc20s" + - type: redirect + source: "/sdk/core-api/sign-and-verify" + destination: "/smart-accounts/sign-and-verify" + - type: redirect + source: "/sdk/core-api/deploy-contract" + destination: "/smart-accounts/deploy-contract" + - type: redirect + source: "/sdk/core-api/delegatecall" + destination: "/smart-accounts/delegatecall" + - type: redirect + source: "/sdk/core-api/status" + destination: "/api-and-toolings/tools/status" + - type: redirect + source: "/sdk/core-api/debugger" + destination: "/api-and-toolings/tools/debugger" + - type: redirect + source: "/sdk/advanced/chain-abstraction" + destination: "/smart-accounts/chain-abstraction/overview" + - type: redirect + source: "/sdk/advanced/passkeys" + destination: "/onboarding/passkeys/overview" + - type: redirect + source: "/sdk/advanced/multisig" + destination: "/advanced/multisig" + - type: redirect + source: "/sdk/advanced/social-login" + destination: "/onboarding/social-login" + - type: redirect + source: "/sdk/advanced/session-keys" + destination: "/smart-accounts/permissions/session-keys" + - type: redirect + source: "/sdk/advanced/recovery" + destination: "/advanced/account-recovery/sdk-recovery" + - type: redirect + source: "/sdk/advanced/multi-chain-signing" + destination: "/smart-accounts/multi-chain-signing" + - type: redirect + source: "/sdk/advanced/key-storage" + destination: "/advanced/key-storage" + - type: redirect + source: "/sdk/advanced/defi" + destination: "/smart-accounts/defi" + - type: redirect + source: "/sdk/advanced/parallel-orders" + destination: "/smart-accounts/parallel-transactions" + - type: redirect + source: "/sdk/advanced/wallet-connect" + destination: "/advanced/wallet-connect" + - type: redirect + source: "/sdk/advanced/fallback-providers" + destination: "/advanced/fallback-providers" + - type: redirect + source: "/sdk/advanced/run-solidity-code-on-init" + destination: "/advanced/track-deployed-accounts" + - type: redirect + source: "/sdk/advanced/upgrade-kernel" + destination: "/advanced/upgrade-kernel" + - type: redirect + source: "/sdk/advanced/go-sdk" + destination: "/get-started/sdks/server-side/go" + - type: redirect + source: "/advanced/go-sdk" + destination: "/get-started/sdks/server-side/go" + - type: redirect + source: "/sdk/advanced/userop-builder-api" + destination: "/advanced/userop-builder-api" + - type: redirect + source: "/sdk/advanced/supported-base-tokens" + destination: "/smart-accounts/chain-abstraction/supported-base-tokens" + - type: redirect + source: "/sdk/advanced/supported-defi-tokens" + destination: "/smart-accounts/chain-abstraction/supported-defi-tokens" + - type: redirect + source: "/sdk/permissions/intro" + destination: "/smart-accounts/permissions/intro" + - type: redirect + source: "/sdk/permissions/transaction-automation" + destination: "/smart-accounts/permissions/transaction-automation" + - type: redirect + source: "/sdk/permissions/install-with-init-config" + destination: "/smart-accounts/permissions/install-with-init-config" + - type: redirect + source: "/sdk/permissions/1-click-trading" + destination: "/smart-accounts/permissions/1-click-trading" + - type: redirect + source: "/sdk/permissions/signers/ecdsa" + destination: "/smart-accounts/permissions/signers/ecdsa" + - type: redirect + source: "/sdk/permissions/signers/passkeys" + destination: "/smart-accounts/permissions/signers/passkeys" + - type: redirect + source: "/sdk/permissions/signers/multisig" + destination: "/smart-accounts/permissions/signers/multisig" + - type: redirect + source: "/sdk/permissions/signers/build-your-own" + destination: "/smart-accounts/permissions/signers/build-your-own" + - type: redirect + source: "/sdk/permissions/policies/sudo" + destination: "/smart-accounts/permissions/policies/sudo" + - type: redirect + source: "/sdk/permissions/policies/call" + destination: "/smart-accounts/permissions/policies/call" + - type: redirect + source: "/sdk/permissions/policies/gas" + destination: "/smart-accounts/permissions/policies/gas" + - type: redirect + source: "/sdk/permissions/policies/signature" + destination: "/smart-accounts/permissions/policies/signature" + - type: redirect + source: "/sdk/permissions/policies/rate-limit" + destination: "/smart-accounts/permissions/policies/rate-limit" + - type: redirect + source: "/sdk/permissions/policies/timestamp" + destination: "/smart-accounts/permissions/policies/timestamp" + - type: redirect + source: "/sdk/permissions/policies/build-your-own" + destination: "/smart-accounts/permissions/policies/build-your-own" + - type: redirect + source: "/sdk/permissions/actions/build-your-own" + destination: "/smart-accounts/permissions/actions/build-your-own" + - type: redirect + source: "/sdk/signers/intro" + destination: "/onboarding/auth-providers" + - type: redirect + source: "/sdk/signers/dynamic" + destination: "/onboarding/dynamic" + - type: redirect + source: "/sdk/signers/privy" + destination: "/onboarding/privy" + - type: redirect + source: "/sdk/signers/magic" + destination: "/onboarding/magic" + - type: redirect + source: "/sdk/signers/web3auth" + destination: "/onboarding/web3auth" + - type: redirect + source: "/sdk/signers/smart-wallet" + destination: "/onboarding/smart-wallet" + - type: redirect + source: "/sdk/signers/portal" + destination: "/onboarding/portal" + - type: redirect + source: "/sdk/signers/turnkey" + destination: "/onboarding/turnkey" + - type: redirect + source: "/sdk/signers/fireblocks" + destination: "/onboarding/fireblocks" + - type: redirect + source: "/sdk/signers/capsule" + destination: "/onboarding/capsule" + - type: redirect + source: "/sdk/signers/lit-protocol" + destination: "/onboarding/lit-protocol" + - type: redirect + source: "/sdk/signers/particle" + destination: "/onboarding/particle" + - type: redirect + source: "/sdk/signers/dfns" + destination: "/onboarding/dfns" + - type: redirect + source: "/sdk/signers/arcana" + destination: "/onboarding/arcana" + - type: redirect + source: "/sdk/signers/eoa" + destination: "/onboarding/eoa" + - type: redirect + source: "/sdk/signers/custom-signer" + destination: "/onboarding/custom-signer" + - type: redirect + source: "/sdk/solana/sponsor-gas" + destination: "/smart-accounts/sponsor-gas/solana" + - type: redirect + source: "/sdk/infra/intro" + destination: "/api-and-toolings/infrastructure/choose-an-infra-provider" + - type: redirect + source: "/sdk/infra/zerodev" + destination: "/api-and-toolings/infrastructure/zerodev" + - type: redirect + source: "/sdk/infra/pimlico" + destination: "/api-and-toolings/infrastructure/pimlico" + - type: redirect + source: "/sdk/infra/coinbase" + destination: "/api-and-toolings/infrastructure/coinbase" + - type: redirect + source: "/sdk/presets/intro" + destination: "/api-and-toolings/presets/intro" + - type: redirect + source: "/sdk/presets/zerodev" + destination: "/api-and-toolings/presets/zerodev" + - type: redirect + source: "/sdk/faqs/chains" + destination: "/api-and-toolings/faqs/chains" + - type: redirect + source: "/sdk/faqs/audits" + destination: "/api-and-toolings/faqs/audits" + - type: redirect + source: "/sdk/faqs/debug-userop" + destination: "/api-and-toolings/faqs/debug-userop" + - type: redirect + source: "/sdk/faqs/use-with-ethers" + destination: "/api-and-toolings/faqs/use-with-ethers" + - type: redirect + source: "/sdk/faqs/use-with-gelato" + destination: "/api-and-toolings/faqs/use-with-gelato" + - type: redirect + source: "/sdk/faqs/use-with-react-native" + destination: "/api-and-toolings/faqs/use-with-react-native" + - type: redirect + source: "/meta-infra/intro" + destination: "/api-and-toolings/infrastructure/intro" + - type: redirect + source: "/meta-infra/gas-policies" + destination: "/api-and-toolings/infrastructure/gas-policies" + - type: redirect + source: "/meta-infra/custom-gas-policies" + destination: "/api-and-toolings/infrastructure/custom-gas-policies" + - type: redirect + source: "/meta-infra/rpcs" + destination: "/api-and-toolings/infrastructure/rpcs" + - type: redirect + source: "/meta-infra/api" + destination: "/api-and-toolings/infrastructure/api" + - type: redirect + source: "/recovery-flow/intro" + destination: "/advanced/account-recovery/flow-intro" + - type: redirect + source: "/recovery-flow/setup" + destination: "/advanced/account-recovery/flow-setup" + - type: redirect + source: "/recovery-flow/portal" + destination: "/advanced/account-recovery/portal" + - type: redirect + source: "/smart-routing-address" + destination: "/onramp/smart-routing-address" + - type: redirect + source: "/global-address" + destination: "/onramp/smart-routing-address" + - type: redirect + source: "/magic-account" + destination: "/smart-accounts/chain-abstraction/overview" + - type: redirect + source: "/react/getting-started" + destination: "/advanced/react-hooks/getting-started" + - type: redirect + source: "/react/use-balance" + destination: "/advanced/react-hooks/use-balance" + - type: redirect + source: "/react/use-chainid" + destination: "/advanced/react-hooks/use-chainid" + - type: redirect + source: "/react/use-chains" + destination: "/advanced/react-hooks/use-chains" + - type: redirect + source: "/react/use-create-basic-session" + destination: "/advanced/react-hooks/use-create-basic-session" + - type: redirect + source: "/react/use-create-kernelclient-eoa" + destination: "/advanced/react-hooks/use-create-kernelclient-eoa" + - type: redirect + source: "/react/use-create-kernelclient-passkey" + destination: "/advanced/react-hooks/use-create-kernelclient-passkey" + - type: redirect + source: "/react/use-create-kernelclient-social" + destination: "/advanced/react-hooks/use-create-kernelclient-social" + - type: redirect + source: "/react/use-create-session" + destination: "/advanced/react-hooks/use-create-session" + - type: redirect + source: "/react/use-disconnect-kernelclient" + destination: "/advanced/react-hooks/use-disconnect-kernelclient" + - type: redirect + source: "/react/use-kernelclient" + destination: "/advanced/react-hooks/use-kernelclient" + - type: redirect + source: "/react/use-send-transaction" + destination: "/advanced/react-hooks/use-send-transaction" + - type: redirect + source: "/react/use-send-transaction-with-session" + destination: "/advanced/react-hooks/use-send-transaction-with-session" + - type: redirect + source: "/react/use-send-useroperation" + destination: "/advanced/react-hooks/use-send-useroperation" + - type: redirect + source: "/react/use-send-useroperation-with-session" + destination: "/advanced/react-hooks/use-send-useroperation-with-session" + - type: redirect + source: "/react/use-sessions" + destination: "/advanced/react-hooks/use-sessions" + - type: redirect + source: "/react/use-session-kernelclient" + destination: "/advanced/react-hooks/use-session-kernelclient" + - type: redirect + source: "/react/use-set-kernelclient" + destination: "/advanced/react-hooks/use-set-kernelclient" + - type: redirect + source: "/react/use-switch-chain" + destination: "/advanced/react-hooks/use-switch-chain" + - type: redirect + source: "/react/use-wallet-connect" + destination: "/advanced/react-hooks/use-wallet-connect" + - type: redirect + source: "/smart-wallet/which-sdk" + destination: "/onboarding/create-a-smart-account" + - type: redirect + source: "/smart-wallet/quickstart-core" + destination: "/get-started/quickstart" + - type: redirect + source: "/smart-wallet/quickstart-react" + destination: "/get-started/quickstart" + - type: redirect + source: "/smart-wallet/quickstart-capabilities" + destination: "/get-started/quickstart" + - type: redirect + source: "/smart-wallet/creating-wallets" + destination: "/onboarding/create-a-smart-account" + - type: redirect + source: "/smart-wallet/setting-up-zerodev-projects" + destination: "/" + - type: redirect + source: "/smart-wallet/sending-transactions" + destination: "/smart-accounts/send-transactions" + - type: redirect + source: "/smart-wallet/batching-transactions" + destination: "/smart-accounts/batch-transactions" + - type: redirect + source: "/smart-wallet/pay-gas-in-erc20s" + destination: "/smart-accounts/pay-gas-with-erc20s" + - type: redirect + source: "/smart-wallet/sponsoring-gas" + destination: "/smart-accounts/sponsor-gas/evm" + - type: redirect + source: "/smart-wallet/delegatecall" + destination: "/smart-accounts/delegatecall" + - type: redirect + source: "/smart-wallet/multisig" + destination: "/advanced/multisig" + - type: redirect + source: "/smart-wallet/account-recovery" + destination: "/advanced/account-recovery/sdk-recovery" + - type: redirect + source: "/smart-wallet/importing-assets" + destination: "/onboarding/create-a-smart-account" + - type: redirect + source: "/smart-wallet/defi-integrations" + destination: "/smart-accounts/defi" + - type: redirect + source: "/smart-wallet/one-click-trading" + destination: "/smart-accounts/permissions/transaction-automation" + - type: redirect + source: "/smart-wallet/parallel-transactions" + destination: "/smart-accounts/parallel-transactions" + - type: redirect + source: "/smart-wallet/transaction-automation" + destination: "/smart-accounts/permissions/transaction-automation" + - type: redirect + source: "/smart-wallet/wallet-connect" + destination: "/advanced/wallet-connect" + - type: redirect + source: "/smart-wallet/infra-fallbacks" + destination: "/advanced/fallback-providers" + - type: redirect + source: "/smart-wallet/code-examples" + destination: "/" + - type: redirect + source: "/smart-wallet/permissions/intro" + destination: "/smart-accounts/permissions/intro" + - type: redirect + source: "/smart-wallet/permissions/transaction-automation" + destination: "/smart-accounts/permissions/transaction-automation" + - type: redirect + source: "/smart-wallet/permissions/signers/ecdsa" + destination: "/smart-accounts/permissions/signers/ecdsa" + - type: redirect + source: "/smart-wallet/permissions/signers/passkeys" + destination: "/smart-accounts/permissions/signers/passkeys" + - type: redirect + source: "/smart-wallet/permissions/signers/multisig" + destination: "/smart-accounts/permissions/signers/multisig" + - type: redirect + source: "/smart-wallet/permissions/signers/build-your-own" + destination: "/smart-accounts/permissions/signers/build-your-own" + - type: redirect + source: "/smart-wallet/permissions/policies/sudo" + destination: "/smart-accounts/permissions/policies/sudo" + - type: redirect + source: "/smart-wallet/permissions/policies/call" + destination: "/smart-accounts/permissions/policies/call" + - type: redirect + source: "/smart-wallet/permissions/policies/gas" + destination: "/smart-accounts/permissions/policies/gas" + - type: redirect + source: "/smart-wallet/permissions/policies/signature" + destination: "/smart-accounts/permissions/policies/signature" + - type: redirect + source: "/smart-wallet/permissions/policies/rate-limit" + destination: "/smart-accounts/permissions/policies/rate-limit" + - type: redirect + source: "/smart-wallet/permissions/policies/timestamp" + destination: "/smart-accounts/permissions/policies/timestamp" + - type: redirect + source: "/smart-wallet/permissions/policies/build-your-own" + destination: "/smart-accounts/permissions/policies/build-your-own" + - type: redirect + source: "/smart-wallet/permissions/actions/build-your-own" + destination: "/smart-accounts/permissions/actions/build-your-own" + - type: redirect + source: "/smart-wallet/permissions/1-click-trading" + destination: "/smart-accounts/permissions/1-click-trading" + - type: redirect + source: "/smart-accounts/create-a-smart-account" + destination: "/onboarding/create-a-smart-account" + - type: redirect + source: "/smart-accounts/authentication/social-login" + destination: "/onboarding/social-login" + - type: redirect + source: "/smart-accounts/authentication/eoa" + destination: "/onboarding/eoa" + - type: redirect + source: "/smart-accounts/authentication/custom-signer" + destination: "/onboarding/custom-signer" + - type: redirect + source: "/smart-accounts/authentication/dynamic" + destination: "/onboarding/dynamic" + - type: redirect + source: "/smart-accounts/authentication/privy" + destination: "/onboarding/privy" + - type: redirect + source: "/smart-accounts/authentication/magic" + destination: "/onboarding/magic" + - type: redirect + source: "/smart-accounts/authentication/web3auth" + destination: "/onboarding/web3auth" + - type: redirect + source: "/smart-accounts/authentication/particle" + destination: "/onboarding/particle" + - type: redirect + source: "/smart-accounts/authentication/arcana" + destination: "/onboarding/arcana" + - type: redirect + source: "/smart-accounts/authentication/turnkey" + destination: "/onboarding/turnkey" + - type: redirect + source: "/smart-accounts/authentication/fireblocks" + destination: "/onboarding/fireblocks" + - type: redirect + source: "/smart-accounts/authentication/dfns" + destination: "/onboarding/dfns" + - type: redirect + source: "/smart-accounts/authentication/lit-protocol" + destination: "/onboarding/lit-protocol" + - type: redirect + source: "/smart-accounts/authentication/capsule" + destination: "/onboarding/capsule" + - type: redirect + source: "/smart-accounts/authentication/portal" + destination: "/onboarding/portal" + - type: redirect + source: "/smart-accounts/authentication/smart-wallet" + destination: "/onboarding/smart-wallet" + - type: redirect + source: "/smart-accounts/use-plugins/signers-intro" + destination: "/onboarding/auth-providers" + - type: redirect + source: "/smart-accounts/use-plugins/passkeys/overview" + destination: "/onboarding/passkeys/overview" + - type: redirect + source: "/smart-accounts/use-plugins/passkeys/tutorial" + destination: "/onboarding/passkeys/tutorial" + - type: redirect + source: "/smart-accounts/use-plugins/multisig" + destination: "/advanced/multisig" + - type: redirect + source: "/smart-accounts/account-recovery/sdk-recovery" + destination: "/advanced/account-recovery/sdk-recovery" + - type: redirect + source: "/smart-accounts/account-recovery/flow-intro" + destination: "/advanced/account-recovery/flow-intro" + - type: redirect + source: "/smart-accounts/account-recovery/flow-setup" + destination: "/advanced/account-recovery/flow-setup" + - type: redirect + source: "/smart-accounts/account-recovery/portal" + destination: "/advanced/account-recovery/portal" + - type: redirect + source: "/smart-accounts/eip-7702/quickstart" + destination: "/get-started/eip-7702/quickstart" + - type: redirect + source: "/cross-chain/smart-routing-address" + destination: "/onramp/smart-routing-address" + - type: redirect + source: "/cross-chain/chain-abstraction/overview" + destination: "/smart-accounts/chain-abstraction/overview" + - type: redirect + source: "/cross-chain/chain-abstraction/supported-base-tokens" + destination: "/smart-accounts/chain-abstraction/supported-base-tokens" + - type: redirect + source: "/cross-chain/chain-abstraction/supported-defi-tokens" + destination: "/smart-accounts/chain-abstraction/supported-defi-tokens" + - type: redirect + source: "/advanced/defi" + destination: "/smart-accounts/defi" + - type: redirect + source: "/advanced/multi-chain-signing" + destination: "/smart-accounts/multi-chain-signing" + - type: redirect + source: "/advanced/parallel-transactions" + destination: "/smart-accounts/parallel-transactions" + - type: redirect + source: "/advanced/deploy-contract" + destination: "/smart-accounts/deploy-contract" + - type: redirect + source: "/advanced/delegatecall" + destination: "/smart-accounts/delegatecall" + - type: redirect + source: "/resources/infrastructure/intro" + destination: "/api-and-toolings/infrastructure/intro" + - type: redirect + source: "/resources/infrastructure/gas-policies" + destination: "/api-and-toolings/infrastructure/gas-policies" + - type: redirect + source: "/resources/infrastructure/custom-gas-policies" + destination: "/api-and-toolings/infrastructure/custom-gas-policies" + - type: redirect + source: "/resources/infrastructure/rpcs" + destination: "/api-and-toolings/infrastructure/rpcs" + - type: redirect + source: "/resources/infrastructure/api" + destination: "/api-and-toolings/infrastructure/api" + - type: redirect + source: "/resources/infrastructure/choose-an-infra-provider" + destination: "/api-and-toolings/infrastructure/choose-an-infra-provider" + - type: redirect + source: "/resources/infrastructure/zerodev" + destination: "/api-and-toolings/infrastructure/zerodev" + - type: redirect + source: "/resources/infrastructure/pimlico" + destination: "/api-and-toolings/infrastructure/pimlico" + - type: redirect + source: "/resources/infrastructure/coinbase" + destination: "/api-and-toolings/infrastructure/coinbase" + - type: redirect + source: "/resources/presets/intro" + destination: "/api-and-toolings/presets/intro" + - type: redirect + source: "/resources/presets/zerodev" + destination: "/api-and-toolings/presets/zerodev" + - type: redirect + source: "/resources/tools/status" + destination: "/api-and-toolings/tools/status" + - type: redirect + source: "/resources/tools/debugger" + destination: "/api-and-toolings/tools/debugger" + - type: redirect + source: "/resources/faqs/chains" + destination: "/api-and-toolings/faqs/chains" + - type: redirect + source: "/resources/faqs/audits" + destination: "/api-and-toolings/faqs/audits" + - type: redirect + source: "/resources/faqs/debug-userop" + destination: "/api-and-toolings/faqs/debug-userop" + - type: redirect + source: "/resources/faqs/use-with-ethers" + destination: "/api-and-toolings/faqs/use-with-ethers" + - type: redirect + source: "/resources/faqs/use-with-gelato" + destination: "/api-and-toolings/faqs/use-with-gelato" + - type: redirect + source: "/resources/faqs/use-with-react-native" + destination: "/api-and-toolings/faqs/use-with-react-native" + # <<< END GENERATED REDIRECTS + # ---- hand-maintained; keep BELOW the generated redirects (first match wins) ---- + # Legacy Magic Account subpaths (the exact /magic-account is in the block above). + - type: redirect + source: "/magic-account/*" + destination: "/smart-accounts/chain-abstraction/overview" + # SPA fallbacks: serve the app shell for any unmapped legacy path under these + # prefixes so it gets the in-app 404 rather than Render's raw 404. Keep last. + - type: rewrite + source: "/sdk/*" + destination: "/index.html" + - type: rewrite + source: "/sdk" + destination: "/index.html" + - type: rewrite + source: "/meta-infra/*" + destination: "/index.html" + - type: rewrite + source: "/meta-infra" + destination: "/index.html" + - type: rewrite + source: "/recovery-flow/*" + destination: "/index.html" + - type: rewrite + source: "/recovery-flow" + destination: "/index.html" + - type: rewrite + source: "/blog/*" + destination: "/index.html" + - type: rewrite + source: "/blog" + destination: "/index.html" + - type: rewrite + source: "/react/*" + destination: "/index.html" + - type: rewrite + source: "/react" + destination: "/index.html" + - type: rewrite + source: "/smart-wallet/*" + destination: "/index.html" + - type: rewrite + source: "/smart-wallet" + destination: "/index.html" diff --git a/scripts/sync-render-redirects.mjs b/scripts/sync-render-redirects.mjs new file mode 100644 index 0000000..b6cc242 --- /dev/null +++ b/scripts/sync-render-redirects.mjs @@ -0,0 +1,68 @@ +/** + * sync-render-redirects — splice redirects.config.js into render.yaml. + * + * The list in redirects.config.js is the single source of truth. Vocs only + * applies it in local dev (via the middleware in vocs.config.tsx), so this + * script mirrors it into render.yaml so Render serves the redirects in + * production. Render reads render.yaml at the start of a deployment (before the + * build command runs), so the generated file is committed. + * + * render.yaml is hand-maintained: it holds the static-site service definition + * (name/build/domains) and the broad SPA-fallback rewrites that must sit BELOW + * the redirects. So rather than regenerating the whole file, we replace only the + * lines between the BEGIN/END markers, leaving the rest untouched. This mirrors + * the OffchainLabs/arbitrum-docs sentinel-splice approach. + * + * Run with `npm run sync-redirects` (also runs on `npm run build` via prebuild). + */ + +import { readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { redirects } from "../redirects.config.js"; + +const root = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); +const renderPath = path.join(root, "render.yaml"); + +const BEGIN = "# >>> BEGIN GENERATED REDIRECTS"; +const END = "# <<< END GENERATED REDIRECTS"; + +const yaml = await readFile(renderPath, "utf8"); +const lines = yaml.split("\n"); + +const beginIdx = lines.findIndex((l) => l.includes(BEGIN)); +const endIdx = lines.findIndex((l) => l.includes(END)); +if (beginIdx === -1 || endIdx === -1 || endIdx < beginIdx) { + throw new Error( + `sync-render-redirects: could not find BEGIN/END markers in render.yaml`, + ); +} + +// Indent the generated list items to match the BEGIN marker's column. Render +// redirects are always 301 (the type isn't configurable), so there's no +// permanent/temporary flag to emit. Values are double-quoted (JSON.stringify) +// so any future path with YAML-special characters stays safe. +// +// Format note: block style + double-quoted scalars is exactly Prettier's +// default YAML output, so the generated render.yaml stays prettier-clean (no +// .prettierignore needed, `npm run format` leaves it untouched). Verified +// against prettier 3.5.3–3.8.x. Don't switch this to flow style (`{ type: ..., +// source: ... }`) — Prettier would reformat it and fight the sync check. +const indent = lines[beginIdx].match(/^\s*/)[0]; +const block = redirects.flatMap(({ from, to }) => [ + `${indent}- type: redirect`, + `${indent} source: ${JSON.stringify(from)}`, + `${indent} destination: ${JSON.stringify(to)}`, +]); + +const next = [ + ...lines.slice(0, beginIdx + 1), + ...block, + ...lines.slice(endIdx), +]; + +await writeFile(renderPath, next.join("\n")); +console.log( + `sync-render-redirects: wrote ${redirects.length} redirects into render.yaml.`, +); diff --git a/scripts/sync-vercel-redirects.mjs b/scripts/sync-vercel-redirects.mjs deleted file mode 100644 index 1ad6f66..0000000 --- a/scripts/sync-vercel-redirects.mjs +++ /dev/null @@ -1,45 +0,0 @@ -/** - * sync-vercel-redirects — mirror redirects.config.js into vercel.json. - * - * The list in redirects.config.js is the single source of truth. Vocs only - * applies it in local dev (via the middleware in vocs.config.tsx), so this - * script mirrors it into vercel.json so Vercel serves the redirects in - * production. Vercel reads vercel.json at the start of a deployment (before the - * build command runs), so the generated file is committed. - * - * Run with `npm run sync-redirects` (also runs on `npm run build` via prebuild). - * - * Patterned on OffchainLabs/arbitrum-docs (scripts/sync-vercel-redirects.ts). - * That repo splices a sentinel-bounded block into a hand-maintained vercel.json - * to coexist with manual entries; ZeroDev's vercel.json is fully generated, so - * here we (re)write it wholesale. Written as `.mjs` because this repo has no - * `tsx`; it imports the `.js` config natively. - */ - -import { writeFile } from "node:fs/promises"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -import { redirects } from "../redirects.config.js"; - -const root = path.join(path.dirname(fileURLToPath(import.meta.url)), ".."); -const vercelPath = path.join(root, "vercel.json"); - -// permanent: false -> 307, matching the arbitrum-docs convention. Temporary -// redirects aren't cached aggressively by browsers/crawlers, which keeps future -// doc reorganizations easy to revert. -const json = - JSON.stringify( - { - redirects: redirects.map(({ from, to }) => ({ - source: from, - destination: to, - permanent: false, - })), - }, - null, - 2, - ) + "\n"; - -await writeFile(vercelPath, json); -console.log(`sync-redirects: wrote ${redirects.length} redirects into vercel.json.`); diff --git a/vercel.json b/vercel.json deleted file mode 100644 index 97fddea..0000000 --- a/vercel.json +++ /dev/null @@ -1,1009 +0,0 @@ -{ - "redirects": [ - { - "source": "/sdk/getting-started/quickstart", - "destination": "/get-started/quickstart", - "permanent": false - }, - { - "source": "/sdk/getting-started/tutorial", - "destination": "/get-started/quickstart", - "permanent": false - }, - { - "source": "/sdk/getting-started/tutorial-passkeys", - "destination": "/onboarding/passkeys/tutorial", - "permanent": false - }, - { - "source": "/sdk/getting-started/quickstart-7702", - "destination": "/get-started/eip-7702/quickstart", - "permanent": false - }, - { - "source": "/sdk/getting-started/quickstart-agentkit", - "destination": "/smart-accounts/permissions/agentkit", - "permanent": false - }, - { - "source": "/sdk/getting-started/migration", - "destination": "/advanced/migration", - "permanent": false - }, - { - "source": "/sdk/core-api/create-account", - "destination": "/onboarding/create-a-smart-account", - "permanent": false - }, - { - "source": "/sdk/core-api/using-plugins", - "destination": "/smart-accounts/use-plugins/overview", - "permanent": false - }, - { - "source": "/sdk/core-api/send-transactions", - "destination": "/smart-accounts/send-transactions", - "permanent": false - }, - { - "source": "/sdk/core-api/batch-transactions", - "destination": "/smart-accounts/batch-transactions", - "permanent": false - }, - { - "source": "/sdk/core-api/sponsor-gas", - "destination": "/smart-accounts/sponsor-gas/evm", - "permanent": false - }, - { - "source": "/sdk/core-api/pay-gas-with-erc20s", - "destination": "/smart-accounts/pay-gas-with-erc20s", - "permanent": false - }, - { - "source": "/sdk/core-api/sign-and-verify", - "destination": "/smart-accounts/sign-and-verify", - "permanent": false - }, - { - "source": "/sdk/core-api/deploy-contract", - "destination": "/smart-accounts/deploy-contract", - "permanent": false - }, - { - "source": "/sdk/core-api/delegatecall", - "destination": "/smart-accounts/delegatecall", - "permanent": false - }, - { - "source": "/sdk/core-api/status", - "destination": "/api-and-toolings/tools/status", - "permanent": false - }, - { - "source": "/sdk/core-api/debugger", - "destination": "/api-and-toolings/tools/debugger", - "permanent": false - }, - { - "source": "/sdk/advanced/chain-abstraction", - "destination": "/smart-accounts/chain-abstraction/overview", - "permanent": false - }, - { - "source": "/sdk/advanced/passkeys", - "destination": "/onboarding/passkeys/overview", - "permanent": false - }, - { - "source": "/sdk/advanced/multisig", - "destination": "/advanced/multisig", - "permanent": false - }, - { - "source": "/sdk/advanced/social-login", - "destination": "/onboarding/social-login", - "permanent": false - }, - { - "source": "/sdk/advanced/session-keys", - "destination": "/smart-accounts/permissions/session-keys", - "permanent": false - }, - { - "source": "/sdk/advanced/recovery", - "destination": "/advanced/account-recovery/sdk-recovery", - "permanent": false - }, - { - "source": "/sdk/advanced/multi-chain-signing", - "destination": "/smart-accounts/multi-chain-signing", - "permanent": false - }, - { - "source": "/sdk/advanced/key-storage", - "destination": "/advanced/key-storage", - "permanent": false - }, - { - "source": "/sdk/advanced/defi", - "destination": "/smart-accounts/defi", - "permanent": false - }, - { - "source": "/sdk/advanced/parallel-orders", - "destination": "/smart-accounts/parallel-transactions", - "permanent": false - }, - { - "source": "/sdk/advanced/wallet-connect", - "destination": "/advanced/wallet-connect", - "permanent": false - }, - { - "source": "/sdk/advanced/fallback-providers", - "destination": "/advanced/fallback-providers", - "permanent": false - }, - { - "source": "/sdk/advanced/run-solidity-code-on-init", - "destination": "/advanced/track-deployed-accounts", - "permanent": false - }, - { - "source": "/sdk/advanced/upgrade-kernel", - "destination": "/advanced/upgrade-kernel", - "permanent": false - }, - { - "source": "/sdk/advanced/go-sdk", - "destination": "/get-started/sdks/server-side/go", - "permanent": false - }, - { - "source": "/advanced/go-sdk", - "destination": "/get-started/sdks/server-side/go", - "permanent": false - }, - { - "source": "/sdk/advanced/userop-builder-api", - "destination": "/advanced/userop-builder-api", - "permanent": false - }, - { - "source": "/sdk/advanced/supported-base-tokens", - "destination": "/smart-accounts/chain-abstraction/supported-base-tokens", - "permanent": false - }, - { - "source": "/sdk/advanced/supported-defi-tokens", - "destination": "/smart-accounts/chain-abstraction/supported-defi-tokens", - "permanent": false - }, - { - "source": "/sdk/permissions/intro", - "destination": "/smart-accounts/permissions/intro", - "permanent": false - }, - { - "source": "/sdk/permissions/transaction-automation", - "destination": "/smart-accounts/permissions/transaction-automation", - "permanent": false - }, - { - "source": "/sdk/permissions/install-with-init-config", - "destination": "/smart-accounts/permissions/install-with-init-config", - "permanent": false - }, - { - "source": "/sdk/permissions/1-click-trading", - "destination": "/smart-accounts/permissions/1-click-trading", - "permanent": false - }, - { - "source": "/sdk/permissions/signers/ecdsa", - "destination": "/smart-accounts/permissions/signers/ecdsa", - "permanent": false - }, - { - "source": "/sdk/permissions/signers/passkeys", - "destination": "/smart-accounts/permissions/signers/passkeys", - "permanent": false - }, - { - "source": "/sdk/permissions/signers/multisig", - "destination": "/smart-accounts/permissions/signers/multisig", - "permanent": false - }, - { - "source": "/sdk/permissions/signers/build-your-own", - "destination": "/smart-accounts/permissions/signers/build-your-own", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/sudo", - "destination": "/smart-accounts/permissions/policies/sudo", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/call", - "destination": "/smart-accounts/permissions/policies/call", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/gas", - "destination": "/smart-accounts/permissions/policies/gas", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/signature", - "destination": "/smart-accounts/permissions/policies/signature", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/rate-limit", - "destination": "/smart-accounts/permissions/policies/rate-limit", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/timestamp", - "destination": "/smart-accounts/permissions/policies/timestamp", - "permanent": false - }, - { - "source": "/sdk/permissions/policies/build-your-own", - "destination": "/smart-accounts/permissions/policies/build-your-own", - "permanent": false - }, - { - "source": "/sdk/permissions/actions/build-your-own", - "destination": "/smart-accounts/permissions/actions/build-your-own", - "permanent": false - }, - { - "source": "/sdk/signers/intro", - "destination": "/onboarding/auth-providers", - "permanent": false - }, - { - "source": "/sdk/signers/dynamic", - "destination": "/onboarding/dynamic", - "permanent": false - }, - { - "source": "/sdk/signers/privy", - "destination": "/onboarding/privy", - "permanent": false - }, - { - "source": "/sdk/signers/magic", - "destination": "/onboarding/magic", - "permanent": false - }, - { - "source": "/sdk/signers/web3auth", - "destination": "/onboarding/web3auth", - "permanent": false - }, - { - "source": "/sdk/signers/smart-wallet", - "destination": "/onboarding/smart-wallet", - "permanent": false - }, - { - "source": "/sdk/signers/portal", - "destination": "/onboarding/portal", - "permanent": false - }, - { - "source": "/sdk/signers/turnkey", - "destination": "/onboarding/turnkey", - "permanent": false - }, - { - "source": "/sdk/signers/fireblocks", - "destination": "/onboarding/fireblocks", - "permanent": false - }, - { - "source": "/sdk/signers/capsule", - "destination": "/onboarding/capsule", - "permanent": false - }, - { - "source": "/sdk/signers/lit-protocol", - "destination": "/onboarding/lit-protocol", - "permanent": false - }, - { - "source": "/sdk/signers/particle", - "destination": "/onboarding/particle", - "permanent": false - }, - { - "source": "/sdk/signers/dfns", - "destination": "/onboarding/dfns", - "permanent": false - }, - { - "source": "/sdk/signers/arcana", - "destination": "/onboarding/arcana", - "permanent": false - }, - { - "source": "/sdk/signers/eoa", - "destination": "/onboarding/eoa", - "permanent": false - }, - { - "source": "/sdk/signers/custom-signer", - "destination": "/onboarding/custom-signer", - "permanent": false - }, - { - "source": "/sdk/solana/sponsor-gas", - "destination": "/smart-accounts/sponsor-gas/solana", - "permanent": false - }, - { - "source": "/sdk/infra/intro", - "destination": "/api-and-toolings/infrastructure/choose-an-infra-provider", - "permanent": false - }, - { - "source": "/sdk/infra/zerodev", - "destination": "/api-and-toolings/infrastructure/zerodev", - "permanent": false - }, - { - "source": "/sdk/infra/pimlico", - "destination": "/api-and-toolings/infrastructure/pimlico", - "permanent": false - }, - { - "source": "/sdk/infra/coinbase", - "destination": "/api-and-toolings/infrastructure/coinbase", - "permanent": false - }, - { - "source": "/sdk/presets/intro", - "destination": "/api-and-toolings/presets/intro", - "permanent": false - }, - { - "source": "/sdk/presets/zerodev", - "destination": "/api-and-toolings/presets/zerodev", - "permanent": false - }, - { - "source": "/sdk/faqs/chains", - "destination": "/api-and-toolings/faqs/chains", - "permanent": false - }, - { - "source": "/sdk/faqs/audits", - "destination": "/api-and-toolings/faqs/audits", - "permanent": false - }, - { - "source": "/sdk/faqs/debug-userop", - "destination": "/api-and-toolings/faqs/debug-userop", - "permanent": false - }, - { - "source": "/sdk/faqs/use-with-ethers", - "destination": "/api-and-toolings/faqs/use-with-ethers", - "permanent": false - }, - { - "source": "/sdk/faqs/use-with-gelato", - "destination": "/api-and-toolings/faqs/use-with-gelato", - "permanent": false - }, - { - "source": "/sdk/faqs/use-with-react-native", - "destination": "/api-and-toolings/faqs/use-with-react-native", - "permanent": false - }, - { - "source": "/meta-infra/intro", - "destination": "/api-and-toolings/infrastructure/intro", - "permanent": false - }, - { - "source": "/meta-infra/gas-policies", - "destination": "/api-and-toolings/infrastructure/gas-policies", - "permanent": false - }, - { - "source": "/meta-infra/custom-gas-policies", - "destination": "/api-and-toolings/infrastructure/custom-gas-policies", - "permanent": false - }, - { - "source": "/meta-infra/rpcs", - "destination": "/api-and-toolings/infrastructure/rpcs", - "permanent": false - }, - { - "source": "/meta-infra/api", - "destination": "/api-and-toolings/infrastructure/api", - "permanent": false - }, - { - "source": "/recovery-flow/intro", - "destination": "/advanced/account-recovery/flow-intro", - "permanent": false - }, - { - "source": "/recovery-flow/setup", - "destination": "/advanced/account-recovery/flow-setup", - "permanent": false - }, - { - "source": "/recovery-flow/portal", - "destination": "/advanced/account-recovery/portal", - "permanent": false - }, - { - "source": "/smart-routing-address", - "destination": "/onramp/smart-routing-address", - "permanent": false - }, - { - "source": "/global-address", - "destination": "/onramp/smart-routing-address", - "permanent": false - }, - { - "source": "/react/getting-started", - "destination": "/advanced/react-hooks/getting-started", - "permanent": false - }, - { - "source": "/react/use-balance", - "destination": "/advanced/react-hooks/use-balance", - "permanent": false - }, - { - "source": "/react/use-chainid", - "destination": "/advanced/react-hooks/use-chainid", - "permanent": false - }, - { - "source": "/react/use-chains", - "destination": "/advanced/react-hooks/use-chains", - "permanent": false - }, - { - "source": "/react/use-create-basic-session", - "destination": "/advanced/react-hooks/use-create-basic-session", - "permanent": false - }, - { - "source": "/react/use-create-kernelclient-eoa", - "destination": "/advanced/react-hooks/use-create-kernelclient-eoa", - "permanent": false - }, - { - "source": "/react/use-create-kernelclient-passkey", - "destination": "/advanced/react-hooks/use-create-kernelclient-passkey", - "permanent": false - }, - { - "source": "/react/use-create-kernelclient-social", - "destination": "/advanced/react-hooks/use-create-kernelclient-social", - "permanent": false - }, - { - "source": "/react/use-create-session", - "destination": "/advanced/react-hooks/use-create-session", - "permanent": false - }, - { - "source": "/react/use-disconnect-kernelclient", - "destination": "/advanced/react-hooks/use-disconnect-kernelclient", - "permanent": false - }, - { - "source": "/react/use-kernelclient", - "destination": "/advanced/react-hooks/use-kernelclient", - "permanent": false - }, - { - "source": "/react/use-send-transaction", - "destination": "/advanced/react-hooks/use-send-transaction", - "permanent": false - }, - { - "source": "/react/use-send-transaction-with-session", - "destination": "/advanced/react-hooks/use-send-transaction-with-session", - "permanent": false - }, - { - "source": "/react/use-send-useroperation", - "destination": "/advanced/react-hooks/use-send-useroperation", - "permanent": false - }, - { - "source": "/react/use-send-useroperation-with-session", - "destination": "/advanced/react-hooks/use-send-useroperation-with-session", - "permanent": false - }, - { - "source": "/react/use-sessions", - "destination": "/advanced/react-hooks/use-sessions", - "permanent": false - }, - { - "source": "/react/use-session-kernelclient", - "destination": "/advanced/react-hooks/use-session-kernelclient", - "permanent": false - }, - { - "source": "/react/use-set-kernelclient", - "destination": "/advanced/react-hooks/use-set-kernelclient", - "permanent": false - }, - { - "source": "/react/use-switch-chain", - "destination": "/advanced/react-hooks/use-switch-chain", - "permanent": false - }, - { - "source": "/react/use-wallet-connect", - "destination": "/advanced/react-hooks/use-wallet-connect", - "permanent": false - }, - { - "source": "/smart-wallet/which-sdk", - "destination": "/onboarding/create-a-smart-account", - "permanent": false - }, - { - "source": "/smart-wallet/quickstart-core", - "destination": "/get-started/quickstart", - "permanent": false - }, - { - "source": "/smart-wallet/quickstart-react", - "destination": "/get-started/quickstart", - "permanent": false - }, - { - "source": "/smart-wallet/quickstart-capabilities", - "destination": "/get-started/quickstart", - "permanent": false - }, - { - "source": "/smart-wallet/creating-wallets", - "destination": "/onboarding/create-a-smart-account", - "permanent": false - }, - { - "source": "/smart-wallet/setting-up-zerodev-projects", - "destination": "/", - "permanent": false - }, - { - "source": "/smart-wallet/sending-transactions", - "destination": "/smart-accounts/send-transactions", - "permanent": false - }, - { - "source": "/smart-wallet/batching-transactions", - "destination": "/smart-accounts/batch-transactions", - "permanent": false - }, - { - "source": "/smart-wallet/pay-gas-in-erc20s", - "destination": "/smart-accounts/pay-gas-with-erc20s", - "permanent": false - }, - { - "source": "/smart-wallet/sponsoring-gas", - "destination": "/smart-accounts/sponsor-gas/evm", - "permanent": false - }, - { - "source": "/smart-wallet/delegatecall", - "destination": "/smart-accounts/delegatecall", - "permanent": false - }, - { - "source": "/smart-wallet/multisig", - "destination": "/advanced/multisig", - "permanent": false - }, - { - "source": "/smart-wallet/account-recovery", - "destination": "/advanced/account-recovery/sdk-recovery", - "permanent": false - }, - { - "source": "/smart-wallet/importing-assets", - "destination": "/onboarding/create-a-smart-account", - "permanent": false - }, - { - "source": "/smart-wallet/defi-integrations", - "destination": "/smart-accounts/defi", - "permanent": false - }, - { - "source": "/smart-wallet/one-click-trading", - "destination": "/smart-accounts/permissions/transaction-automation", - "permanent": false - }, - { - "source": "/smart-wallet/parallel-transactions", - "destination": "/smart-accounts/parallel-transactions", - "permanent": false - }, - { - "source": "/smart-wallet/transaction-automation", - "destination": "/smart-accounts/permissions/transaction-automation", - "permanent": false - }, - { - "source": "/smart-wallet/wallet-connect", - "destination": "/advanced/wallet-connect", - "permanent": false - }, - { - "source": "/smart-wallet/infra-fallbacks", - "destination": "/advanced/fallback-providers", - "permanent": false - }, - { - "source": "/smart-wallet/code-examples", - "destination": "/", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/intro", - "destination": "/smart-accounts/permissions/intro", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/transaction-automation", - "destination": "/smart-accounts/permissions/transaction-automation", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/signers/ecdsa", - "destination": "/smart-accounts/permissions/signers/ecdsa", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/signers/passkeys", - "destination": "/smart-accounts/permissions/signers/passkeys", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/signers/multisig", - "destination": "/smart-accounts/permissions/signers/multisig", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/signers/build-your-own", - "destination": "/smart-accounts/permissions/signers/build-your-own", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/sudo", - "destination": "/smart-accounts/permissions/policies/sudo", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/call", - "destination": "/smart-accounts/permissions/policies/call", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/gas", - "destination": "/smart-accounts/permissions/policies/gas", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/signature", - "destination": "/smart-accounts/permissions/policies/signature", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/rate-limit", - "destination": "/smart-accounts/permissions/policies/rate-limit", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/timestamp", - "destination": "/smart-accounts/permissions/policies/timestamp", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/policies/build-your-own", - "destination": "/smart-accounts/permissions/policies/build-your-own", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/actions/build-your-own", - "destination": "/smart-accounts/permissions/actions/build-your-own", - "permanent": false - }, - { - "source": "/smart-wallet/permissions/1-click-trading", - "destination": "/smart-accounts/permissions/1-click-trading", - "permanent": false - }, - { - "source": "/smart-accounts/create-a-smart-account", - "destination": "/onboarding/create-a-smart-account", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/social-login", - "destination": "/onboarding/social-login", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/eoa", - "destination": "/onboarding/eoa", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/custom-signer", - "destination": "/onboarding/custom-signer", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/dynamic", - "destination": "/onboarding/dynamic", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/privy", - "destination": "/onboarding/privy", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/magic", - "destination": "/onboarding/magic", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/web3auth", - "destination": "/onboarding/web3auth", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/particle", - "destination": "/onboarding/particle", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/arcana", - "destination": "/onboarding/arcana", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/turnkey", - "destination": "/onboarding/turnkey", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/fireblocks", - "destination": "/onboarding/fireblocks", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/dfns", - "destination": "/onboarding/dfns", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/lit-protocol", - "destination": "/onboarding/lit-protocol", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/capsule", - "destination": "/onboarding/capsule", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/portal", - "destination": "/onboarding/portal", - "permanent": false - }, - { - "source": "/smart-accounts/authentication/smart-wallet", - "destination": "/onboarding/smart-wallet", - "permanent": false - }, - { - "source": "/smart-accounts/use-plugins/signers-intro", - "destination": "/onboarding/auth-providers", - "permanent": false - }, - { - "source": "/smart-accounts/use-plugins/passkeys/overview", - "destination": "/onboarding/passkeys/overview", - "permanent": false - }, - { - "source": "/smart-accounts/use-plugins/passkeys/tutorial", - "destination": "/onboarding/passkeys/tutorial", - "permanent": false - }, - { - "source": "/smart-accounts/use-plugins/multisig", - "destination": "/advanced/multisig", - "permanent": false - }, - { - "source": "/smart-accounts/account-recovery/sdk-recovery", - "destination": "/advanced/account-recovery/sdk-recovery", - "permanent": false - }, - { - "source": "/smart-accounts/account-recovery/flow-intro", - "destination": "/advanced/account-recovery/flow-intro", - "permanent": false - }, - { - "source": "/smart-accounts/account-recovery/flow-setup", - "destination": "/advanced/account-recovery/flow-setup", - "permanent": false - }, - { - "source": "/smart-accounts/account-recovery/portal", - "destination": "/advanced/account-recovery/portal", - "permanent": false - }, - { - "source": "/smart-accounts/eip-7702/quickstart", - "destination": "/get-started/eip-7702/quickstart", - "permanent": false - }, - { - "source": "/cross-chain/smart-routing-address", - "destination": "/onramp/smart-routing-address", - "permanent": false - }, - { - "source": "/cross-chain/chain-abstraction/overview", - "destination": "/smart-accounts/chain-abstraction/overview", - "permanent": false - }, - { - "source": "/cross-chain/chain-abstraction/supported-base-tokens", - "destination": "/smart-accounts/chain-abstraction/supported-base-tokens", - "permanent": false - }, - { - "source": "/cross-chain/chain-abstraction/supported-defi-tokens", - "destination": "/smart-accounts/chain-abstraction/supported-defi-tokens", - "permanent": false - }, - { - "source": "/advanced/defi", - "destination": "/smart-accounts/defi", - "permanent": false - }, - { - "source": "/advanced/multi-chain-signing", - "destination": "/smart-accounts/multi-chain-signing", - "permanent": false - }, - { - "source": "/advanced/parallel-transactions", - "destination": "/smart-accounts/parallel-transactions", - "permanent": false - }, - { - "source": "/advanced/deploy-contract", - "destination": "/smart-accounts/deploy-contract", - "permanent": false - }, - { - "source": "/advanced/delegatecall", - "destination": "/smart-accounts/delegatecall", - "permanent": false - }, - { - "source": "/resources/infrastructure/intro", - "destination": "/api-and-toolings/infrastructure/intro", - "permanent": false - }, - { - "source": "/resources/infrastructure/gas-policies", - "destination": "/api-and-toolings/infrastructure/gas-policies", - "permanent": false - }, - { - "source": "/resources/infrastructure/custom-gas-policies", - "destination": "/api-and-toolings/infrastructure/custom-gas-policies", - "permanent": false - }, - { - "source": "/resources/infrastructure/rpcs", - "destination": "/api-and-toolings/infrastructure/rpcs", - "permanent": false - }, - { - "source": "/resources/infrastructure/api", - "destination": "/api-and-toolings/infrastructure/api", - "permanent": false - }, - { - "source": "/resources/infrastructure/choose-an-infra-provider", - "destination": "/api-and-toolings/infrastructure/choose-an-infra-provider", - "permanent": false - }, - { - "source": "/resources/infrastructure/zerodev", - "destination": "/api-and-toolings/infrastructure/zerodev", - "permanent": false - }, - { - "source": "/resources/infrastructure/pimlico", - "destination": "/api-and-toolings/infrastructure/pimlico", - "permanent": false - }, - { - "source": "/resources/infrastructure/coinbase", - "destination": "/api-and-toolings/infrastructure/coinbase", - "permanent": false - }, - { - "source": "/resources/presets/intro", - "destination": "/api-and-toolings/presets/intro", - "permanent": false - }, - { - "source": "/resources/presets/zerodev", - "destination": "/api-and-toolings/presets/zerodev", - "permanent": false - }, - { - "source": "/resources/tools/status", - "destination": "/api-and-toolings/tools/status", - "permanent": false - }, - { - "source": "/resources/tools/debugger", - "destination": "/api-and-toolings/tools/debugger", - "permanent": false - }, - { - "source": "/resources/faqs/chains", - "destination": "/api-and-toolings/faqs/chains", - "permanent": false - }, - { - "source": "/resources/faqs/audits", - "destination": "/api-and-toolings/faqs/audits", - "permanent": false - }, - { - "source": "/resources/faqs/debug-userop", - "destination": "/api-and-toolings/faqs/debug-userop", - "permanent": false - }, - { - "source": "/resources/faqs/use-with-ethers", - "destination": "/api-and-toolings/faqs/use-with-ethers", - "permanent": false - }, - { - "source": "/resources/faqs/use-with-gelato", - "destination": "/api-and-toolings/faqs/use-with-gelato", - "permanent": false - }, - { - "source": "/resources/faqs/use-with-react-native", - "destination": "/api-and-toolings/faqs/use-with-react-native", - "permanent": false - } - ] -} diff --git a/vocs.config.tsx b/vocs.config.tsx index 5340d95..33119cd 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -5,8 +5,8 @@ import { redirects } from "./redirects.config.js"; dotenv.config(); // Lookup table for the dev-server redirect middleware below. The redirect list -// lives in redirects.config.js (single source of truth) and is mirrored into -// vercel.json for production by `npm run sync-redirects`. +// lives in redirects.config.js (single source of truth) and is spliced into +// render.yaml for production by `npm run sync-redirects`. const REDIRECT_MAP: Record = Object.fromEntries( redirects.map((r) => [r.from, r.to]), );