<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ShipInAnHour</title>
    <description>The latest articles on DEV Community by ShipInAnHour (@shipinanhour).</description>
    <link>https://dev.to/shipinanhour</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4193175%2F7fb6e504-b535-4754-9473-43bbd30e2fb8.png</url>
      <title>DEV Community: ShipInAnHour</title>
      <link>https://dev.to/shipinanhour</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shipinanhour"/>
    <language>en</language>
    <item>
      <title>Next.js 16 + Tailwind v4: 5 traps AI coding assistants keep hitting (and the prompts that fix them)</title>
      <dc:creator>ShipInAnHour</dc:creator>
      <pubDate>Mon, 19 Oct 2026 04:08:16 +0000</pubDate>
      <link>https://dev.to/shipinanhour/nextjs-16-tailwind-v4-5-traps-ai-coding-assistants-keep-hitting-and-the-prompts-that-fix-them-3ioc</link>
      <guid>https://dev.to/shipinanhour/nextjs-16-tailwind-v4-5-traps-ai-coding-assistants-keep-hitting-and-the-prompts-that-fix-them-3ioc</guid>
      <description>&lt;p&gt;A fresh &lt;code&gt;create-next-app&lt;/code&gt; in late 2026 gives you Next.js 16 and Tailwind CSS v4. Most AI coding assistants learned on years of Next 13–15 and Tailwind v3 code. That gap produces the same handful of failures again and again, and they often show up only at &lt;code&gt;npm run build&lt;/code&gt;, or only on a laptop set to dark mode.&lt;/p&gt;

&lt;p&gt;Below are five of them. For each one you get the symptom (with the exact error text where there is one), why the assistant gets it wrong, the fix, and a short prompt you can paste into Cursor, Claude Code, or ChatGPT.&lt;/p&gt;

&lt;p&gt;Versions used: &lt;code&gt;create-next-app&lt;/code&gt; 16.4.2 (Next.js 16.4.2, React 19.3), Tailwind CSS 4.3, Node 20.&lt;/p&gt;




