Wocart

Deploy to Cloudflare

This page deploys one store: the API server, the dashboard and the storefront, each a Cloudflare Worker, sharing one D1 database. It assumes you have run Wocart locally from the same checkout.

What you need

A Cloudflare account with R2 enabled, a domain on Cloudflare for the API (see Domains), and Wrangler signed in: npx wrangler login.

1. Create the resources

Choose your own names. Every installation gets new resources: never reuse another project's.

TerminalCode
npx wrangler d1 create mystore-db npx wrangler r2 bucket create mystore-media npx wrangler kv namespace create RATE_LIMIT npx wrangler kv namespace create OAUTH_KV npx wrangler kv namespace create DASHBOARD_RATE_LIMIT npx wrangler queues create mystore-events

Keep the IDs each command prints. Then put the names in the root .env:

Terminal.env
COD_ACCOUNT_ID=<your account id> COD_DB_NAME=mystore-db COD_R2_BUCKET_NAME=mystore-media COD_SERVER_URL=https://api.yourdomain.com

2. Configure the API server

In cod-server/wrangler.toml, the [env.production] section is what a production deploy reads. Fill in:

  • the D1 database_name and database_id, the bucket name, both KV IDs and the queue name, in the production bindings;
  • the production variables: WORKER_URL, WORKER_SELF_URL, BETTER_AUTH_URL, ALLOWED_ORIGINS, STOREFRONT_URL, and the media settings (Media).

Configuration explains each value. Check that no placeholder is left:

TerminalCode
grep -n "00000000" cod-server/wrangler.toml cod-client-astro/wrangler.toml

It must print nothing.

3. Create the database and the store

TerminalCode
cd cod-server npm run db:migrate:remote STORE_API_KEY=<a new store key> npm run db:seed:remote

db:migrate:remote applies every migration to the deployed database: sign-in fails until it has run. db:seed:remote creates the store, its API key (it keeps only its hash), menus, default collections, legal pages and a shipping profile; running it again changes nothing the store has. Generate the key with openssl rand -hex 32 and keep it for the storefront (step 4).

Then clear uploads that were never prepared, once for the bucket:

TerminalCode
npm run r2:lifecycle

4. Deploy the three Workers

The API server:

TerminalCode
cd cod-server npm run deploy -- --env production npx wrangler secret put MCP_LOGIN_TICKET_SECRET --env production npx wrangler secret put REVIEW_UPLOAD_SECRET --env production npx wrangler secret put IMAGEKIT_PRIVATE_KEY --env production # with ImageKit

The dashboard. In cod-client-astro/wrangler.toml, set the same D1 database, the DASHBOARD_RATE_LIMIT namespace's ID as RATE_LIMIT_KV, and PUBLIC_APP_URL, PUBLIC_API_URL, PUBLIC_TRUSTED_ORIGINS. Then:

TerminalCode
cd cod-client-astro npm run deploy npx wrangler secret put BETTER_AUTH_SECRET npx wrangler secret put MCP_LOGIN_TICKET_SECRET # the same value as the API server's ADMIN_EMAIL=you@yourdomain.com ADMIN_NAME=You npm run seed:admin:remote

seed:admin:remote creates your account locally and in the deployed database, and prints its password and a merchant API key once.

The storefront. Theme-00's deploy takes COD_SERVER_URL from the root .env and refuses a localhost value:

TerminalCode
cd cod-astro/theme-00 npm run deploy npx wrangler secret put STORE_API_KEY # the key you gave db:seed:remote

Theme-00 also builds for Vercel (npm run build:vercel) with the same three values; see Production and upgrades for a theme of your own.

5. Domains

The API needs a custom domain

Cloudflare blocks a Worker on *.workers.dev from calling another *.workers.dev Worker (error 1042), so a storefront on workers.dev cannot reach an API on workers.dev. Put at least the API on your own domain.

In the Cloudflare dashboard, open each Worker, then Settings → Domains & Routes → Add → Custom domain: for example api.yourdomain.com, dashboard.yourdomain.com and shop.yourdomain.com.

Once the domains are live, make every URL match them, and redeploy what changed:

WhereValues
cod-server/wrangler.tomlWORKER_URL, WORKER_SELF_URL, BETTER_AUTH_URL, ALLOWED_ORIGINS, STOREFRONT_URL
cod-client-astro/wrangler.tomlPUBLIC_APP_URL, PUBLIC_API_URL, PUBLIC_TRUSTED_ORIGINS. A changed PUBLIC_API_URL needs npm run deploy, which rebuilds
Root .envCOD_SERVER_URL, then the storefront's npm run deploy

6. Check it

TerminalCode
curl -s -o /dev/null -w "%{http_code}\n" https://api.yourdomain.com/api/docs # 200

Then sign in to the dashboard, open the storefront, and place a test order: it appears in the dashboard's orders.

When something fails

SymptomCauseFix
Sign-in answers 500The deployed database is not migratednpm run db:migrate:remote in cod-server
Sign-in answers 403 INVALID_ORIGINThe dashboard's address is not in PUBLIC_TRUSTED_ORIGINSAdd it, then npm run deploy
Signed in, but every screen fails with 401The API server does not accept the dashboard's tokensBETTER_AUTH_URL must be the dashboard's /api/auth address, and WORKER_SELF_URL the API's own origin
The storefront shows an empty, unavailable storeIt cannot read the APICOD_SERVER_URL must be the API's public domain, and STORE_API_KEY the key given to db:seed:remote
Image uploads failMedia is not configuredThe error code names what is missing: Media
Anything elsenpx wrangler tail <worker-name> shows the Worker's errors while you retry

Keep it running

  • Logs: npx wrangler tail <worker-name>, or the Worker's Logs tab.
  • Roll back a Worker: npx wrangler rollback. A rollback does not undo a migration, which is why a release keeps working on the database the previous one left.
  • Back up the database before an upgrade: npx wrangler d1 export <database> --remote --output backup.sql.
  • Upgrade with Upgrading.