SuperAPI AI Directory

mkfast-deploy

Deployment & operations

View repository

Updated 10-15 13:03

About this skill

Mkfast Deploy

Deploy mkfast-template(TanStarter-family) projects to Cloudflare Workers.Core value: dynamically trim deployment steps based on the components actually enabled in the project, avoiding copying the full-version docs wholesale, which would cause a trimmed project to run empty commands or even error out.

Scope

Is: projects derived from the mkfast-template template, including the full SaaS form, trimmed blog versions, or any intermediate form.

Is not: any Cloudflare Workers project (in that case the wrangler skill is enough).

Identification markers (any one is sufficient):

  • The root directory has wrangler.jsonc + package.json
  • package.json containing wrangler + @cloudflare/vite-plugin + @tanstack/react-start any one of
  • The directory contains mkfast characteristic files:drizzle.config.ts / src/server.ts / src/db/auth.schema.ts

Important principles

  1. Assess before executing — Phase 1 must be completed before any deploy command, generating a trimmed step checklist. Directly pnpm run deploy does not count as work completed
  2. Do not copy the official docs wholesale — the full mkfast docs assume D1 + R2 + secret bulk,and a trimmed project running these steps will error or waste time(for example, running db:migrate:remote when there is no drizzle config will fail to find the migrations directory)
  3. secret bulk is a gating step — the project has server-side secrets (.env.production containing non- VITE_* variables) that must be pushed to Cloudflare before deploy, otherwise it will crash at runtime
  4. Production deployment requires explicit confirmation — before executing pnpm run deploy in Phase 3, you must use AskUserQuestion to get the user's final confirmation (it affects the production domain)
  5. Domain status determines the routes strategy — when the domain is not hosted on Cloudflare, you cannot directly deploy a config containing routes ; you must first remove routes, deploy to get the default domain, then bind it in the Dashboard (see references/tailoring.md Routes configuration strategy table)
  6. Security first — .env* must go into .gitignore;any secret that has appeared in conversations / screenshots / Slack / commit messages is considered leaked, and must be rotated immediately (see Phase 1.5 security baseline + Phase 4 Secret rotation reminder)
  7. Template placeholders must be checked — mkfast-template-derived projects' wrangler.jsonc has 4 template default values that must be changed(name / routes.pattern / database_id / bucket_name) + 1 that must be disabled (logpush: true will always report code 10023 on the Free/Pro plan). See references/components.md §0 placeholder identification table;deploying without checking will write to the template author's D1 or the deploy will fail

Workflow (4 phases)

Phase 1 — Automatic assessment (read-only)

Step 1.0 (mandatory, blocks subsequent progress): check against references/components.md §0 template default placeholder identification table for wrangler.jsonc + package.json diff。any unreplaced template default values——name="mkfast-template" / routes[0].pattern="demo.tanstarter.dev" / database_id="dc34f04a-3445-4b5c-bf61-c4ec2328e239" / r2.bucket_name="mkfast-template" / logpush: true— all of them directly block entry into Phase 2。

This isthe most important prerequisite gate of this skill: Deploying without checking will (a) write to the template author's D1 database; (b) fail the deploy with code 10023 (a Logpush enterprise feature); (c) cause route conflicts. All of these are pitfalls that first-time deployments of projects derived from mkfast-templateare almost certain to hit.

Read the project state and identify the "project profile".At minimum, read these 5 files:

What to read What to extract
wrangler.jsonc name / routes / d1_databases / r2_buckets / send_email / other bindings
package.json name + whether the dependencies include drizzle-orm / better-auth / stripe / creem / @beehiiv/sdk
.env.example All supported variable categories (refer to the references/components.md detection signal table)
.env.production(if present) Configured variables vs. unfilled (empty string) variables
.env.local(if present) CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN whether it is ready

According to references/components.md , determine one by one whether each of the 12 component categories is enabled, and generate the "project profile" output (for the format, refer to templates/deploy-checklist.md):

  • Project form: full SaaS / trimmed-down blog / intermediate form
  • Enabled components checklist
  • Environment variable gap table
  • Trimmed-down checklist of steps to execute (number of steps)

Phase 1.5 — Security baseline (read-only + create .gitignore if necessary)

