operations

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.

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 ci completed.
  • A Cloudflare account selected with npx wrangler login or CLOUDFLARE_API_TOKEN plus CLOUDFLARE_ACCOUNT_ID in CI.
  • A final public origin, for example https://app.example.com or the assigned workers.dev URL.
  • 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.

For a custom domain, add it only after deciding the canonical origin:

"routes": [{ "pattern": "app.example.com", "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.

NameRequired value
BETTER_AUTH_SECRETRandom value of at least 32 characters. Never reuse another key.
BETTER_AUTH_URLExact public HTTPS origin with no path or trailing slash, such as https://app.example.com.
CREDENTIALS_ENCRYPTION_KEYA different random value of at least 32 characters. Back it up securely; changing or losing it makes stored connector credentials unreadable.

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.

NamePurpose
REPORT_CRON_SECRETIndependent random value used by protected manual cron endpoints. Native Cron Triggers do not send this value, but operations endpoints require it.
DASHLOOM_OPERATOR_EMAILSComma-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 Analytics and Search Console

Set GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET. Register this exact callback in Google Cloud:

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

Set RESEND_API_KEY and a sender on a verified Resend domain in RESEND_FROM_EMAIL, for example Dashloom <auth@example.com>. Keep AUTH_REQUIRE_EMAIL_VERIFICATION=false until a real verification email has been delivered and its link tested. Then change it to true.

Waffo and Anyway billing

For Waffo, set WAFFO_MODE, WAFFO_MERCHANT_ID, WAFFO_PRIVATE_KEY_BASE64, and WAFFO_PRODUCT_SOLO, WAFFO_PRODUCT_STUDIO, WAFFO_PRODUCT_AGENCY. Configure its webhook as:

https://YOUR_ORIGIN/api/billing/webhook/waffo

For Anyway, set the three ANYWAY_PAYMENT_LINK_* values and matching ANYWAY_PRODUCT_* IDs. Configure its webhook as https://YOUR_ORIGIN/api/billing/webhook/anyway. Finish the complete test checkout, signed webhook, renewal, cancellation, and entitlement flow before enabling production payment 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 Flash endpoint:

KIE_AI_BASE_URL=https://api.kie.ai/gemini-3-flash/v1
KIE_AI_MODEL=gemini-3-5-flash-thinking
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 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, Resend delivery, and test checkout/webhook for each enabled payment provider.