deploy
Skill0 starsChanged 2 months agoMITView on GitHub
Stage 3 production deploy for substrate projects. Covers public *.vercel.app deploy, custom domain + 5 Clerk DNS CNAMEs + SSL, Clerk prod instance with domain-typo confirmation, prod Convex deployment, env sync via .env.prod, and optional GCP OAuth. Five phase markers (A–E) so you can stop or resume without redoing completed work. Invoke after /substrate:migrate once local sign-in is verified.
- Reads credentials
- Commits and pushes
155 other projects use a version of this.
Adopted by
Most recently taken up by
- pedrohcgs/claude-code-my-workflowtheir own version, first seen Nov 8, 2026
- KingKongRobotics/jumpertheir own version, first seen Nov 8, 2026
- stakeme-team/arc-agent-kittheir own version, first seen Nov 8, 2026
- dockhold/mcptheir own version, first seen Nov 8, 2026
- KhaiTrang1995/nexus-kbtheir own version, first seen Nov 8, 2026
- ribato22/vibechecktheir own version, first seen Nov 8, 2026
Used with
Projects with it also use pm-discovery, qa-phase and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
ww-w-aiSkillpm-discovery
PM Agent Team - Automated product discovery, strategy, and PRD generation. Runs PM analysis workflow to produce comprehensive PRD before PDCA Plan phase.
Also in 3 projects that use this
ww-w-aiSkillqa-phase
Run QA tests at various levels (L1-L5) for features under PDCA management. Integrates with MCP tools to execute structured test plans.
Also in 3 projects that use this
- +10 more from ww-w-ai
Other versions155 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 155
- ok-oldking/ok-wuthering-waves★ 8.6ksame name
- memovai/mimiclaw★ 5.8ksame name
- KingKongRobotics/jumper★ 3.1ksame name
- jhd3197/ServerKit★ 1.8ksame name
- pedrohcgs/claude-code-my-workflow★ 1.7ksame name
- mattmireles/gemma-tuner-multimodal★ 1.5ksame name
- microsoft/power-platform-skills★ 1.1ksame name
- jazzyalex/agent-sessions★ 941same name
- awslabs/agent-plugins★ 918same name
- patrickjaja/claude-desktop-extra★ 734same name
145 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- add-doctrineSkill
- adoptSkill
- architect-specSkill
- diagnoseSkill
- executeSkill
- graph-specSkill
- initSkill
- migrateSkill
- orchestrateSkill
- quick-specSkill
- serve-beadSkill
- spoolSkill
- synthesize-sessionSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
32 rules. 0 are common, 12 are distinctive, and 20 are very specific to this project.
0
Common
Most of the 139 edited versions we read keep these.
12
Distinctive
This author's own choices. Worth a look.
20
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 37
If STAGE_MISMATCH, stop and redirect per the table above.
- Very specific: line 65
If likely done, ask: *.vercel.app appears already deployed.
- Very specific: line 69
GitHub remote: If no origin, run:
- Very specific: line 75
Ask user for slug + visibility with default-escape.
- Very specific: line 77
Vercel link: If no .vercel/project.json:
- Very specific: line 85
Use printf %s "$VALUE" | vercel env add NAME production (stdin form — piped heredoc is unreliable on some shells):
- Very specific: line 104
Verify: Ask user to visit the Vercel-generated URL and sign in via dev Clerk.
- Very specific: line 138
Custom domain decision: Ask: Register a custom domain?
- Very specific: line 140
If skip, jump to Phase C (user can still have a prod Clerk instance attached to the *.vercel.app URL, but it's uncommon).
- Very specific: line 142
Get or buy the domain: Ask: Already own the domain?
- Very specific: line 211
Goal: create a production Clerk instance bound to the custom domain, write prod keys to .env.prod.
- Distinctive: line 285
Domain-typo confirmation: BEFORE the user creates the Clerk prod instance, echo the domain back and require exact re-entry:
- Distinctive: line 309
GCP OAuth (optional, prod-only): If Google sign-in is desired on prod, the user needs their own Google OAuth client (Clerk's shared creds …
- Distinctive: line 326
Validate the webhook secret format: before writing anything:
- Very specific: line 375
Goal: create prod Convex deployment, sync .env.prod values to Convex prod + Vercel prod (overwriting Phase A's dev-env temps).
- Distinctive: line 401
If already set to the dev URL, EDIT it rather than creating a new endpoint.
- Distinctive: line 515
MUST verify migration is complete at the stage gate.
- Distinctive: line 516
MUST run idempotency check at the start of each phase.
- Distinctive: line 517
MUST print each phase's checklist before the gate.
- Very specific: line 518
MUST pause at each phase gate for explicit y/n/default approval.
- Distinctive: line 519
MUST perform domain-typo confirmation before Clerk prod create (Phase C step 1).
- Very specific: line 520
MUST perform tenant-drift detection at Phase C start (diff .env.prod against npx convex env get --prod).
- Very specific: line 521
MUST write .env.prod in Phase C, read from it in Phase D.
- Very specific: line 522
MUST NOT commit .env.prod — gitignored via .env* rule.
- Distinctive: line 523
MUST NOT push secret keys (Clerk Secret Key, webhook secret, Convex deploy key) to the client bundle.
- Very specific: line 524
MUST NOT push CLERK_JWT_ISSUER_DOMAIN or CLERK_WEBHOOK_SECRET as Vite env vars — these are Convex-server-only, set via npx convex env set …
- Distinctive: line 525
MUST NOT force-push to remote main.
- Very specific: line 526
MUST validate the webhook secret format (^whsec_) in Phase C step 9 before any write.
- Very specific: line 527
MUST NOT run dev Clerk setup — that belongs to /substrate:migrate.
- Distinctive: line 528
SHOULD tolerate partial progress: if the user has done some steps manually (e.g.
- Distinctive: line 529
SHOULD narrate context clearly when the user switches between terminal, Clerk dashboard, GCP Console, Vercel dashboard, and DNS provider.
- Very specific: line 530
SHOULD offer the default-escape suffix [type 'default' to let me decide sensible defaults] on Socratic questions (repo slug, visibility, …
“Common” is measured: kept by at least 6 in 10 of the 139 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
/substrate:deploy
Take a migrated substrate project from localhost to a fully functional production deployment: public URL → custom domain → prod Clerk → prod Convex → prod env sync.
Heads up: this is a long interactive operation with five phases. Each phase has its own idempotency check, checklist, and approval gate — you can stop after any phase and resume later. The user will switch between terminal, Clerk dashboard, Google Cloud Console, Vercel dashboard, and possibly their DNS provider. Narrate context clearly.
When to run
/substrate:migratehas completed —src/App.tsxno longer shows the substrate welcome screen, and dev Clerk sign-in works on localhost.convex/_generated/is present (Convex codegen has run).- The user wants a production URL (
*.vercel.appat minimum; custom domain is the goal).
When to REFUSE
| Signal | Redirect |
Migration hasn't run (src/App.tsx still shows welcome screen) | Run /substrate:migrate first |
Dev Clerk not configured (.env.local missing VITE_CLERK_PUBLISHABLE_KEY) | Run /substrate:migrate step 9 to complete dev Clerk setup |
convex/_generated/ missing | Run npx convex dev once in another terminal |
Stage gate
test -f package.json \
&& test -d convex/_generated \
&& test -f .env.local \
&& grep -q "^VITE_CLERK_PUBLISHABLE_KEY=." .env.local \
&& ! grep -q "Substrate project initialized" src/App.tsx \
|| echo "STAGE_MISMATCH"If STAGE_MISMATCH, stop and redirect per the table above.
Resolve SUBSTRATE_ROOT (same pattern as /substrate:init):
for candidate in \
"$HOME/.claude/plugins/substrate" \
"$PWD/.claude/plugins/substrate" \
"${SUBSTRATE_ROOT:-}"; do
if [ -n "$candidate" ] && [ -f "$candidate/scripts/connect-vercel.sh" ]; then
echo "FOUND: $candidate"
break
fi
donePhase A — Public deploy (*.vercel.app on dev backends)
Goal: app reachable at a Vercel-generated URL, using DEV Clerk + DEV Convex. Quick preview deploy for sharing; NOT real production (dev Clerk has shared Google OAuth, dev Convex isn't isolated).
Idempotency check:
test -f .vercel/project.json && git remote get-url origin >/dev/null 2>&1 && vercel whoami >/dev/null 2>&1 && echo "PHASE_A_LIKELY_DONE"If likely done, ask: *.vercel.app appears already deployed. Skip Phase A? [type 'default' to let me decide sensible defaults]. Default: skip.
Steps
GitHub remote. If no
origin, run:bash "$SUBSTRATE_ROOT/scripts/init-github.sh" "<repo-slug>" "<public|private>"Ask user for slug + visibility with default-escape. Defaults: slug from
package.json#name, visibilityprivate.Vercel link. If no
.vercel/project.json:bash "$SUBSTRATE_ROOT/scripts/connect-vercel.sh" "<project-slug>"Push DEV env to Vercel prod (temporary). Phase A uses dev backends so the public URL works immediately. Phase D will overwrite these.
Use
printf %s "$VALUE" | vercel env add NAME production(stdin form — piped heredoc is unreliable on some shells):VCU=$(grep -E "^VITE_CONVEX_URL=" .env.local | cut -d= -f2-) VCK=$(grep -E "^VITE_CLERK_PUBLISHABLE_KEY=" .env.local | cut -d= -f2-) CSK=$(grep -E "^CLERK_SECRET_KEY=" .env.local | cut -d= -f2-) printf '%s' "$VCU" | vercel env add VITE_CONVEX_URL production printf '%s' "$VCK" | vercel env add VITE_CLERK_PUBLISHABLE_KEY production printf '%s' "$CSK" | vercel env add CLERK_SECRET_KEY productionTrigger deploy:
git push origin mainVercel auto-builds. Print the expected Vercel dashboard URL.
- Verify. Ask user to visit the Vercel-generated URL and sign in via dev Clerk. Wait for y/n/default.
Phase A checklist (print to terminal before gate)
Phase A — Public Deploy
✓ GitHub remote: <repo-url>
✓ Vercel project: <vercel-url>
✓ Env pushed (dev): VITE_CONVEX_URL, VITE_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEY
✓ Deploy triggered: git push origin main
✓ Live URL reachable: https://<project>.vercel.app
✓ Dev sign-in works: confirmed
⚠ App is running on DEV backends. Phase B+ add custom domain and prod.Gate
"Continue to Phase B (custom domain)? (y/n/default)". Default: yes.
Phase B — Custom domain + DNS
Goal: custom domain points at the Vercel deployment, and 5 Clerk DNS CNAMEs are in place ready for Phase C.
Idempotency check:
vercel domains ls 2>/dev/null | grep -q "<domain>" && echo "PHASE_B_DOMAIN_OWNED"Steps
Custom domain decision. Ask:
Register a custom domain? (y/n/default — default: skip, stay on *.vercel.app).If skip, jump to Phase C (user can still have a prod Clerk instance attached to the
*.vercel.appURL, but it's uncommon).Get or buy the domain. Ask:
Already own the domain? (y/n/default — default: buy).Buy:
vercel domains buy <domain>Known bug: CLI has a polling timeout that can falsely report failure after a successful purchase. Verify with
vercel domains lsbefore retrying.Add existing:
vercel domains add <domain>Domain in team inventory vs. attached to project. These are two separate states.
vercel domains buyputs the domain in inventory automatically. If you bought elsewhere, runvercel domains add <domain>to put it in inventory. Only THEN can you:vercel alias set <latest-deployment> <domain>to attach to the project.
Add 5 Clerk DNS CNAMEs. Open Clerk dashboard → Domains → add
<domain>. Clerk shows 5 tenant-specific CNAME targets. Add each via Vercel DNS:vercel dns add <domain> clerk CNAME <tenant>.clerk.services vercel dns add <domain> accounts CNAME <tenant>.accounts.clerk.services vercel dns add <domain> clkmail CNAME mail.<tenant>.clerk.services vercel dns add <domain> clk._domainkey CNAME dkim1.<tenant>.clerk.services vercel dns add <domain> clk2._domainkey CNAME dkim2.<tenant>.clerk.servicesCLI quirks:
--scope <team>MUST come AFTER the subcommand (vercel dns add ... --scopeworks;vercel --scope ... dns add ...errors).vercel dns rm <id> --yesis NOT supported. Pipeyes y | vercel dns rm <id>if unattended.
- Wait for Clerk verification. In Clerk dashboard, click "Verify configuration". Clerk checks DNS and provisions SSL certs automatically. Can take 2–10 minutes.
Confirm DNS resolves:
dig <domain> +shortExpect Vercel IPs. If empty, wait another 2 minutes and retry.
Phase B checklist
Phase B — Custom Domain
✓ Domain purchased/added: <domain>
✓ Domain in team inventory: yes
✓ Domain attached to project: yes
✓ 5 Clerk CNAMEs added: clerk, accounts, clkmail, clk._domainkey, clk2._domainkey
✓ Clerk "Verify configuration": clicked
✓ DNS resolves: <Vercel IPs>
⚠ SSL provisioning may still be in progress (Clerk handles automatically)Gate
"Continue to Phase C (prod Clerk instance)?". Default: yes.
Phase C — Prod Clerk instance
Goal: create a production Clerk instance bound to the custom domain, write prod keys to .env.prod.
Prerequisite: Phase B complete — Clerk has verified DNS.
Idempotency + tenant-drift check:
Phase C has THREE possible states when re-entered. Detect which one before deciding whether to skip:
# State 1: .env.prod lacks pk_live_ → Phase C has never run. Proceed normally.
grep -q "^VITE_CLERK_PUBLISHABLE_KEY=pk_live_" .env.prod 2>/dev/null || echo "PHASE_C_FIRST_RUN"
# State 2: .env.prod has pk_live_ but Convex prod doesn't have matching
# CLERK_JWT_ISSUER_DOMAIN / CLERK_WEBHOOK_SECRET → TENANT DRIFT. User likely
# recreated Clerk prod (different tenant ID) or rotated keys.
LOCAL_ISSUER=$(grep "^CLERK_JWT_ISSUER_DOMAIN=" .env.prod 2>/dev/null | cut -d= -f2-)
LOCAL_WEBHOOK=$(grep "^CLERK_WEBHOOK_SECRET=" .env.prod 2>/dev/null | cut -d= -f2-)
DEPLOYED_ISSUER=$(npx convex env get CLERK_JWT_ISSUER_DOMAIN --prod 2>/dev/null || true)
DEPLOYED_WEBHOOK=$(npx convex env get CLERK_WEBHOOK_SECRET --prod 2>/dev/null || true)
if [ -z "$DEPLOYED_ISSUER" ]; then
echo "PHASE_C_LOCAL_DONE_PHASE_D_PENDING"
elif [ "$LOCAL_ISSUER" != "$DEPLOYED_ISSUER" ] || [ "$LOCAL_WEBHOOK" != "$DEPLOYED_WEBHOOK" ]; then
echo "DRIFT_DETECTED"
else
echo "PHASE_C_FULLY_IN_SYNC"
fiHandling each state:
PHASE_C_FIRST_RUN→ proceed to step 1 below.PHASE_C_LOCAL_DONE_PHASE_D_PENDING→ user ran Phase C earlier but Convex prod doesn't have env set yet (Phase D hasn't completed). Ask: "Phase C appears done locally but prod env isn't synced. Skip to Phase D?" Default: yes.PHASE_C_FULLY_IN_SYNC→.env.prodmatches Convex prod exactly. Phase C is done. Ask: "Clerk prod already configured. Skip Phase C? [type 'default' to let me decide sensible defaults]". Default: skip.DRIFT_DETECTED→ Clerk credentials in.env.proddon't match what's deployed. STOP and print this warning verbatim (do NOT prompt to skip Phase C — drift means re-sync is required):⚠ TENANT DRIFT DETECTED Clerk credentials in .env.prod don't match Convex prod env: .env.prod CLERK_JWT_ISSUER_DOMAIN: <LOCAL_ISSUER> Convex prod CLERK_JWT_ISSUER_DOMAIN: <DEPLOYED_ISSUER> .env.prod CLERK_WEBHOOK_SECRET: <whsec_...XXXX> (last 4 chars) Convex prod CLERK_WEBHOOK_SECRET: <whsec_...YYYY> (last 4 chars) Probable cause: you regenerated your Clerk prod instance or rotated keys. Tenant ID likely changed, which means FIVE things may need updating: 1. DKIM CNAMEs (dkim1, dkim2, clkmail, clerk, accounts) — tenant-specific targets change. Re-run Phase B step 4 with Clerk dashboard's new targets. 2. Publishable + Secret keys → push to Vercel prod (Phase D step 5). 3. JWT Issuer Domain → push to Convex prod (Phase D step 4). 4. Webhook Signing Secret → push to Convex prod (Phase D step 4). 5. Webhook Endpoint URL in Clerk dashboard — verify it still points to https://<prod-convex>.convex.site/clerk-webhook; re-subscribe to user.* events if the old endpoint was deleted. Continue and re-sync Convex prod + Vercel prod? (y / n / default)On
yordefault: skip the "has .env.prod got pk_live_?" re-check and jump to Phase D (which will push the new.env.prodvalues to both backends). The user is responsible for re-running Phase B step 4 (DNS CNAMEs) if the tenant ID changed — the skill prints the recommendation but can't auto-detect what the NEW tenant's CNAME targets should be (those come from Clerk dashboard).On
n: halt. User fixes.env.prodmanually (typically by pasting back the old values from Clerk dashboard) and re-runs the skill.
Steps
Steps
Domain-typo confirmation. BEFORE the user creates the Clerk prod instance, echo the domain back and require exact re-entry:
About to create a Clerk production instance for: <domain> Typos BAKE INTO the publishable key and force a full recreation (losing tenant ID, all DKIM CNAMEs, webhooks). Type your domain back EXACTLY to confirm:Reject if mismatch. This prevents the 30-minute re-do cycle the first-run reporter hit.
- Create Clerk prod instance. User opens Clerk dashboard → toggle to "Production instance" → enter confirmed domain → Create.
- Wait for Clerk SSL provisioning (may already be complete from Phase B step 5).
- Configure sign-in methods. Email (code / magic link) + optional Google. Same as dev.
- Create Convex JWT template on prod Clerk. Configure → JWT Templates → New → Convex preset. Note the new Issuer URL — it's DIFFERENT from the dev issuer.
- Create prod webhook endpoint. Webhooks → Add Endpoint →
https://<prod-convex-deployment>.convex.site/clerk-webhook(you'll have the prod Convex URL after Phase D step 1 — come back to this). Subscribe touser.created,user.updated,user.deleted. Copy the signing secret (whsec_...). GCP OAuth (optional, prod-only). If Google sign-in is desired on prod, the user needs their own Google OAuth client (Clerk's shared creds don't apply to prod):
- Google Cloud Console → APIs & Services → Credentials → Create OAuth 2.0 Client ID → type: Web application
- Authorized redirect URI (paste exactly):
https://clerk.<domain>/v1/oauth_callback - Authorized JS origin:
https://clerk.<domain> - Copy Client ID + Client Secret
- Clerk dashboard → Social Connections → Google → Custom credentials → paste values
Skip if user is OK with Email-only prod sign-in (which is fine).
Collect prod Clerk values (all four — ask one at a time with default-escape NOT offered since these are typed-confirmation secrets):
- Publishable Key (
pk_live_...) - Secret Key (
sk_live_...) - JWT Issuer Domain (prod issuer URL from step 5)
- Webhook Signing Secret (
whsec_...from step 6)
- Publishable Key (
Validate the webhook secret format before writing anything:
if [[ ! "$CLERK_WEBHOOK_PROD" =~ ^whsec_ ]]; then echo "ERROR: webhook secret must start with whsec_. You probably pasted the URL." exit 1 fiWrite
.env.prod(gitignored via.env*rule).VITE_CONVEX_URLis filled in Phase D step 3:cat > .env.prod <<EOF # Substrate production env (gitignored). # Source of truth for Convex prod + Vercel prod. Updated via /substrate:deploy. # Client-safe VITE_CONVEX_URL= VITE_CLERK_PUBLISHABLE_KEY=$CLERK_PK_LIVE # Server-only CLERK_SECRET_KEY=$CLERK_SK_LIVE CLERK_JWT_ISSUER_DOMAIN=$CLERK_ISSUER_PROD CLERK_WEBHOOK_SECRET=$CLERK_WEBHOOK_PROD EOF
Phase C checklist
Phase C — Prod Clerk Instance
✓ Domain confirmed (no typo): <domain>
✓ Prod instance created: Clerk prod for <domain>
✓ SSL cert provisioned: https://clerk.<domain>
✓ Sign-in methods enabled: Email [+ Google]
✓ JWT template created: Convex preset on prod
✓ Webhook endpoint (URL pending prod Convex in Phase D)
✓ GCP OAuth configured: yes/no (optional)
✓ Keys in .env.prod: pk_live_, sk_live_, issuer, whsec_Gate
"Continue to Phase D (prod Convex + env sync)?". Default: yes.
Phase D — Prod Convex + env sync
Goal: create prod Convex deployment, sync .env.prod values to Convex prod + Vercel prod (overwriting Phase A's dev-env temps).
Idempotency check:
npx convex env get CLERK_JWT_ISSUER_DOMAIN --prod 2>/dev/null | grep -q . && echo "PHASE_D_LIKELY_DONE"Steps
Create prod Convex deployment:
npx convex deployNote:
--prodflag was removed in recent Convex versions —convex deploytargets production by default. CI usesCONVEX_DEPLOY_KEY; interactive prod pushes refuse piped stdin.First run: prompts to create a prod deployment (name usually
project-name-prod). Convex prints the prod deployment URL.Finish the Clerk prod webhook endpoint (deferred from Phase C step 6). Update the endpoint URL in Clerk dashboard to:
https://<prod-convex-deployment>.convex.site/clerk-webhookIf already set to the dev URL, EDIT it rather than creating a new endpoint.
Update
.env.prodwith prod Convex URL:PROD_CONVEX_URL="<prod-convex-url-from-step-1>" # macOS sed sed -i '' "s|^VITE_CONVEX_URL=.*|VITE_CONVEX_URL=$PROD_CONVEX_URL|" .env.prod # Linux sed # sed -i "s|^VITE_CONVEX_URL=.*|VITE_CONVEX_URL=$PROD_CONVEX_URL|" .env.prodPush
.env.prodto Convex prod (Convex-only env vars — these are NOT pushed to Vercel):CLERK_ISSUER=$(grep "^CLERK_JWT_ISSUER_DOMAIN=" .env.prod | cut -d= -f2-) CLERK_WEBHOOK=$(grep "^CLERK_WEBHOOK_SECRET=" .env.prod | cut -d= -f2-) npx convex env set CLERK_JWT_ISSUER_DOMAIN "$CLERK_ISSUER" --prod npx convex env set CLERK_WEBHOOK_SECRET "$CLERK_WEBHOOK" --prodPush
.env.prodto Vercel prod (overwrites Phase A's dev-env temps). Vercel doesn't have an update-in-place for env vars — remove + re-add:for KEY in VITE_CONVEX_URL VITE_CLERK_PUBLISHABLE_KEY CLERK_SECRET_KEY; do VAL=$(grep "^${KEY}=" .env.prod | cut -d= -f2-) vercel env rm "$KEY" production --yes >/dev/null 2>&1 || true printf '%s' "$VAL" | vercel env add "$KEY" production doneDo NOT push
CLERK_JWT_ISSUER_DOMAINorCLERK_WEBHOOK_SECRETto Vercel — these are Convex-server-only and are already set via step 4.
Phase D checklist
Phase D — Prod Convex + Env Sync
✓ Prod Convex deployment: <prod-convex-url>
✓ Webhook endpoint fixed up: https://<prod-convex>.convex.site/clerk-webhook
✓ .env.prod VITE_CONVEX_URL: updated to prod
✓ Convex prod env: CLERK_JWT_ISSUER_DOMAIN, CLERK_WEBHOOK_SECRET set
✓ Vercel prod env (overwrote): VITE_CONVEX_URL, VITE_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEYGate
"Continue to Phase E (redeploy + verify)?". Default: yes.
Phase E — Redeploy + verify
Goal: redeploy with prod credentials; user confirms end-to-end prod sign-in on the custom domain.
Steps
Trigger redeploy. Either:
vercel --prod --yesOR push an empty commit to trigger Vercel's git integration:
git commit --allow-empty -m "chore: redeploy with prod env" git push origin main- Wait for build (~1–3 min).
Verify on custom domain. Tell the user:
Open https://<domain>. Sign in via prod Clerk (Email or Google). Confirm you land on an authenticated page with no console errors. Did prod sign-in work end-to-end? (y/n)If
n, diagnose in this order:- Clerk allowlist missing custom domain → Clerk dashboard → Domains → add
https://<domain> - Prod Clerk webhook URL mismatches
.env.prod→ Clerk dashboard → Webhooks → verify endpoint URL matcheshttps://<prod-convex>.convex.site/clerk-webhook - Vercel prod env not refreshed →
vercel env ls productionand re-run Phase D step 5 if values look dev-ish - Convex prod env not set →
npx convex env get CLERK_JWT_ISSUER_DOMAIN --prodshould return the prod issuer; if empty, re-run Phase D step 4 - SPA route 404 → confirm
vercel.jsonwith SPA rewrite is committed (shipped in the scaffold; if missing, add before redeploying) - Clerk sign-in redirects to
/sign-up/verify-email-addressand 404s → ensure<SignIn/>/<SignUp/>userouting="virtual"(frontend-doctrine §4.2a)
- Clerk allowlist missing custom domain → Clerk dashboard → Domains → add
Final handoff
✔ Substrate production deploy complete.
Clerk prod: https://clerk.<domain>
Convex prod: <prod-convex-url>
GitHub: <repo-url>
Vercel: <vercel-url>
Live URL: https://<domain>
Auto-deploy: enabled — every push to main → rebuild
Env staging: .env.prod (gitignored, sync via /substrate:deploy re-run)
Next:
- git push to redeploy any time
- /substrate:quick-spec or /substrate:architect-spec to ship features
- Rotating keys / Clerk tenant changes? Update .env.prod and re-run
Phase D to sync.Constraints
- MUST verify migration is complete at the stage gate. Deploying the welcome screen is worthless.
- MUST run idempotency check at the start of each phase. If done, offer to skip; don't force re-work.
- MUST print each phase's checklist before the gate. Gates are user-review checkpoints.
- MUST pause at each phase gate for explicit y/n/default approval. Non-negotiable.
- MUST perform domain-typo confirmation before Clerk prod create (Phase C step 1). This is the single biggest footgun in the flow.
- MUST perform tenant-drift detection at Phase C start (diff
.env.prodagainstnpx convex env get --prod). IfDRIFT_DETECTED, print the full re-sync guidance and do NOT offer to skip Phase C — drift means Convex prod is stale. - MUST write
.env.prodin Phase C, read from it in Phase D..env.prodis the source of truth for production env staging. - MUST NOT commit
.env.prod— gitignored via.env*rule. - MUST NOT push secret keys (Clerk Secret Key, webhook secret, Convex deploy key) to the client bundle.
- MUST NOT push
CLERK_JWT_ISSUER_DOMAINorCLERK_WEBHOOK_SECRETas Vite env vars — these are Convex-server-only, set vianpx convex env set ... --prod. - MUST NOT force-push to remote main.
- MUST validate the webhook secret format (
^whsec_) in Phase C step 9 before any write. - MUST NOT run dev Clerk setup — that belongs to
/substrate:migrate. If.env.locallacks Clerk values, halt and redirect to migrate. - SHOULD tolerate partial progress: if the user has done some steps manually (e.g. bought the domain via dashboard), skip those steps rather than re-running and overwriting.
- SHOULD narrate context clearly when the user switches between terminal, Clerk dashboard, GCP Console, Vercel dashboard, and DNS provider.
- SHOULD offer the default-escape suffix
[type 'default' to let me decide sensible defaults]on Socratic questions (repo slug, visibility, domain decisions). Typed confirmations (Clerk keys, domain-name retype) are NOT defaultable — deliberate manual inputs.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

