Deployment Architecture
How the deployment pipeline actually works under the hood
Deployment Architecture
Deploying this stack used to be a multi-step nightmare. You have Convex (backend), Cloudflare Workers (the AI agent), and Vercel (the frontend), and they all need each other's URLs and secrets. To fix this, we unified everything into a single script that orchestrates the entire deployment from Vercel.
The Problem (The "Why")
We have a circular dependency of environment variables:
- The Agent (Cloudflare) needs the
CONVEX_URLto talk to the database. - The Frontend (Vercel) needs both the
VITE_CONVEX_URLand theVITE_AGENT_URLto work. - We also need shared secrets (like
EXTERNAL_TOKEN,BETTER_AUTH_SECRET, andJWKS) securely synced between Convex and the Agent without manual copy-pasting.
If you deploy them separately, you're constantly waiting for one to finish just to copy a URL into the environment variables of the other. For PR preview environments, this is literally impossible to do manually.
The Solution: scripts/deploy.ts (The "How")
We wrote a monolithic script (scripts/deploy.ts) that Vercel runs as its Build Command. Here is exactly what happens under the hood when Vercel triggers a build:
-
Vercel starts the build
Vercel spins up and runsbun scripts/deploy.ts. -
Convex Deployment & URL Provisioning
The script immediately fires offbunx convex deploy --cmd "bun scripts/deploy.ts --continue".
This tells Convex: "Deploy the backend, figure out theCONVEX_URL(whether it's prod or a new PR preview), and then pass that URL back to me by running this--continuecommand." -
Secret Generation & Syncing
Inside the--continueblock, the script generates secure secrets on the fly (EXTERNAL_TOKEN,BETTER_AUTH_SECRET,JWKS,ALCHEMY_PASSWORD) and pushes them directly into your Convex environment. No manual.envjuggling required. It also syncs any other required backend environment variables over to Convex. -
Agent Deployment (Alchemy)
Now that we have theCONVEX_URLand secrets set up, the script deploys the Cloudflare Worker agent via Alchemy (bunx alchemy deploy). It parses the CLI output to grab the resultingALCHEMY_WORKER_URL. -
Frontend Build
Finally, we have all the pieces. The script injectsVITE_CONVEX_URLandVITE_AGENT_URLinto the current process environment and runs the Vite build for the TanStack Start frontend (bunx vite build). It then moves the Nitro build output into Vercel's.vercel/outputfolder so Vercel can serve it.
What You Need To Do
Literally just push to Vercel.
Set your Vercel Build Command to:
bun scripts/deploy.tsSet these environment variables in Vercel:
CONVEX_DEPLOY_KEY(Get this from your Convex dashboard settings)CLOUDFLARE_API_TOKEN(For the agent deployment via Alchemy)CLOUDFLARE_ACCOUNT_ID(For the agent deployment via Alchemy)
That's it. Every PR gets a full-stack preview environment (Convex preview + fresh Cloudflare worker + Vercel preview URL), and pushing to main deploys straight to production.