From c440ff072ec18ac5642230493445c85bba748706 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Fri, 17 Jul 2026 11:56:28 -0700 Subject: [PATCH] Pin transitive tailwindcss dep in email rendering to stop sanity-test mismatches The js-execution sanity test compares rendered email output from Freestyle and Vercel Sandbox byte-for-byte. Both engines install nodeModules independently, and @react-email/tailwind declares tailwindcss with a caret range, so each new tailwindcss release created a window where the two engines rendered byte-different HTML (4.3.3 emits "margin:0px" where 4.3.2 emitted "margin:0"). Verified against both live engines that pinning tailwindcss makes their outputs byte-identical. --- apps/backend/src/lib/email-rendering.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/backend/src/lib/email-rendering.tsx b/apps/backend/src/lib/email-rendering.tsx index 59e04640a..d79be5d55 100644 --- a/apps/backend/src/lib/email-rendering.tsx +++ b/apps/backend/src/lib/email-rendering.tsx @@ -56,6 +56,15 @@ const nodeModules = { "react": "19.1.1", "@react-email/components": "1.0.6", "arktype": "2.1.20", + // tailwindcss is a transitive dep (@react-email/tailwind wants "^4.1.18") that must be pinned + // exactly: executeJavascript runs this bundle on two engines (Freestyle and Vercel Sandbox) that + // install node_modules independently, so when a new matching tailwindcss version was published, one + // engine picked it up before the other and the rendered HTML differed byte-wise (4.3.3 emits + // "margin:0px" where 4.3.2 emitted "margin:0"), tripping the js-execution sanity test on + // essentially every run. Pinning it here dedupes the transitive dep onto one exact version on both + // engines. Other transitive deps still float via caret ranges; if the sanity test starts firing + // again with byte-different HTML, find the drifted package and pin it here the same way. + "tailwindcss": "4.3.3", }; const entryJs = deindent`