This checklist covers only external provider setup (Vercel, Neon, Clerk, Stripe, Twilio) for the shipping baseline commit:
169303c(finish: production hardening + compliance + docs)
Set these in Vercel Project Settings -> Environment Variables.
NEXT_PUBLIC_APP_URL- Where to find value: your production app domain (for example
https://app.example.com) - Must be full
https://URL.
- Where to find value: your production app domain (for example
DEBUG_ENV_ENDPOINT_TOKEN(optional)- Where to find value: generated by you (random secret string).
PORTFOLIO_DEMO_MODE(optional)- Where to find value: set by you only if intentionally using demo mode.
DATABASE_URL- Where to find value: Neon Console -> Project -> Connection Details -> pooled connection string.
DIRECT_DATABASE_URL- Where to find value: Neon Console -> Project -> Connection Details -> direct (non-pooler) connection string.
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY- Where to find value: Clerk Dashboard -> API Keys -> Publishable key.
CLERK_SECRET_KEY- Where to find value: Clerk Dashboard -> API Keys -> Secret key.
NEXT_PUBLIC_CLERK_SIGN_IN_URL(optional)- Where to find value: your app route, usually
/sign-in.
- Where to find value: your app route, usually
NEXT_PUBLIC_CLERK_SIGN_UP_URL(optional)- Where to find value: your app route, usually
/sign-up.
- Where to find value: your app route, usually
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY- Where to find value: Stripe Dashboard -> Developers -> API keys -> Publishable key.
STRIPE_SECRET_KEY- Where to find value: Stripe Dashboard -> Developers -> API keys -> Secret key.
STRIPE_WEBHOOK_SECRET- Where to find value: Stripe Dashboard -> Developers -> Webhooks -> endpoint signing secret.
STRIPE_PRICE_STARTER- Where to find value: Stripe Dashboard -> Product catalog -> Starter price ID (
price_...).
- Where to find value: Stripe Dashboard -> Product catalog -> Starter price ID (
STRIPE_PRICE_PRO- Where to find value: Stripe Dashboard -> Product catalog -> Pro price ID (
price_...).
- Where to find value: Stripe Dashboard -> Product catalog -> Pro price ID (
TWILIO_ACCOUNT_SID- Where to find value: Twilio Console -> Account Info -> Account SID.
TWILIO_AUTH_TOKEN- Where to find value: Twilio Console -> Account Info -> Auth Token.
- Use the parent-account auth token. CallbackCloser uses it for managed subaccount provisioning, Messaging Service setup, and parent/subaccount webhook signature validation.
TWILIO_WEBHOOK_AUTH_TOKEN- Where to find value: generated by you (optional secret used only for local/non-production token-mode webhook auth).
TWILIO_VALIDATE_SIGNATURE(required in prod; set totrue)- Where to find value: set by you (
true).
- Where to find value: set by you (
Run after production env vars are set:
npx prisma migrate deploy
npm run db:smokeOptional quick checks:
npm run env:check
npm run preflight:providers
npm run typecheckIn Clerk Dashboard, add production URLs based on NEXT_PUBLIC_APP_URL:
- Sign-in redirect URL:
NEXT_PUBLIC_APP_URL/sign-in - Sign-up redirect URL:
NEXT_PUBLIC_APP_URL/sign-up - Allowed origins:
NEXT_PUBLIC_APP_URL - Allowed redirect URLs: include both sign-in and sign-up URLs above.
Create webhook endpoint:
- Endpoint URL:
NEXT_PUBLIC_APP_URL/api/stripe/webhook
Enable these events (from app/api/stripe/webhook/route.ts):
checkout.session.completedcustomer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_failedinvoice.payment_succeeded
Replace placeholders:
NEXT_PUBLIC_APP_URL-> your production domain
Voice (A CALL COMES IN, POST):
NEXT_PUBLIC_APP_URL/api/twilio/voice
Messaging (A MESSAGE COMES IN, POST):
NEXT_PUBLIC_APP_URL/api/twilio/sms
Status callback URL (used by TwiML <Dial action> and recording status callback):
NEXT_PUBLIC_APP_URL/api/twilio/status
- Answered call path:
- Call Twilio number and answer forwarded call.
- Expected: call is forwarded; lead may not be created as missed.
- Missed call path:
- Call Twilio number and do not answer forwarded call.
- Expected:
Leadcreated, initial SMS sent (if billing active and recipient not opted out).
- SMS compliance:
- Reply
HELP. - Expected: help message returned with app instructions.
- Reply
STOP. - Expected: unsubscribe confirmation, future outbound SMS suppressed for that sender.
- Reply
START. - Expected: opt-in confirmation and outbound eligibility restored.
- Reply
- Recording validation:
- Complete an answered forwarded call long enough to produce recording.
- Expected:
Callrow contains recording metadata (recordingSid,recordingUrl,recordingStatus,recordingDurationSeconds).
- Logs validation:
- Check Vercel logs for
twilio.voice,twilio.status,twilio.sms,twilio.messaging,twilio.webhook-authand ensure no unexpected401/DB errors.
- Check Vercel logs for
- CallbackCloser now automates Twilio subaccount creation, Messaging Service creation, number assignment, and webhook sync for the managed new-number path.
- Existing-number onboarding is still admin-assisted and expects the number to already live in the target Twilio account context.
- US long-code messaging still requires A2P brand/campaign approval. Treat businesses in “brand submitted” or “campaign pending review” as onboarding, not live.
- If a business is stuck in pending or rejected state, record the exact Twilio/A2P note in the admin A2P failure field and keep the business out of
LIVEuntil approval is complete.
Output from npm run env:check:
CallbackCloser env check
- Loaded env files: .env, .env.local
- TWILIO_VALIDATE_SIGNATURE: enabled
- Result: PASS (all required env vars are present)
Output from npm run webhooks:print:
CallbackCloser Twilio webhook URLs
- Loaded env files: .env, .env.local
- Base URL: https://dermal-fontal-branson.ngrok-free.dev
- Auth mode: signature validation
- Token display: redacted (default)
Voice (A CALL COMES IN, POST): https://dermal-fontal-branson.ngrok-free.dev/api/twilio/voice
Messaging (A MESSAGE COMES IN, POST): https://dermal-fontal-branson.ngrok-free.dev/api/twilio/sms
Status callback (Twilio Number statusCallback + <Dial action>, POST): https://dermal-fontal-branson.ngrok-free.dev/api/twilio/status