I've been building a React component library along with a playground site where people can preview each component before dropping it into their own project. Pretty standard setup: a docs page for every component, a live preview area, code snippets, the usual.
While building the documentation pages, I ran into this error in the console:
Text content does not match server-rendered HTML. Warning: Text content did not match. This tree will not be patched up. This can happen if a SSR-ed Client Component used...
Along with that, the site felt noticeably slow, especially when navigating from the homepage into an individual component's doc page. So I started digging into what was actually going wrong, and it raised a bigger question for me:
If a component playground keeps throwing hydration mismatches, should I just switch the whole thing to client-side rendering instead of fighting SSR?
Hydration errors happen when the HTML React renders on the server doesn't match what React produces on the client during the first render. A few usual suspects:
window, document, or localStorage during render instead of inside useEffectDate.now() or Math.random(), used directly in the render outputtypeof window !== 'undefined', which by definition renders different output on each sideIn my case, some of the components in the library just weren't written with SSR in mind, so pushing them through Next.js's SSR pipeline was the root of both the console errors and the sluggish page loads.
Once I found the actual cause, I had to think through whether switching the playground pages to full client-side rendering was the right call, or if it was overkill.
Where CSR helps:
Where CSR hurts:
Instead of flipping the entire site to CSR, I only disabled SSR for the actual live preview part of each page, and kept everything else (the title, description, props table, code examples) server-rendered as usual.
In Next.js this looks like:
import dynamic from 'next/dynamic';
const LivePreview = dynamic(() => import('./LivePreview'), { ssr: false });This way the text-heavy parts of the docs stay indexable and fast to load, and the interactive preview, which is the part actually causing the mismatch, just renders client-side without any conflict.
It's the same rough pattern you'll find behind most component documentation sites out there. Feels like the right balance between SEO, load speed, and not fighting hydration errors all day.
Still early days on this project, but figured I'd write this down in case someone else runs into the same error while building something similar.