Cloudflare Workers deployment
Dashloom Cloud deploys as one vinext Worker with static assets, a D1 binding named `DB`, two Cron Triggers, and Workers observability. `wrangler.jsonc` is the only Worker configuration source.
1. Prerequisites
- Node.js 22.13 or newer and
npm cicompleted. - A Cloudflare account selected with
npx wrangler loginorCLOUDFLARE_API_TOKENplusCLOUDFLARE_ACCOUNT_IDin CI. - The canonical public origin
https://dashloom.dev. - A production D1 database. Create one only if it does not already exist:
npx wrangler whoami
npx wrangler d1 create dashloom-cloud-d1
Copy the returned UUID into wrangler.jsonc as d1_databases[0].database_id. Do not leave 00000000-0000-4000-8000-000000000000 in production. If the database already exists, use npx wrangler d1 list and verify both its name and account before copying the ID.
The canonical custom-domain route is version-controlled in wrangler.jsonc:
"routes": [{ "pattern": "dashloom.dev", "custom_domain": true }]
2. Required runtime configuration
Set these values in Workers > Settings > Variables and Secrets, or with npx wrangler secret put NAME. wrangler.jsonc uses keep_vars: true, so dashboard-managed plaintext variables are preserved by later deploys. Secrets are always encrypted by Cloudflare.
| Name | Required value |
|---|---|
BETTER_AUTH_SECRET | Random value of at least 32 characters. Never reuse another key. |
BETTER_AUTH_URL | Exact public HTTPS origin with no path or trailing slash, such as https://app.example.com. |
CREDENTIALS_ENCRYPTION_KEY | A different random value of at least 32 characters. Back it up securely; changing or losing it makes stored connector credentials unreadable. |
KIE_AI_API_KEY | Server-only kie.ai credential for managed AI calls. Rotate it immediately if it was ever stored as a plaintext Worker variable. |
WAFFO_PRIVATE_KEY | Waffo signing private key. Keep only as an encrypted Worker Secret. |
ANYWAY_MERCHANT_API_KEY | Server-only Anyway Merchant API key used for authoritative fulfillment and reconciliation. |
ANYWAY_WEBHOOK_PUBLIC_KEY | Anyway Standard Webhooks verification key (whpk_...); keep it in the encrypted gate so deployment cannot omit webhook verification. |
These seven names are version-controlled in secrets.required. Wrangler warns during local development when they are absent, npm run config:check fails when the gate or canonical route is removed, and npm run secrets:check:remote confirms the deployed values are encrypted Secrets rather than plaintext variables. The remote check runs automatically before npm run deploy. Store their values as encrypted Worker Secrets, never under vars.
Generate two independent values locally:
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"
Run the command twice, then store the outputs separately as BETTER_AUTH_SECRET and CREDENTIALS_ENCRYPTION_KEY.
3. Recommended hosted-operations configuration
| Name | Purpose |
|---|---|
REPORT_CRON_SECRET | Independent random value used by protected manual cron endpoints. Native Cron Triggers do not send this value, but operations endpoints require it. |
DASHLOOM_OPERATOR_EMAILS | Comma-separated sign-in email addresses allowed to access operator/support features. |
The configured schedules are */15 * * * * and 17 3 * * *. Cloudflare Cron expressions run in UTC; the daily job therefore runs at 11:17 China Standard Time.
4. Optional feature configuration
Google sign-in, Analytics, and Search Console
Set GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET for identity-only Google sign-in, with this callback:
https://YOUR_ORIGIN/api/auth/callback/google
Set the separate GOOGLE_CONNECTOR_CLIENT_ID and GOOGLE_CONNECTOR_CLIENT_SECRET for GA4/GSC data authorization, with this callback:
https://YOUR_ORIGIN/api/connectors/google/callback
The origin must exactly match BETTER_AUTH_URL. See docs/google-cloud-setup.md.
Bing Webmaster Tools
Bing does not require a Worker environment variable. Each workspace owner enters a Bing Webmaster API key in Dashboard > Sources; Dashloom encrypts it with CREDENTIALS_ENCRYPTION_KEY.
Transactional email
Password reset emails use Cloudflare Email Service through the EMAIL Workers binding declared in wrangler.jsonc. Onboard your sender domain under Cloudflare Email Service > Email Sending, complete the required DNS setup, and set EMAIL_FROM_ADDRESS to a plain address on that domain (the hosted default is auth@dashloom.dev). No Resend API key is needed. Test real password-reset delivery and the reset link after deployment. Sign-up signs users in immediately; sign-up and sign-in never require or send email verification. Old AUTH_REQUIRE_EMAIL_VERIFICATION values have no effect.
Waffo and Anyway billing
For Waffo, set WAFFO_MODE, WAFFO_MERCHANT_ID, WAFFO_PRIVATE_KEY, WAFFO_PRODUCT_SOLO, WAFFO_PRODUCT_STUDIO, WAFFO_PRODUCT_AGENCY, and WAFFO_PRODUCT_CREDITS_5000/10000/50000. The three credit products must be one-time products priced at USD 12, 22, and 89. Configure its webhook as:
https://YOUR_ORIGIN/api/billing/webhook/waffo
For Anyway subscriptions, set the three ANYWAY_PAYMENT_LINK_* values and matching ANYWAY_PRODUCT_* IDs. Permanent packs additionally require ANYWAY_PRODUCT_CREDITS plus ANYWAY_PAYMENT_LINK_CREDITS_5000, ANYWAY_PAYMENT_LINK_CREDITS_10000, and ANYWAY_PAYMENT_LINK_CREDITS_50000; these must be fixed one-time links priced at USD 12, 22, and 89. All flows share server-only ANYWAY_MERCHANT_API_KEY and ANYWAY_WEBHOOK_PUBLIC_KEY. Configure https://YOUR_ORIGIN/api/billing/webhook/anyway for all order.* and subscription.* events. Complete test checkout, signed webhook, renewal, credit grant, cancellation, refund/dispute, reconciliation, and entitlement verification before enabling live links. See docs/payment-billing.md.
Managed AI
Dashloom Cloud's managed model runs use kie.ai. Set KIE_AI_API_KEY to enable them. The defaults use kie.ai's OpenAI-compatible Gemini 3.7 Flash endpoint:
KIE_AI_BASE_URL=https://api.kie.ai/gemini-3-7-flash-openai/v1
KIE_AI_MODEL=gemini-3-7-flash
KIE_AI_API_KEY=...
The base URL is restricted to the official api.kie.ai host. Change the base path and model together when selecting another kie.ai chat model. Without KIE_AI_API_KEY, BYOK provider connections still work but managed AI is unavailable.
5. Production database gate
Database migrations are a separate, explicit release step. A Worker upload does not prove that production D1 is current.
npm run config:check
npx wrangler d1 info dashloom-cloud-d1 --json
npm run db:status:remote
npm run db:migrate:remote
npm run db:status:remote
npx wrangler d1 execute dashloom-cloud-d1 --remote --command "SELECT name FROM sqlite_schema WHERE type='table' AND name IN ('user','session','workspaces','connector_accounts','metric_points') ORDER BY name"
Confirm that the reported D1 UUID matches wrangler.jsonc, no migrations remain pending, and all five queried tables exist. Back up an existing production database before applying schema changes.
6. Validate and deploy
npm ci
npm run typecheck
npm run lint
npm test
npm run config:check
npm run secrets:check:remote
npm run deploy:dry-run
npm run deploy
deploy:dry-run builds vinext and validates the generated dist/server/wrangler.json without uploading. deploy performs the build and Worker upload but does not apply D1 migrations.
After deployment, verify the home page, sign-up, sign-in, workspace creation, one connector save/sync, Cron Trigger history, Worker logs, Google callback when enabled, Cloudflare password-reset email delivery, and test checkout/webhook for each enabled payment provider.