react-helmet-async

Thread-safe document head management for React 16 through 19, encapsulating title, meta, and link tags per request during server rendering.

Library
npm
v3.0.0
2,298stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity4
Maintenance20
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture78
Code Quality85
Innovation72
Learning Curve40

react-helmet-async is a fork of the original React Helmet built to fix its core weakness: thread-unsafe server rendering. Where react-helmet relies on react-side-effect’s static rewind() method — which breaks under concurrent, asynchronous SSR — this package requires a HelmetProvider that encapsulates head state per request via context, so multiple simultaneous server renders never leak each other’s title, meta, or link tags.

Starting with version 3.0, the library detects the React runtime version and adapts: on React 16-18 it keeps its original client/server dispatcher that diffs and patches <head> tags manually via direct DOM manipulation or server-side string/component generation, while on React 19+ it becomes a thin passthrough that renders <title>, <meta>, <link>, <style>, and <script> as ordinary JSX and lets React’s native head-hoisting take over, stepping in manually only for htmlAttributes and bodyAttributes, which React 19 does not hoist.

What You Get

  • Declarative <Helmet> component for title, meta, link, script, style, base, and html/body attribute tags
  • <HelmetProvider> with per-request context, making server-side rendering thread-safe under concurrent requests
  • Automatic React 19 detection that swaps to native JSX head-hoisting while preserving the same public API
  • prioritizeSeoTags flag to reorder canonical links, Open Graph, and Twitter Card tags ahead of less-important tags in server output
  • HelmetData escape hatch for using <Helmet> without React context, for isolated or parallel SSR renders

Common Use Cases

  • Setting per-page <title> and meta description/Open-Graph tags in a server-rendered React app
  • Injecting canonical link tags and JSON-LD structured data for SEO
  • Managing multiple concurrent SSR requests without title/meta state leaking between them
  • Adding a class to <html> or <body> conditionally from a nested route component
  • Migrating a React 16-18 codebase forward to React 19 without rewriting head-management call sites

Under The Hood

Architecture react-helmet-async separates concerns across four layers: Helmet (src/index.tsx) is the public component that walks its React children and flattens them into a plain props object; Provider (src/Provider.tsx) supplies a HelmetData instance through context, scoping state to a single request/render tree instead of the module-level singleton react-side-effect relied on; Dispatcher (src/Dispatcher.tsx) is the reconciliation point that merges every mounted Helmet instance’s props via reducePropsToState (src/utils.ts) and hands the merged state to either client.ts (DOM diffing on the browser) or server.ts (string/React-element generation for SSR); and HelmetData (src/HelmetData.ts) owns the actual instance registry and context mutation. A parallel code path, React19Dispatcher.tsx, bypasses this whole pipeline on React 19+, rendering title/meta/link/script/style directly as JSX and relying on React’s native head-hoisting, falling back to manual DOM manipulation only for html/body attributes via a module-level react19Instances registry. The runtime switch is a single isReact19 check in both Helmet.render() and HelmetProvider, keeping the public API identical across both code paths. The main risk if either dispatcher’s merge/dedupe logic changes is silent divergence between the legacy and React-19 tag-priority behavior, since the two paths do not share reconciliation code.

Tech Stack Written in TypeScript against the react peer dependency (16.6–19.x), with react-fast-compare for shouldComponentUpdate diffing, shallowequal for dispatcher prop comparisons, and invariant for runtime prop validation. Bundled via a custom esbuild-based build.ts script producing both CJS (lib/index.js) and ESM (lib/index.esm.js) outputs plus .d.ts declarations through a separate tsc --project tsconfig.build.json pass. Tests run on Vitest with @testing-library/react and jsdom for unit/integration coverage, and Playwright for a dedicated browser-based e2e suite (e2e/) alongside a server-rendering e2e config. Linting is ESLint (Remix’s shared config) plus Prettier, wired through Husky pre-commit hooks and commitlint for conventional commits, with CI running via GitHub Actions.

