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 cicompleted. - A Cloudflare account selected with
npx wrangler loginorCLOUDFLARE_API_TOKENplusCLOUDFLARE_ACCOUNT_IDin CI. - A final public origin, for example
https://app.example.comor the assignedworkers.devURL. - 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.
| 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. |
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 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.