4 items that must be checked before deployment; fill in whichever is missing.Not letting secrets leak out of the repository is the bottom line:

Item Check command Fix when it fails
.gitignore exists and contains .env* grep -E "\.env" .gitignore If it does not exist,create it immediatelycontaining .env、.env.local、.env.*.local、.env.production、.dev.vars
.env.local is not in git history git log --all --full-history -- .env.local output is empty has already been committed → use git filter-repo to clear it + immediately rotate all secrets involved in
wrangler.jsonc has no hard-coded secrets grep should not show sk_live_ / re_live_ / whsec_ , etc. Delete hard-coded ones; route everything through wrangler secret put
.env.production no plaintext production secrets are about to be committed `cat .gitignore grep .env.production`

When a trimmed-down project has no .gitignore(I have seen projects that have not yet run git init but have already written .env.local ), first create .gitignore before continuing to Phase 2.

Phase 2 — Decision points (AskUserQuestion)

Ask the user based on the Phase 1 / 1.5 profile, choosing 1-5 questions depending on the situation:

  • Target user region(strongly recommended to ask first): Global / Overseas only / Mainly mainland China / Both domestic and overseas
    • If mainland China is selected → ⚠️ Warning: Cloudflare has no PoP nodes in mainland Chinano PoP nodes(unless Enterprise Edition + JD Cloud partnership); access experience will be intermittent;recommend referring to references/cn-access.md switchover plan(EdgeOne / Vercel + domestic CDN / dual deployment)
  • Domain status(must ask):<domain> Is it hosted on Cloudflare? Three options: already hosted / not hosted (use the default *.workers.dev for now) / not purchased yet
  • D1 / R2 resources(full version only): Have they already been created in Cloudflare? If not, do you agree to now wrangler d1 create / wrangler r2 bucket create?
  • Optional features: Should Giscus / analytics / Webhook / Crisp be enabled this time?
  • CI automation: Whether to sync-configure GitHub Actions auto-deploy?

For the pruning decision tree, see references/tailoring.md。

Phase 3 — Execution (according to the pruned checklist)

Step 0 — Sanity (strongly recommended):

# 清掉过往 dev 留下的 dist + .vite 缓存
# 避免 chokidar 在 dev 中 EINTR 报错(曾导致 dev server 起不来)
rm -rf dist .vite node_modules/.vite

# 验证 wrangler 凭证已加载(推荐用 .env.local + 一次 source 而非 wrangler login)
# wrangler 不会自动读 vite 系的 .env.local,必须 export 到当前 shell:
set -a && . ./.env.local && set +a && pnpm wrangler whoami

Recommended to add an alias once in package.json to solve it:

"deploy:cf": "set -a && . ./.env.local && set +a && pnpm run build && wrangler deploy"

Afterwards, just use pnpm deploy:cf , avoiding the need to export before every wrangler command.

Required for all projects:

  1. pnpm wrangler whoami Verify login (when not logged in, check .env.local credentials or prompt wrangler login)
  2. Check token permissions: according to the enabled components, check references/components.md 's §API Token permission complete matrix (Workers Scripts / D1 / R2 / Workers Routes / Email / KV, etc.); if permissions are missing, go directly to Dashboard → My Profile → API Tokens and edit the existing token to add permissions (no need to recreate)
  3. AskUserQuestion final confirmation → pnpm run deploy

Only do this when the corresponding component is detected(according to references/components.md detailed steps):

  • (has D1) pnpm wrangler d1 create <name> → write back to wrangler.jsonc 's database_id → pnpm db:migrate:remote
  • (has R2) pnpm wrangler r2 bucket create <name> → write back to bucket_name
  • (has send_email) Cloudflare Dashboard enable Email Routing + verify from email
  • (has Better Auth) pnpm dlx @better-auth/cli@latest secret generate → wrangler secret put BETTER_AUTH_SECRET
  • (has server-side secret) pnpm wrangler secret bulk .env.production
  • (has payment) Stripe/Creem live key + price ID + webhook endpoint configuration

Only when the user selected CI in Phase 2:

  • Create .github/workflows/deploy.yml + prompt to go to GitHub Settings → Secrets and add CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN / all VITE_*

Phase 4 — Verification

# 在线验证(首次)
curl -s -o /dev/null -w "HTTP %{http_code} | size %{size_download}B | time %{time_total}s\n" https://<domain>

