Recipe — Sentry + Resend setup
Wire production error tracking and transactional email together in one sitting.
These two integrations belong in the same recipe because both are critical-day-one and both are no-ops without configuration. A production cartwright deploy without Sentry is flying blind; without Resend you cannot send receipts.
Sentry
-
Create a Sentry project. sentry.io → Create Project → Next.js platform → name it after your shop.
-
Copy the DSN. Sentry shows you a
https://<key>@o<org>.ingest.sentry.io/<project>URL. You need this twice: as the server DSN (private) and the client DSN (public).For most setups the two values are the same DSN string — Sentry's UI may show a distinct "public" DSN under the project's client SDK config.
-
Set the env vars in Vercel (Production scope only).
SENTRY_DSN="https://...@...ingest.sentry.io/..." NEXT_PUBLIC_SENTRY_DSN="https://...@...ingest.sentry.io/..."Skip Preview-scope Sentry. Preview deploys generate noise — every PR sends test errors to the same project, drowning real production signal.
-
Wire source-map upload. Cartwright reads
SENTRY_ORG,SENTRY_PROJECT,SENTRY_AUTH_TOKENduring build to upload sourcemaps. Generate the token at sentry.io → Settings → Auth Tokens with scopesproject:releases+org:read.SENTRY_ORG="my-org" SENTRY_PROJECT="my-shop" SENTRY_AUTH_TOKEN="sntrys_..."Set these in Vercel Production env. They are build-time only.
-
Verify error capture. Deploy. Trigger a real error path (a non-existent product slug works) and watch Sentry's Issues page. The error should land within seconds, with sourcemap-resolved stack frames.
Cartwright does not ship a dedicated /api/sentry-test-error route. Validate by triggering a real error (404 path, intentionally bad checkout input, etc.) rather than expecting a test endpoint.
Sentry sample-rate tuning
For a small shop, leaving tracesSampleRate at 1.0 is fine — Sentry's free tier handles hobby traffic without trouble. Once you cross ~10k orders/month, drop it to 0.1 (10%) in instrumentation-client.ts and sentry.server.config.ts. Errors are always 100%; only performance traces sample.
Resend
-
Create a Resend account at resend.com. The free tier ships 3000 emails/month — fine for most cartwright shops.
-
Add and verify your domain. Resend dashboard → Domains → Add Domain. Resend gives you SPF and DKIM records.
-
Add the DNS records at your domain registrar (Porkbun, Cloudflare, etc.). The records are TXT entries. Save and wait for propagation — usually under 30 minutes.
-
Verify in Resend. Click "Verify" in the Resend dashboard. It re-checks DNS and flips the domain to verified.
-
Send a test email from the Resend dashboard to your inbox. If it lands, your sender reputation is intact.
-
Generate an API key. Resend dashboard → API Keys → Create. Restrict it to "Sending access" only.
-
Set the env var in Vercel (Production).
RESEND_API_KEY="re_..." -
Align the from-address. In
brand.config.ts:emails.fromandemails.fromName, set values that match a verified Resend sender. Mismatches cause silent send failures — the order completes, but the receipt never arrives. -
Trigger a real customer email. Place a test order in Stripe test mode (see Stripe test mode recipe). The receipt template should render with your palette and the customer should receive it within a few seconds.
What good looks like after this recipe
- Sentry shows your deploy as a release. Any 500-level error in the next hour lands in Issues with a sourcemap-resolved trace.
- A test order generates a receipt email that reaches a real inbox, not a spam folder, with
Authentication-Results: passin the headers. brand.config.ts:emails.fromis identical to a Resend verified sender.