Skip to content

React Helmet

A React adapter over @mongez/dom’s metadata module. One <Helmet> component that sets the document title (with optional app-name suffix), description, keywords, Open Graph / Twitter cards, canonical URL, and <html> attributes. Effect-only — returns null, writes directly to document.head and document.documentElement, restores prior values on unmount.

Highlighted features

One prop fans out

<Helmet title=“X” /> writes <title>, og:title, twitter:title, and itemprop=name in one go. Same for description, image, URL.

Auto-restore on unmount

Each effect snapshots the mount-time value. Unmount cleanly restores — perfect for client-side route transitions that briefly mount one Helmet and then another.

App-wide defaults

setHelmetConfigurations({ appName, titleSeparator, …, translationFunction }) — set once, every <Helmet> instance inherits. Per-call props win.

SSR-safe import

document is read lazily inside helpers, not at module top. Importing in a Node SSR context doesn’t throw — writes happen in client effects, so SSR is a clean no-op.

Install

Terminal window
npm install @mongez/react-helmet @mongez/dom

Peer deps: react >= 18, @mongez/dom >= 1.1.2.

Quick peek

import Helmet from "@mongez/react-helmet";
export default function ArticlePage({ post }) {
return (
<>
<Helmet
title={post.title}
description={post.summary}
keywords={post.tags}
image={post.coverImage}
/>
<Article post={post} />
</>
);
}

Drop <Helmet> anywhere in the tree — every prop fans out to the matching <head> tags. Unmount restores the prior values automatically.

Mental model

ConceptWhat it is
<Helmet>Side-effect renderer — returns null. Every prop maps to an effect that writes one or more <head> tags.
HelmetPropsPer-instance settings. Each maps to a known set of tags.
setHelmetConfigurationsApp-wide defaults. Per-call props win when both are provided.
translationFunctionOptional (key) => string — auto-translates the title and appName through @mongez/localization.

Lifecycle

<Helmet title=… description=… />
mount → one effect per prop → writes to document.head / documentElement
re-render with new prop → effect with that prop in deps re-runs → overwrites the tag
unmount → each effect's cleanup restores the mount-time snapshot

title, description, keywords, image, url, pageId, className, and htmlAttributes all restore reliably.

Scope boundaries

ConcernLives whereWhy
DOM-level title / meta writers@mongez/domFramework-agnostic
React component + config singletonThis packageReact-specific
Translation strings@mongez/localizationPluggable via translationFunction

SSR

document.documentElement is accessed lazily inside helper functions, not at the module top level — importing @mongez/react-helmet in a Node SSR context does not throw. All writes happen in client-side effects, so the component is a no-op during server render. For Next.js App Router, wrap in a "use client" boundary; for Pages Router / Remix, use dynamic(..., { ssr: false }).

Where to go next

  • The Helmet component — full prop list, mount/unmount semantics
  • Metadata — which tags each prop writes
  • ConfigurationsetHelmetConfigurations, app-wide defaults, translation function
  • Recipes — common patterns (article pages, dark mode, route transitions)