&lt;h2&gt;
  
  
  Trap 1: &lt;code&gt;npm run build&lt;/code&gt; fails on a brand-new app (&lt;code&gt;cacheComponents&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; &lt;code&gt;npm run dev&lt;/code&gt; looks fine, then the build fails with one of these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route segment config "dynamic" is not compatible with `nextConfig.cacheComponents`. Please remove it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route "/expenses": Next.js encountered the unstable value `new Date()` in a Client Component.

This value would be evaluated during the prerender, instead of recomputed on each visit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why the assistant gets it wrong.&lt;/strong&gt; With its recommended defaults (&lt;code&gt;--yes&lt;/code&gt;), &lt;code&gt;create-next-app&lt;/code&gt; 16.4 now writes this into &lt;code&gt;next.config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;cacheComponents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;partialPrefetching&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;turbopack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* … Tailwind CSS loader … */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Next.js caching docs say it directly: new App Router apps made with the recommended defaults "already have Cache Components and Partial Prefetching enabled." The assistant doesn't know this. It reaches for the Next 13–15 habit of &lt;code&gt;export const dynamic = "force-dynamic"&lt;/code&gt;, which Cache Components rejects, or it puts &lt;code&gt;new Date()&lt;/code&gt; in a component that now gets prerendered.&lt;/p&gt;

&lt;p&gt;In our test runs, both of our sample apps failed &lt;code&gt;npm run build&lt;/code&gt; at this point. One failed on the &lt;code&gt;dynamic&lt;/code&gt; export and one on a &lt;code&gt;new Date()&lt;/code&gt; default for a date input. The fix that worked was removing the two config lines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix, option A: opt out&lt;/strong&gt; (fine for a localStorage app or a small landing page):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// next.config.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// removed: cacheComponents: true,&lt;/span&gt;
  &lt;span class="c1"&gt;// removed: partialPrefetching: true,&lt;/span&gt;
  &lt;span class="na"&gt;turbopack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* keep this block: it loads Tailwind */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also scaffold without it. In our check, the 16.4.2 CLI accepted &lt;code&gt;--no-cache-components&lt;/code&gt; even though &lt;code&gt;--help&lt;/code&gt; doesn't list it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest my-app &lt;span class="nt"&gt;--ts&lt;/span&gt; &lt;span class="nt"&gt;--tailwind&lt;/span&gt; &lt;span class="nt"&gt;--eslint&lt;/span&gt; &lt;span class="nt"&gt;--app&lt;/span&gt; &lt;span class="nt"&gt;--use-npm&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-components&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After either change, delete &lt;code&gt;.next/&lt;/code&gt; and rebuild.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix, option B: keep Cache Components and do it its way.&lt;/strong&gt; Remove the &lt;code&gt;dynamic&lt;/code&gt; export. The migration guide says to drop &lt;code&gt;force-dynamic&lt;/code&gt;, because uncached work already runs at request time. Then put the request-time part behind &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; and &lt;code&gt;await connection()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SignupCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// render at request time&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getTotal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; people joined&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;…&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SignupCount&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;npm run build&lt;/code&gt; fails with "Route segment config "dynamic" is not compatible with nextConfig.cacheComponents" or "encountered the unstable value &lt;code&gt;new Date()&lt;/code&gt;". This is Next.js 16, and &lt;code&gt;create-next-app&lt;/code&gt; enabled &lt;code&gt;cacheComponents&lt;/code&gt; by default. Open &lt;code&gt;next.config.ts&lt;/code&gt;, remove &lt;code&gt;cacheComponents: true&lt;/code&gt; and &lt;code&gt;partialPrefetching: true&lt;/code&gt;, and keep the &lt;code&gt;turbopack&lt;/code&gt; block. Make sure no component calls &lt;code&gt;new Date()&lt;/code&gt;, &lt;code&gt;Date.now()&lt;/code&gt;, or &lt;code&gt;Math.random()&lt;/code&gt; while rendering. Delete &lt;code&gt;.next/&lt;/code&gt; and re-run the build until it passes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Trap 2: &lt;code&gt;new Date()&lt;/code&gt; and &lt;code&gt;localStorage&lt;/code&gt; during render (and the lint errors after you fix it)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; Hydration warnings. Data that flashes and disappears. A "today" date that is one day off. A default month that is frozen at whatever month you ran the build in. Once you fix those, &lt;code&gt;npm run lint&lt;/code&gt; fails with &lt;code&gt;react-hooks/set-state-in-effect&lt;/code&gt; or &lt;code&gt;react-hooks/purity&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the assistant gets it wrong.&lt;/strong&gt; Its go-to patterns are &lt;code&gt;useState(new Date())&lt;/code&gt;, &lt;code&gt;useState(() =&amp;gt; JSON.parse(localStorage.getItem(...)))&lt;/code&gt;, and &lt;code&gt;new Date().toISOString().slice(0, 10)&lt;/code&gt; for "today." All three either run during server prerendering or quietly use UTC. A common reflex is a &lt;code&gt;mounted&lt;/code&gt; flag that renders "Loading…" until the effect runs. In our test runs that didn't help. The &lt;code&gt;useState&lt;/code&gt; initializers still ran during prerender, and the build still failed.&lt;/p&gt;

&lt;p&gt;Two more things from the test runs. A month default set during render ended up baked into the static HTML. Then the standard fix (empty state, load in &lt;code&gt;useEffect&lt;/code&gt;) produced &lt;strong&gt;10&lt;/strong&gt; &lt;code&gt;react-hooks/set-state-in-effect&lt;/code&gt; errors under the ESLint config that Next 16 ships, which includes eslint-plugin-react-hooks 7.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix.&lt;/strong&gt; Start with empty state and read browser values in an effect or an event handler. That is also the "[defer]" option Next's own error message suggests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;expenses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setExpenses&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Expense&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setExpenses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loadExpenses&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// reads localStorage on the client only&lt;/span&gt;
  &lt;span class="nf"&gt;setDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;todayISO&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build "today" from local time, not &lt;code&gt;toISOString()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;todayISO&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMonth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDate&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;padStart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the lint rule you have two honest options. If loading from &lt;code&gt;localStorage&lt;/code&gt; once on mount is intentional, turn off just that rule and leave a comment saying why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint.config.mjs&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Loading from localStorage once on mount is intentional in this app.&lt;/span&gt;
  &lt;span class="nl"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-hooks/set-state-in-effect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or design the effect away: derive the value, let CSS handle it (see Trap 4), or do the work in a handler. For &lt;code&gt;react-hooks/purity&lt;/code&gt;, take &lt;code&gt;Date.now()&lt;/code&gt; out of the component body and compute time-based values on the server, in a Route Handler or a server-only &lt;code&gt;lib/&lt;/code&gt; helper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;House rule for this project: never read &lt;code&gt;localStorage&lt;/code&gt; or call &lt;code&gt;new Date()&lt;/code&gt;/&lt;code&gt;Date.now()&lt;/code&gt; during render or in a &lt;code&gt;useState(...)&lt;/code&gt; initial value. Start state empty (&lt;code&gt;[]&lt;/code&gt; / &lt;code&gt;""&lt;/code&gt;) and load it in &lt;code&gt;useEffect&lt;/code&gt; or in a click/submit handler. Store dates as local &lt;code&gt;YYYY-MM-DD&lt;/code&gt; and never use &lt;code&gt;toISOString()&lt;/code&gt; for "today." A mounted-flag "Loading…" gate is not enough on its own. Then run &lt;code&gt;npm run lint&lt;/code&gt; and &lt;code&gt;npm run build&lt;/code&gt; and fix what they report.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Trap 3: The scaffold's CSS makes your app unreadable in dark mode, and borders look black
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; On a computer set to dark mode, the page is near-black with light text, and your new &lt;code&gt;bg-white&lt;/code&gt; cards show light text on white. Every &lt;code&gt;border&lt;/code&gt; looks dark.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the assistant gets it wrong.&lt;/strong&gt; It builds on top of the template's &lt;code&gt;app/globals.css&lt;/code&gt; without reading it. In 16.4.2 that file includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefers-color-scheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0a0a0a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ededed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--foreground&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On top of that, Tailwind v4 changed the default border color from &lt;code&gt;gray-200&lt;/code&gt; to &lt;code&gt;currentColor&lt;/code&gt; (see the upgrade guide's "Default border color" section). v3-trained assistants assume borders are a soft gray. In our test runs, both problems showed up in the final QA pass: the UI was unreadable on a dark-mode OS, and the borders defaulted to black.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix.&lt;/strong&gt; Replace &lt;code&gt;globals.css&lt;/code&gt; with a minimal version and set colors on &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--color-neutral-200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-neutral-50 text-neutral-900"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Text is unreadable on a computer set to dark mode, and all borders look black. In &lt;code&gt;app/globals.css&lt;/code&gt;, remove the default &lt;code&gt;:root&lt;/code&gt;, &lt;code&gt;prefers-color-scheme&lt;/code&gt;, and &lt;code&gt;body&lt;/code&gt; rules. Keep &lt;code&gt;@import "tailwindcss";&lt;/code&gt; and add &lt;code&gt;@layer base { *, ::before, ::after { border-color: var(--color-neutral-200); } }&lt;/code&gt;. Put &lt;code&gt;bg-neutral-50 text-neutral-900&lt;/code&gt; on &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;. Tailwind only, no UI library.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Trap 4: The dark-mode toggle does nothing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; You click the toggle and nothing changes, or the page only goes dark when the OS is already dark. After a refresh you get a white flash.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the assistant gets it wrong.&lt;/strong&gt; In Tailwind v3 you set &lt;code&gt;darkMode: "class"&lt;/code&gt; in &lt;code&gt;tailwind.config.js&lt;/code&gt;. In v4, &lt;code&gt;dark:&lt;/code&gt; follows &lt;code&gt;prefers-color-scheme&lt;/code&gt; by default, and class-based toggling is configured in CSS. Assistants still write the v3 config, or toggle the class on &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; instead of &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;. When we compiled Tailwind 4.3 without the override, &lt;code&gt;dark:&lt;/code&gt; utilities came out inside a &lt;code&gt;prefers-color-scheme&lt;/code&gt; media query, so a &lt;code&gt;.dark&lt;/code&gt; class had no effect. Our budget-app test run hit exactly this: the toggle did nothing until we added &lt;code&gt;@custom-variant dark&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix.&lt;/strong&gt; This one line is from the Tailwind dark-mode docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@custom-variant&lt;/span&gt; &lt;span class="n"&gt;dark&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(.&lt;/span&gt;&lt;span class="n"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dark&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Toggle the class on &lt;code&gt;document.documentElement&lt;/code&gt;. Apply the saved theme before first paint with a small inline script, and let CSS pick the icon so there's no React state to mismatch on hydration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/layout.tsx&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;themeScript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`try{if(localStorage.getItem("theme")==="dark")document.documentElement.classList.add("dark")}catch(e){}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;suppressHydrationWarning&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;themeScript&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  …
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/ThemeToggle.tsx&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ThemeToggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;theme&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;toggle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Toggle dark mode"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark:hidden"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;🌙&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hidden dark:inline"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;☀️&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CSS-picked icon also avoids the &lt;code&gt;set-state-in-effect&lt;/code&gt; lint error from Trap 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The dark-mode toggle does nothing. This is Tailwind v4: there is no &lt;code&gt;darkMode&lt;/code&gt; setting in a JS config. Add &lt;code&gt;@custom-variant dark (&amp;amp;:where(.dark, .dark *));&lt;/code&gt; to &lt;code&gt;globals.css&lt;/code&gt;. Toggle the &lt;code&gt;dark&lt;/code&gt; class on &lt;code&gt;document.documentElement&lt;/code&gt;, not &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;. Add an inline &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; script that applies the saved theme before paint, and add &lt;code&gt;suppressHydrationWarning&lt;/code&gt; on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;. Choose the icon with &lt;code&gt;dark:hidden&lt;/code&gt; / &lt;code&gt;hidden dark:inline&lt;/code&gt; instead of React state. Then add missing &lt;code&gt;dark:&lt;/code&gt; classes to cards, inputs, and the header.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Trap 5: Tailwind v3 habits (gradients, renamed utilities, the JS config)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom.&lt;/strong&gt; Shadows, corners, and blurs look slightly off. A custom brand color or gradient you asked for doesn't appear. The assistant creates a &lt;code&gt;tailwind.config.js&lt;/code&gt; or adds &lt;code&gt;@tailwind base;&lt;/code&gt; lines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why the assistant gets it wrong.&lt;/strong&gt; Most of the Tailwind in its training data is v3. A common trap is a mix of v3 and v4 syntax:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;v3 habit&lt;/th&gt;
&lt;th&gt;v4&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bg-gradient-to-r&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;bg-linear-to-r&lt;/code&gt; (renamed in v4.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;shadow-sm&lt;/code&gt; / &lt;code&gt;shadow&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;shadow-xs&lt;/code&gt; / &lt;code&gt;shadow-sm&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;rounded-sm&lt;/code&gt; / &lt;code&gt;rounded&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rounded-xs&lt;/code&gt; / &lt;code&gt;rounded-sm&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;outline-none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;outline-hidden&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ring&lt;/code&gt; (3px)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ring-3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@tailwind base; …&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@import "tailwindcss";&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;tailwind.config.js&lt;/code&gt; theme&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@theme { … }&lt;/code&gt; in CSS (JS config only loads via &lt;code&gt;@config&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To be fair to &lt;code&gt;bg-gradient-to-r&lt;/code&gt;: when we compiled it with Tailwind 4.3, it still produced CSS as a legacy alias. The v4 docs only use &lt;code&gt;bg-linear-*&lt;/code&gt; (along with the new &lt;code&gt;bg-radial-*&lt;/code&gt; and &lt;code&gt;bg-conic-*&lt;/code&gt;), so standardize on that. A more common reason a gradient "doesn't show up" is that its colors are defined in a &lt;code&gt;tailwind.config.js&lt;/code&gt; that v4 never loads, so classes like &lt;code&gt;from-brand&lt;/code&gt; are never generated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix.&lt;/strong&gt; Define custom colors in CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@theme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-brand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#7c3aed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-linear-to-r from-brand to-pink-600 bg-clip-text text-transparent"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Ship it
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This project uses Tailwind CSS v4, not v3. Don't create &lt;code&gt;tailwind.config.js&lt;/code&gt; or use &lt;code&gt;@tailwind&lt;/code&gt; directives. Theme values go in &lt;code&gt;@theme&lt;/code&gt; in &lt;code&gt;globals.css&lt;/code&gt;. Use v4 names: &lt;code&gt;bg-linear-to-*&lt;/code&gt; instead of &lt;code&gt;bg-gradient-to-*&lt;/code&gt;, &lt;code&gt;shadow-xs&lt;/code&gt;/&lt;code&gt;rounded-xs&lt;/code&gt; for the old &lt;code&gt;-sm&lt;/code&gt; sizes, &lt;code&gt;outline-hidden&lt;/code&gt; instead of &lt;code&gt;outline-none&lt;/code&gt;. Gradient text needs &lt;code&gt;bg-clip-text text-transparent&lt;/code&gt;. Search the codebase for v3 names and replace them.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Two smaller ones worth adding to your rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Internal links.&lt;/strong&gt; &lt;code&gt;&amp;lt;a href="/#features"&amp;gt;&lt;/code&gt; triggers &lt;code&gt;@next/next/no-html-link-for-pages&lt;/code&gt; in &lt;code&gt;npm run lint&lt;/code&gt;. In one test run it produced 6 errors. Use &lt;code&gt;&amp;lt;Link href="/#features"&amp;gt;&lt;/code&gt; from &lt;code&gt;next/link&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;searchParams&lt;/code&gt; is a Promise.&lt;/strong&gt; Type it as &lt;code&gt;searchParams: Promise&amp;lt;Record&amp;lt;string, string | string[] | undefined&amp;gt;&amp;gt;&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; it. Assistants still destructure it synchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Make it stick
&lt;/h2&gt;

&lt;p&gt;Fixing these one at a time works, but the cheaper move is to stop the assistant from writing them in the first place. Put the house rules in a file your tool reads on every request: &lt;code&gt;AGENTS.md&lt;/code&gt; at the project root (Cursor reads it, and so do recent Claude Code versions when there's no &lt;code&gt;CLAUDE.md&lt;/code&gt;) or a &lt;code&gt;.cursor/rules/*.mdc&lt;/code&gt; file with &lt;code&gt;alwaysApply: true&lt;/code&gt;. &lt;code&gt;create-next-app&lt;/code&gt; 16.4 already generates an &lt;code&gt;AGENTS.md&lt;/code&gt; that tells agents to read the bundled docs in &lt;code&gt;node_modules/next/dist/docs/&lt;/code&gt;. Add your rules below that block. Then make &lt;code&gt;npm run lint &amp;amp;&amp;amp; npm run build&lt;/code&gt; the final checkpoint of every session, because that is where most of these failures show up.&lt;/p&gt;

&lt;p&gt;If you want these as ready-to-paste prompts, there's a free sample with four of them: the scaffold, the Tailwind v4 dark-mode toggle, and the build-failure and colors/gradients rescues. It's here: &lt;a href="https://shipinanhour.gumroad.com/l/qfzgeg" rel="noopener noreferrer"&gt;https://shipinanhour.gumroad.com/l/qfzgeg&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tailwindcss</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