# 5-10 秒后再跑一次(验证缓存 + 二次访问性能)
curl -s -o /dev/null -w "HTTP %{http_code} | size %{size_download}B | time %{time_total}s\n" https://<domain>

Expected:

Metric First time Second time (warm)
HTTP code 200 200
size > a few KB (SSR rendered successfully) Same as first time or smaller (cache hit)
time < 3s (including cold start + CDN propagation) < 500ms (PoP hit)

Additional checks:

  • In the deploy output, Total Upload: X KiB / gzip: Y KiB → Y < 3072(3 MB free plan limit)
  • Cloudflare Dashboard → Workers & Pages → <worker-name> → Logs → no runtime error
  • The first visit to a custom domain may have a 30s CDN propagation delay

30-minute post-launch observation checklist:

Check item Command / Location Expected
5xx response rate Dashboard → Workers & Pages → <worker> → Logs → filter status >= 500 0 entries
Version number matches Dashboard → <worker> → Deployments Latest Version ID matches the deploy output
Analytics traffic Dashboard → <worker> → Analytics (or third-party RUM) Normal requests are coming in
D1 table access (if enabled) wrangler d1 execute <name> --remote --command "SELECT COUNT(*) FROM user" Numbers are returned without errors
R2 bucket access (if enabled) wrangler r2 object list <bucket> List returns without errors

Rollback plan:

# 列出历史版本
pnpm wrangler deployments list

# 回滚到上一版(不传 id)
pnpm wrangler rollback

# 回滚到指定版本
pnpm wrangler rollback <version-id>

Note:

  • D1 migrations are forward-only; schema rollback requires manually writing a down migration and wrangler d1 execute applying it
  • R2 has no versioning concept; restore from backup as needed (only if wrangler r2 object get backup was done before deployment)
  • Secret rollback:wrangler secret put <KEY> overwrite with the old value, or wrangler secret delete <KEY> clear

Secret rotation reminder (important): If, during this deployment, a token / API key / database secret has been in any of the following channelsappeared:

  • Claude / ChatGPT and other chat histories
  • Slack / Lark / WeChat messages
  • Screenshots / screen recordings
  • Code comments / commit messages

→ immediately go to the Cloudflare Dashboard / third-party service backend and roll it(generate a new value to replace the old value). If the token string has changed, remember to update .env.local and GitHub Secrets.

For troubleshooting errors, see references/troubleshoot.md。

Output format

After each phase ends, give the user a concise report, e.g.:

Phase 1 project profile output (example)

## Phase 1 — 项目画像

**形态**:裁剪版博客
**启用组件**:无(纯 SSR + 博客)
**待执行步骤**:2 步(whoami + deploy)
**跳过**:D1 / R2 / Email / Auth / Pay / Secret bulk / Migrate

Final checklist (example)

✅ wrangler 登录(账户 zhihui)
✅ pnpm run deploy(gzip 471 KB / 17ms 启动)
✅ HTTP 200 验证通过
⚠️ 可选未启用:Giscus / Plausible

Tool files

  • references/components.md — mkfast-template 12 categories of component detection signals → deployment step mapping table

    • §0 Template default placeholder identification table (required check in Phase 1 Step 1.0)
    • §API Token permission complete matrix (quick reference table for checking permissions by enabled component)
    • §How to infer the secret list when there is no .env.example (infer by reading src/env/*.ts)
  • references/tailoring.md — Full version vs trimmed version vs intermediate-form trimming decision tree + decision matrix quick reference table

    • §Pitfall:enable=false The D1 binding still needs to be retained (module-load-time call getDb())
    • §Clarification:enable=false ≠ tree-shake (enable only controls UX; the bundle still contains the SDK)
  • references/troubleshoot.md — 11 common errors + troubleshooting commands + fixes (including #10 Logpush / #11 already exists)

  • references/cn-access.md — 4 tiers of solutions for optimizing access from mainland China (Cloudflare settings / image hosting / EdgeOne reverse proxy / dual deployment)

  • templates/deploy-checklist.md — Phase 1 project profile output template + final report template + AskUserQuestion template

  • templates/stub-no-d1-r2.md — Code stub template to completely disable D1/R2 (pasteable version with changes to 4 files)