hydration-proof finds React hydration errors by loading every route of your
server-rendered app in a real browser and comparing the server HTML with what
React renders on the client. Install it, run npx hydration-proof test, and it
tells you which element differs, both values, the likely cause and the fix.
Install hydration-proof
Add it as a dev dependency, then download the browser once:
npm install -D hydration-proof
npx hydration-proof install # downloads ChromiumIt needs Node.js 22.18 or newer, and works with npm, pnpm, Yarn (including
Plug'n'Play) and Bun. There are no install scripts: browsers are only
downloaded by the install command, into Playwright's shared cache, so a
project that already uses the same Playwright version does not download them
again.
To catch the same mistakes in your editor, add the ESLint plugin as well:
npm install -D eslint-plugin-hydration-proofRun your first test
npx hydration-proof init # creates hydration-proof.config.ts
npx hydration-proof testFor Next.js, React Router, Remix and Astro apps that is all. hydration-proof:
- discovers your routes from
app/,pages/and the build output, - builds the app if there is no build yet, and starts it on a free port,
- loads every route and compares the server HTML with the hydrated DOM,
- exits with code
1if it found a problem.
Vite SSR and custom Node servers are detected too. Any other setup works with
--url (see adapters).
Read the report
Each finding in the terminal shows the issue code, the element, the value on each side, the source line and a fix:
Hydration Proof — 20 pages on http://localhost:3000
✓ /pricing 684ms
✖ /dashboard 1.1s 1 error
HP1001 Text differs between server and client (timezone difference, 95%)
#last-login in LastLogin
server: "Signed in at 5:00 AM"
client: "Signed in at 10:00 AM"
app/dashboard/LastLogin.tsx:14:10
→ Pass an explicit timeZone to the formatter (the same on both sides), or format the date after mount.
Report: .hydration-proof/report/report.htmlHP1001is a stable issue code with its own page.timezone difference, 95%is the likely cause and how sure hydration-proof is.
Open .hydration-proof/report/report.html for everything at once: filters,
the server and client values side by side, the code, screenshots with the
element outlined, and a timeline of the page. Reports covers
every output format.
Test an app that is already running
npx hydration-proof test --url http://localhost:3000 --route / --route /pricingWith --url, nothing is built or started, and only the routes you name are
tested. Add --sitemap to test the pages in your sitemap, or --crawl to
follow links from the tested pages.
Test development and production builds
Development builds give exact source lines. Production builds show what your users get, including attribute mismatches React 19 never reports in production. Test both in one run:
npx hydration-proof test --mode bothAdd it to CI
- run: npm ci
- run: npx hydration-proof install --with-deps
- run: npx hydration-proof testOr let npx hydration-proof init --ci github write the workflow for you.
Detect hydration errors in CI covers GitHub Actions, GitLab and
CircleCI, sharding, baselines and budgets.
Configure it
The config file is optional for most apps. When you need it, it is TypeScript with completion:
import { defineConfig } from "hydration-proof";
export default defineConfig({
routes: {
// Example values for dynamic routes
dynamic: { "/products/[id]": ["1", "42"] },
exclude: ["/api/**"],
},
// The environments your users have
scenarios: [
{ name: "default" },
{ name: "dark-mobile", colorScheme: "dark", viewport: "mobile" },
{ name: "karachi", locale: "ur-PK", timezoneId: "Asia/Karachi" },
],
});See configuration for every option, and scenarios for signed-in pages.
Related
- How hydration-proof works: the six snapshots it compares
- What is hydration in React?
- All React hydration error messages, decoded
- Common causes of hydration errors and their fixes
- The CLI: every command and flag