Code Quality The test suite is extensive: 40 test files under __tests__/ (423 test/assertion call sites) split cleanly by concern — server/ for SSR output, react19/ for the native-JSX path, api/ for prop-level behavior, plus dedicated fragment, deferred, and misc suites. Error handling favors explicit invariant() calls that throw descriptive messages for invalid children rather than silently swallowing bad input. Naming is consistent (TAG_NAMES, ATTRIBUTE_NAMES, TAG_PROPERTIES enums centralize all magic strings in constants.ts), and the codebase is fully typed with no any-heavy interfaces beyond a few intentionally loose Props/Attributes maps needed for dynamic tag attributes. ESLint and Prettier are enforced via Husky pre-commit hooks, and CI runs the full suite on every push.

API Design The public surface is deliberately small: a single <Helmet> component and a <HelmetProvider>, with declarative children (<title>, <meta>, <link>, etc.) instead of a custom prop-based API, which keeps the learning curve low for anyone who already knows HTML. The library’s standout design decision is preserving that exact same API across a full internal rewrite for React 19 — consumers upgrading React versions get native head-hoisting for free without touching call sites, only losing access to context-based SSR state extraction and a few React 19-inapplicable flags (prioritizeSeoTags, titleTemplate behave as documented no-ops). The HelmetData escape hatch for context-free usage is a thoughtful addition for parallel/isolated SSR renders, a scenario the original react-helmet couldn’t handle at all.

Used by 14 apps in this directory

Go
60%
Apache 2.0

Apache Answer

Community

15,665

Open-source Q&A platform for communities, help centers, and knowledge bases with AI assistant and plugin extensibility

View details
83
Repo Health
78
Technical
68
Dependency
Built with
Go60%
TypeScript36%
Updated 1 weeks ago
Go
54%
Apache 2.0

Authgear

Authentication

2,028

Open-source, self-hostable authentication platform with passkeys, biometric login, SSO, MFA, and GraphQL admin API — a full Auth0/Clerk/Firebase alternative for SaaS and mobile apps.

View details
88
Repo Health
81
Technical
68
Dependency
Built with
Go54%
HTML25%
TypeScript18%
Updated 3 days ago
Java
73%
Other

ByteChef

Automation · AI Agents

1,000

Unified open-source platform for AI agent orchestration and workflow automation with 180+ connectors, MCP support, and durable execution.

View details
85
Repo Health
82
Technical
70
Dependency
Built with
Java73%
TypeScript26%
Updated yesterday
JavaScript
99%
Other

ChartBrew

Analytics · Databases

4,054

Open-source reporting platform to build live dashboards from SQL, NoSQL, APIs, and SaaS tools with an AI assistant that creates charts from natural language.

View details
90
Repo Health
83
Technical
64
Dependency
Built with
JavaScript99%
Updated 4 days ago
TypeScript
95%
AGPL 3.0

Docmost

Productivity · Note Taking · Collaboration

21,600

Self-hosted collaborative wiki and knowledge base with real-time editing, diagrams, AI assistance, and enterprise access controls — a modern alternative to Confluence and Notion.

View details
89
Repo Health
70
Technical
70
Dependency
Built with
TypeScript95%
Updated yesterday
PHP
58%
Other

Hi.Events

Ecommerce · Scheduling

4,015

Self-hosted event ticketing platform that keeps your attendee data, brand, and revenue completely under your control.

View details
89
Repo Health
84
Technical
66
Dependency
Built with
PHP58%
TypeScript36%
Updated yesterday
TypeScript
99%
MIT

GraphQL Hive

Developer Tools · Devops · Monitoring

484

Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.

View details
89
Repo Health
81
Technical
69
Dependency
Built with
TypeScript99%
Updated 2 days ago
TypeScript
100%
Apache 2.0

ILLA Builder

Developer Tools · Low Code Platforms · No Code Platforms

12,312

Open-source low-code platform for building internal tools with drag-and-drop UI, reactive data bindings, and real-time collaboration.

View details
57
Repo Health
71
Technical
63
Dependency
Built with
TypeScript100%
Updated 3 months ago
TypeScript
86%
MIT

medusa

Ecommerce

36,163

The most flexible open-source commerce platform — build B2C, B2B, and marketplace applications with modular, composable commerce primitives.

View details
93
Repo Health
87
Technical
63
Dependency
Built with
TypeScript86%
JavaScript14%
Updated 2 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search