TypeScript/TSX Hydration Checker - Catches Next.js hydration errors before production
npm install hyntbash
Install as dev dependency (recommended)
npm install --save-dev hynt
Or run once with npx
npx hynt
`
Requirements: Node.js >= 16
Quick Start
`bash
Analyze your project
npx hynt
Strict mode (fail on errors)
npx hynt --strict
CI/CD mode
npx hynt --ci
Analyze specific directory
npx hynt --path ./src
`
Detection Capabilities
Hynt uses 9 specialized pattern detectors plus 3 React-specific analyzers to catch all hydration errors:
$3
1. Universal Hydration Detector - Modular pattern registry detecting:
- Non-deterministic values (Math.random, Date, crypto.randomUUID)
- Conditional expressions with browser APIs
- Logical expressions with client-only code
- Hook dependencies with non-deterministic values
- Return statements with dynamic content
- Template literals with random values
- Object/array patterns with non-deterministic properties
- Function calls to browser-only APIs
2. Non-Deterministic Value Detector - Detection for:
- Math.random() usage
- Date.now(), new Date() in render
- crypto.randomUUID(), crypto.getRandomValues()
- window.location, document properties
- localStorage, sessionStorage access
- Any value that differs between server and client
3. Text Content Mismatch Detector - Detects:
- Server/client text differences
- Dynamic text content in JSX
- Template literals with non-deterministic values
- Whitespace-only text nodes in sensitive contexts
4. Attribute Mismatch Detector - Finds:
- className/class differences
- Style attribute mismatches
- Boolean attributes (checked, disabled, selected)
- data- and aria- attribute issues
- Browser-dependent attribute values
5. Nesting Violation Detector - Identifies:
- Invalid HTML nesting (e.g., inside
)
dangerouslySetInnerHTML
- Interactive elements nested incorrectly
- Table structure violations
- List item placement issues
6. Whitespace Issue Detector - Catches:
- Inconsistent whitespace in inline elements
- Mixed whitespace types (spaces/tabs/newlines)
- Leading/trailing whitespace in blocks
- Whitespace between inline elements
7. Conditional Rendering Detector - Detects:
- Browser API-dependent conditionals
- Client-only state in rendering logic
- Inconsistent ternary/logical operators
- SSR/client conditional mismatches
8. DangerouslySetInnerHTML Detector - Flags:
- mismatches
-s, --strict
- Dynamic HTML content differences
9. Suspense Boundary Detector - Identifies:
- Suspense boundary issues
- Missing or dynamic fallback content
- Third-party component hydration problems
$3
10. Consistent UseId Analyzer - Validates:
- Proper useId() hook usage
- Static ID attributes in form elements
- Math.random() used for IDs
11. No Missing Keys Analyzer - Checks:
- Missing key props in .map() calls
- Keys in JSX elements within arrays
12. No Unsafe Hooks Analyzer - Detects:
- useLayoutEffect during SSR
- useImperativeHandle, useInsertionEffect issues
- DOM manipulation in hooks
- Conditional hook usage
CLI Options
$3
- - Exit with non-zero code on any hydration issue
-j, --json
- - Output report in JSON format
-c, --ci
- - CI/CD friendly mode (JSON output + non-zero exit on issues)
-p, --path
-
- Target directory to analyze (default: current working directory)
- -r, --runtime - Enable SSR → DOM hydration diff analysis
$3
- --parallel - Enable parallel processing (default: true)
- --no-parallel - Disable parallel processing
- --max-issues - Maximum number of issues to report (0 = unlimited, default: 0)
- --patterns-only - Use only pattern-based detection (disable React-specific analyzers)
- --legacy-only - Use only React-specific analyzers (disable pattern-based detection)
$3
- hynt setup - Generate hynt.config.ts for your project
- hynt setup --force - Overwrite existing configuration file
Configuration
Generate a configuration file:
`bash
npx hynt setup
`
$3
`typescript
import { HyntConfig } from 'hynt';
const config: HyntConfig = {
rules: {
// === Pattern-Based Detection ===
// The unified-hydration rule uses pattern detection
// to catch hydration errors automatically
'unified-hydration': 'issue',
// === React-Specific Analyzers ===
// These cover React-specific patterns not handled by pattern detection
'consistent-useId': 'issue', // Validates proper useId() usage
'no-missing-keys': 'issue', // Checks for keys in .map()
'no-unsafe-hooks': 'issue' // React hooks best practices
},
// Files and directories to exclude from analysis
exclude: [
'node_modules/**',
'.next/**',
'dist/**',
'build/**',
'coverage/**',
'out/**',
'.cache/**',
'*/.test.ts',
'*/.test.tsx',
'*/.spec.ts',
'*/.spec.tsx',
'/__tests__/',
'*/.d.ts'
],
// Enable runtime hydration analysis (SSR → DOM comparison)
runtimeChecks: false,
// Maximum number of issues to report (0 = unlimited)
maxIssues: 0,
// Enable parallel processing
parallel: true
};
export default config;
`
Rule Severity Levels:
- 'issue' - Enable the rule and report issues
- 'off' - Disable the rule
Architecture
Hynt uses a modular architecture with separation of concerns:
`
┌─────────────────────────────────────────────┐
│ CLI Interface │
│ (Commander.js + Console Reporter) │
├─────────────────────────────────────────────┤
│ Analysis Engine │
│ (Orchestrates file discovery & analysis) │
├─────────────────────────────────────────────┤
│ Unified Detection Engine │
│ ├─ Pattern Registry │
│ ├─ Unified Hydration Analyzer │
│ └─ Pattern Context & Caching │
├─────────────────────────────────────────────┤
│ Pattern Detectors (9) │
│ ├─ Universal Hydration Detector │
│ ├─ Non-Deterministic Value Detector │
│ ├─ Text Content Mismatch Detector │
│ ├─ Attribute Mismatch Detector │
│ ├─ Nesting Violation Detector │
│ ├─ Whitespace Issue Detector │
│ ├─ Conditional Rendering Detector │
│ ├─ DangerouslySetInnerHTML Detector │
│ └─ Suspense Boundary Detector │
├─────────────────────────────────────────────┤
│ React-Specific Analyzers (3) │
│ ├─ Consistent UseId Analyzer │
│ ├─ No Missing Keys Analyzer │
│ └─ No Unsafe Hooks Analyzer │
├─────────────────────────────────────────────┤
│ File Cluster Processor │
│ ├─ Adaptive Batch Sizing │
│ ├─ Resource-Aware Concurrency │
│ └─ CPU/Memory Detection │
└─────────────────────────────────────────────┘
`
Examples
$3
`bash
Analyze Next.js project
cd my-nextjs-app
npx hynt
Expected output:
Discovered 42 files to analyze
#
0 issues — 42 files analyzed
Analysis completed in 2.3s
#
Hynt - Hydration Analysis
`
When issues are found, they're displayed with file paths, line numbers, rule names, and suggestions:
`
src/pages/index.tsx
15:23 issue Non-deterministic value detected [Non-deterministic value detected]
Use a deterministic value or move to client-side only
Code: Math.random()
0 issues — 3 files analyzed
Analysis completed in 60.9ms
`
$3
`yaml
.github/workflows/check-hydration.yml
name: Hydration Check
on: [push, pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm ci
- run: npx hynt --ci
`
$3
`typescript
import { AnalysisEngine, HyntConfiguration } from 'hynt';
import { UnifiedHydrationAnalyzer } from 'hynt/domain/rules/UnifiedHydrationAnalyzer';
import { ConsistentUseIdAnalyzer } from 'hynt/domain/rules/ConsistentUseIdAnalyzer';
import { NoMissingKeysAnalyzer } from 'hynt/domain/rules/NoMissingKeysAnalyzer';
import { NoUnsafeHooksAnalyzer } from 'hynt/domain/rules/NoUnsafeHooksAnalyzer';
const config: HyntConfiguration = {
rules: {
'unified-hydration': 'issue',
'consistent-useId': 'issue',
'no-missing-keys': 'issue',
'no-unsafe-hooks': 'issue'
},
exclude: ['node_modules/**'],
include: ['/.ts', '/.tsx'],
runtimeChecks: false,
maxIssues: 0,
parallel: true
};
const engine = new AnalysisEngine([
new UnifiedHydrationAnalyzer(),
new ConsistentUseIdAnalyzer(),
new NoMissingKeysAnalyzer(),
new NoUnsafeHooksAnalyzer()
]);
const report = await engine.analyzeProject('./src', config);
console.log(Found ${report.summary.issues} issues in ${report.summary.filesAnalyzed} files);
`
Performance
Hynt is designed for speed and resource efficiency:
- Parallel Processing: Analyzes files concurrently using up to 80% of available CPU cores
- Clustering: Adaptive batch sizing (default: 15 files per batch)
- Resource-Aware: Automatically adjusts concurrency based on CPU count and available memory
- Pattern Caching: Detection results cached per file to avoid redundant analysis
- Automatic Thresholds: Clustering enabled automatically for 20+ files
Performance Characteristics:
- Uses adaptive batching to balance throughput and memory usage
- Automatically detects concurrency based on system resources
- Processes files in parallel batches
- Memory-aware to prevent system overload on large projects
Development
`bash
Clone repository
git clone https://github.com/abd-ul-ahad/hynt.git
cd hynt
Install dependencies
npm install
Build
npm run build
Run tests
npm test
Run on example project
cd examples/nextjs-app
npx hynt
`
Advanced Topics
$3
Hynt automatically sets up configuration when installed via npm. The postinstall script:
- Detects React/Next.js projects
- Creates hynt.config.ts if it doesn't exist
- Adds npm scripts to package.json (optional)
- Provides setup messages
$3
Create your own pattern detector by extending BaseHydrationPattern:
`typescript
import { BaseHydrationPattern, PatternContext, PatternCategory } from 'hynt/domain/patterns';
export class MyCustomDetector extends BaseHydrationPattern {
readonly id = 'my-custom-check';
readonly name = 'My Custom Check';
readonly description = 'Detects my specific hydration issue';
readonly category = PatternCategory.CUSTOM;
readonly enabled = true;
protected async executeDetection(context: PatternContext) {
const issues = [];
// Your detection logic here
// Access context.ast, context.sourceCode, context.filePath
// Use this.createIssue() helper to create issues
return this.createResult(issues);
}
}
`
$3
Register custom patterns with the Unified Detection Engine:
`typescript
import { PatternRegistry, UnifiedDetectionEngine } from 'hynt/domain/patterns';
const registry = new PatternRegistry();
registry.register(new MyCustomDetector());
const engine = new UnifiedDetectionEngine(registry);
``