hydration-proof
v1.0.1
Published
Find, explain, reproduce and prevent React hydration mismatches before users see them. Compares real server HTML with the hydrated DOM in CI. Next.js, React 18 and 19. Adds nothing to your production bundle.
Maintainers
Readme
hydration-proof
Find React hydration problems in a real browser, before your users do.
Hydration happens when React takes over HTML rendered by your server. If the first client render differs, users can see flicker, lose state, or keep an incorrect attribute. hydration-proof shows the page, the server and client values, and a practical next step. It does not change your app or add code to its production bundle.
Get started
You need Node.js 22.18+ and an app that renders React on the server.
npm install -D hydration-proof
npx hydration-proof install
npx hydration-proof init
npx hydration-proof testinstall downloads Chromium once. init creates hydration-proof.config.ts (or .mjs in a JavaScript project) and ignores generated reports in Git. The generated config is deliberately small: the tool already knows how to build, start, and discover routes in Next.js, React Router, Remix, and Astro. For Vite SSR or a custom Node server, add your real routes to the generated file. If no framework is detected, also set server.command or pass --url.
You can use the same commands with your package manager:
| npm | pnpm | Yarn | Bun |
| --- | --- | --- | --- |
| npx hydration-proof test | pnpm exec hydration-proof test | yarn hydration-proof test | bunx hydration-proof test |
Use the corresponding command for install and init too. No browser is downloaded during package installation.
Read a result
Hydration Proof — checking 20 pages on http://localhost:3000
✖ /dashboard 1.1s 1 error
HP1001 Text differs between server and client · app/dashboard/LastLogin.tsx:14
server "5:00 AM" → client "10:00 AM"
Possible cause: Timezone difference. Fix: Use the same timeZone on the server and client.
Pages tested: 20
Passed: 19
Failed: 1
Report: .hydration-proof/report/report.html
More detail: run with --verbose or open the report.The terminal focuses on pages that need attention. --verbose shows every page and full finding details. Open .hydration-proof/report/report.html for screenshots, evidence, and all findings. The JSON report is in the same folder for automation. The command exits with code 1 when it finds errors, so it works in CI.
Add the routes your app needs
init does not invent product IDs or sample pages. If a dynamic route is not prerendered by your framework, give it a real value from your test data:
import { defineConfig } from 'hydration-proof';
export default defineConfig({
routes: {
dynamic: { '/products/[id]': ['your-stable-test-product-id'] },
},
});Replace that value with an ID that exists in your app. Use the configuration guide for signed-in pages, custom servers, and other settings. If you already run the app yourself, you can skip server setup:
npx hydration-proof test --url http://localhost:3000 --route /Use it while developing
npx hydration-proof dev # Browse with a hydration overlay
npx hydration-proof test --watch # Recheck affected routes after a changeThe tool also has a local dashboard, an ESLint plugin that catches risky render code, and CI examples. Your app is never modified.
Run it in CI
npx hydration-proof init --ci githubThis adds a GitHub Actions workflow and keeps your existing config. Review it for any app-specific build steps or test credentials. The same test command runs locally and in CI; it exits non-zero when the configured failure threshold is reached. For GitLab, use --ci gitlab. See the CI guide.
What it catches
- Text, elements, and attributes that differ between server HTML and React's first client render—even attributes React leaves wrong without a console error.
- Invalid HTML the browser repairs before React starts.
- Changes made by scripts before hydration.
- React's own hydration errors and warnings.
Some findings have no reliable source line, especially in production builds without source maps. The report then shows the element and explains what it could identify; it does not guess a file. Likely causes are suggestions, not proof, unless a probe confirms them. Run npx hydration-proof test --probe to investigate a cause with additional page loads.
More
hydration-proof works with React 18 and 19. Its only runtime dependency is playwright-core. No telemetry is shipped and nothing is uploaded by the tool. See security.
MIT © Sohail Khan
