From c440ff072ec18ac5642230493445c85bba748706 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Fri, 17 Jul 2026 11:56:28 -0700 Subject: [PATCH 1/2] 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` From 6d22a9b13d2d321311f86d47b3dca160fea24e61 Mon Sep 17 00:00:00 2001 From: Bilal Godil Date: Fri, 17 Jul 2026 14:05:41 -0700 Subject: [PATCH 2/2] Shorten tailwindcss pin comment --- apps/backend/src/lib/email-rendering.tsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/backend/src/lib/email-rendering.tsx b/apps/backend/src/lib/email-rendering.tsx index d79be5d55..efb6c1d35 100644 --- a/apps/backend/src/lib/email-rendering.tsx +++ b/apps/backend/src/lib/email-rendering.tsx @@ -56,14 +56,10 @@ 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. + // Transitive dep of @react-email/tailwind (declared as a caret range there). Pinned exactly + // because the two js-execution engines install node_modules independently, so a new tailwindcss + // release makes them render byte-different HTML and trip the sanity test. If the sanity test + // fires again with byte-different HTML, find the drifted transitive dep and pin it here too. "tailwindcss": "4.3.3", };