Deploying a Weaverse Theme to Cloudflare Workers
What your theme ships with today
Before changing anything, it helps to see exactly what you are migrating away from. In the current Pilot theme:
Nothing below is pre-configured. Treat each step as a change you are making to your own fork.
Prerequisites
- Node.js:
>=22.12.0(this is theengines.noderequirement of the current Pilot theme) - Cloudflare account: sign up at cloudflare.com
- Shopify store: active store with Storefront API access
- Weaverse project: a configured project ID for your storefront
- A working Oxygen build first — run
npm run buildand confirm it succeeds before you start migrating
Quick Flow
1
Add the Cloudflare dependencies
npm i -D wrangler @cloudflare/vite-plugin2
Swap the Oxygen Vite plugin for the Cloudflare plugin
Edit
vite.config.ts.3
Create wrangler.json
Point
main at your worker entry and enable nodejs_compat.4
Add your own npm scripts
deploy, cf-dev, cf-typegen, check — none of these exist yet.5
Upload secrets and deploy
npx wrangler secret bulk .dev.vars then npx wrangler deploy.1. Install the Cloudflare toolchain
@cloudflare/vite-plugin builds your app for the workerd runtime as Cloudflare runs it. wrangler is the CLI used to configure, preview, and deploy the worker.
2. Update vite.config.ts
Your theme currently registers the Oxygen plugin. Replace it with the Cloudflare plugin — running both is not supported, since each one owns the SSR environment.
vite.config.ts
Keep
assetsInlineLimit: 0. Pilot sets this so no asset is inlined as a data URI, which keeps the storefront compatible with a strict Content-Security-Policy. See Content Security Policy.oxygen() also removes the local Oxygen preview that npm run dev and npm run preview rely on. Decide up front whether you are keeping an Oxygen path for local development or moving entirely to wrangler dev.
3. Review your worker entry
server.ts already exports a module-format worker — a default object with an async fetch(request, env, executionContext) method — which is the shape Cloudflare Workers expects. What is not portable is the Oxygen-specific plumbing around it:
createRequestHandleris imported from@shopify/hydrogen/oxygenenv.d.tspulls worker globals from@shopify/oxygen-workers-typescreateHydrogenRouterContextbuilds the Hydrogen context from Oxygen’senvbinding shape
4. Create wrangler.json
This file does not exist in the theme — create it in the project root:
wrangler.json
5. Configure environment variables
Wrangler reads local development values from.dev.vars. Create one from your existing .env values:
.dev.vars
JUDGEME_PRIVATE_API_TOKEN, KLAVIYO_PRIVATE_API_TOKEN, PUBLIC_GOOGLE_GTM_ID, and so on) — see .env.example in your theme for the authoritative list.
Upload them as Worker secrets:
Setting
NODE_ENV=production prevents Hydrogen from injecting its development-only virtual routes into the production build.6. Add npm scripts
None of these scripts exist in the theme. Add the ones you need topackage.json:
package.json
7. Deploy
https://your-project-name.<subdomain>.workers.dev.
Post-Deployment
Stream logs
Custom domain
- Open the Cloudflare Dashboard
- Workers & Pages → select your worker
- Settings → Domains & Routes
- Add your domain and configure routes
Git-connected builds
- Workers & Pages → your worker → Settings → Builds
- Connect a Git repository and authorize access
- Select the repository and branch
- Build command
npm run build, output directorydist
Rollback
Troubleshooting
Build fails after removingoxygen()
npm run dev, npm run preview, and npm run start all go through the Shopify CLI’s Oxygen sandbox. Once the Oxygen plugin is gone, use npm run cf-dev instead.
nodejs_compat errors at runtime
Confirm the flag is in wrangler.json and that compatibility_date is recent enough for the Node compatibility mode your dependencies need.
Missing environment variables in production
.dev.vars is local-only. Values reach production only after npx wrangler secret bulk .dev.vars, or by setting them in the dashboard. Names are case-sensitive.
Weaverse Studio preview does not connect
Check WEAVERSE_PROJECT_ID and WEAVERSE_HOST are present as Worker secrets, and that the deployed URL is registered on your Weaverse project. See Preview Errors.
Session or cache behaves differently than on Oxygen
Expected — this is the least-validated part of the migration. Compare against an Oxygen deployment before going live.