Setting Up Domains With Porkbun And Vercel

Use this skill when a product fork needs a custom domain or subdomain managed in Porkbun and served by Vercel.

Required secrets

Porkbun DNS API calls require both values:

  • PORKBUN_API_KEY
  • PORKBUN_SECRET_API_KEY

Save them in the product repo's gitignored .env.local. When syncing to Vercel, always pipe with printf %s so no trailing newline is stored:

printf %s "$PORKBUN_API_KEY" | vercel env add PORKBUN_API_KEY production
printf %s "$PORKBUN_SECRET_API_KEY" | vercel env add PORKBUN_SECRET_API_KEY production

Repeat for development, preview, or branch-scoped preview as needed.

Workflow

  1. Confirm the product repo is linked to the intended Vercel project:
    vercel project ls
    vercel domains add crm.unionstreet.ai --scope unstairesearch
    
  2. Create the Porkbun DNS record:
    • Domain: unionstreet.ai
    • Type: CNAME
    • Name: crm
    • Content: cname.vercel-dns.com
    • TTL: 600
  3. If a conflicting crm.unionstreet.ai record exists, delete or replace it before creating the CNAME.
  4. Assign the alias to the intended Vercel deployment if Vercel does not do it automatically:
    vercel alias set crm-crige6ea4-unstairesearch.vercel.app crm.unionstreet.ai --scope unstairesearch
    
  5. Verify DNS and HTTPS:
    dig +short crm.unionstreet.ai CNAME @1.1.1.1
    curl -sS -I https://crm.unionstreet.ai
    

Porkbun API pattern

Porkbun API v3 uses JSON POST bodies with apikey and secretapikey.

await fetch("https://api.porkbun.com/api/json/v3/dns/create/unionstreet.ai", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    apikey: process.env.PORKBUN_API_KEY,
    secretapikey: process.env.PORKBUN_SECRET_API_KEY,
    type: "CNAME",
    name: "crm",
    content: "cname.vercel-dns.com",
    ttl: "600",
  }),
})

Use /dns/retrieve/<domain> first to inspect current records and /dns/delete/<domain>/<recordId> to remove conflicts.

Validation rules

  • Do not print raw secrets in logs or final answers.
  • Verify .env.local is ignored with git check-ignore -v .env.local.
  • Use branch-scoped Vercel preview env vars for feature branches.
  • Treat http://... redirecting to HTTPS as partial success; final success is https://... returning a product response.
  • If curl https://... fails immediately after DNS creation, wait briefly and recheck Vercel alias/domain state. Certificate issuance can lag DNS by a minute or two.