npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jsarc/meta

v0.0.1-beta.2.4

Published

META est une bibliothèque React/TypeScript/Javascript légère et performante pour la gestion dynamique des métadonnées HTML (title, description, keywords, author, etc.) dans les applications SPA. Elle permet de mettre à jour les métadonnées de la page de m

Readme

@jsarc/meta

License TypeScript React Vite

@jsarc/meta est une bibliothèque React/TypeScript/Javascript légère et performante pour la gestion dynamique des métadonnées HTML (title, description, keywords, author, etc.) dans les applications SPA. Elle permet de mettre à jour les métadonnées de la page de manière déclarative et impérative, avec un support complet de TypeScript, Javascript.

✨ Fonctionnalités Principales

📄 Gestion Complète des Métadonnées

  • Mise à jour dynamique du titre de la page (<title>)
  • Gestion des métadonnées HTML standards : description, keywords, author, etc.
  • Support des métadonnées HTTP-EQUIV (Content-Type, etc.)
  • Mise à jour en temps réel lors des changements de route ou d'état

🎯 Deux Approches d'Utilisation

  • Composant déclaratif <Metadata /> pour une utilisation simple
  • Hook impératif useMetaActions() pour un contrôle avancé
  • API flexible permettant les deux approches dans la même application

⚡ Performance Optimisée

  • Mises à jour ciblées uniquement des métadonnées modifiées
  • Aucune dépendance lourde
  • Bundle size minimal (< 3KB gzipped)
  • Zéro impact sur le rendu React

🔧 Intégration Facile

  • Installation en une commande
  • Configuration minimale requise
  • Compatibilité totale avec TypeScript
  • Intégration transparente avec Vite et React Router

📦 Installation

Via npm/yarn/pnpm

npm install @jsarc/meta
# ou
yarn add @jsarc/meta
# ou
pnpm add @jsarc/meta

Dépendances requises

  • React 19+
  • TypeScript 5.0+ (recommandé)
  • Vite (optionnel, mais recommandé)

🚀 Démarrage Rapide

Utilisation avec le composant déclaratif

// App.tsx
import React from 'react';
import Metadata from '@jsarc/meta/components';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const HomePage = () => (
  <>
    <Metadata
      title="Page d'Accueil - Mon Application"
      description="Bienvenue sur notre application révolutionnaire"
      keywords={['accueil', 'application', 'révolutionnaire']}
      author="INICODE Team"
    />
    <h1>Bienvenue !</h1>
  </>
);

const AboutPage = () => (
  <>
    <Metadata
      title="À Propos - Mon Application"
      description="Découvrez notre histoire et notre équipe"
      keywords={['à propos', 'équipe', 'histoire']}
      author="INICODE Team"
    />
    <h1>À Propos</h1>
  </>
);

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/about" element={<AboutPage />} />
      </Routes>
    </BrowserRouter>
  );
};

export default App;

Utilisation avec le hook impératif

// ProductPage.tsx
import React, { useEffect } from 'react';
import { useMetaActions } from '@jsarc/meta/hooks';

const ProductPage = ({ product }) => {
  const { setHeader } = useMetaActions();

  useEffect(() => {
    setHeader({
      title: `\${product.name} - Boutique en ligne`,
      description: product.description,
      keywords: ['produit', product.category, 'achat'],
      author: 'INICODE Shop',
    });
  }, [product]);

  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
    </div>
  );
};

export default ProductPage;

📚 Documentation API

Composant Metadata

import Metadata from '@jsarc/meta/components';

// Props disponibles
interface ParamsMetadata {
  title?: string;        // Titre de la page (<title>)
  description?: string;  // Meta description
  keywords?: string[];   // Mots-clés (seront joints par ', ')
  author?: string;       // Auteur de la page
  // ... autres métadonnées supportées
}

// Utilisation
<Metadata
  title="Mon Titre"
  description="Ma description"
  keywords={['mot1', 'mot2']}
  author="John Doe"
/>

Hook useMetaActions

import { useMetaActions } from '@jsarc/meta/hooks';

const MyComponent = () => {
  const { setHeader } = useMetaActions();
  
  // Configuration possible
  interface ConfigSetHeader {
    title?: string;
    description?: string;
    keywords?: string[];
    author?: string;
    subject?: string;
    language?: string;
    // ... toutes les métadonnées HTML standard
  }
  
  // Exemple d'utilisation
  const updateMetadata = () => {
    setHeader({
      title: 'Nouveau Titre',
      description: 'Nouvelle description',
      keywords: ['react', 'metadata'],
      author: 'INICODE',
      language: 'fr-FR'
    });
  };
  
  return (
    <button onClick={updateMetadata}>
      Mettre à jour les métadonnées
    </button>
  );
};

🔧 Utilisation Avancée

Métadonnées personnalisées

// Le système supporte de nombreuses métadonnées HTML
setHeader({
  title: 'Titre de la page',
  description: 'Description pour les moteurs de recherche',
  keywords: ['technologie', 'react', 'typescript'],
  author: 'Équipe de développement',
  subject: 'Développement Web',
  copyright: '© 2024 INICODE',
  language: 'fr-FR',
  abstract: 'Résumé de la page',
  topic: 'Programmation',
  summary: 'Sommaire du contenu',
  designer: 'Jean Dupont',
  'reply-to': '[email protected]',
  owner: 'INICODE SAS',
  url: 'https://example.com',
  'identifier-URL': 'https://example.com/page-id'
});

Intégration avec React Router

// routes/MetaRoute.tsx
import { useEffect } from 'react';
import { useMetaActions } from '@jsarc/meta/hooks';

interface MetaRouteProps {
  children: React.ReactNode;
  title?: string;
  description?: string;
  keywords?: string[];
}

const MetaRoute = ({ children, title, description, keywords }: MetaRouteProps) => {
  const { setHeader } = useMetaActions();
  
  useEffect(() => {
    if (title || description || keywords) {
      setHeader({
        title,
        description,
        keywords,
      });
    }
  }, [title, description, keywords]);
  
  return <>{children}</>;
};

// Utilisation dans votre router
<Route
  path="/products/:id"
  element={
    <MetaRoute
      title="Détails du Produit"
      description="Consultez les détails complets de notre produit"
      keywords={['produit', 'détails', 'spécifications']}
    >
      <ProductDetails />
    </MetaRoute>
  }
/>

Gestion des métadonnées HTTP-EQUIV

// Le système met automatiquement à jour certaines métadonnées HTTP-EQUIV
// Par défaut : Content-Type: text/html; charset=UTF-8
// Extension possible pour supporter d'autres en-têtes

// Exemple d'extension personnalisée
const setCustomHttpEquiv = () => {
  // Le système peut être étendu pour gérer d'autres en-têtes
  // comme refresh, content-security-policy, etc.
};

🎯 Exemples Complets

Exemple 1 : Blog avec métadonnées dynamiques

// BlogPost.tsx
import React, { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useMetaActions } from '@jsarc/meta/hooks';
import { blogPosts } from '../data/blogPosts';

const BlogPost = () => {
  const { id } = useParams();
  const { setHeader } = useMetaActions();
  const post = blogPosts.find(p => p.id === id);

  useEffect(() => {
    if (post) {
      setHeader({
        title: `\${post.title} - Mon Blog`,
        description: post.excerpt,
        keywords: [...post.tags, 'blog', 'article'],
        author: post.author,
        subject: post.category,
      });
    }
  }, [post]);

  if (!post) return <div>Article non trouvé</div>;

  return (
    <article>
      <h1>{post.title}</h1>
      <div>Par {post.author} • {post.date}</div>
      <div>{post.content}</div>
    </article>
  );
};

Exemple 2 : E-commerce avec métadonnées SEO

// CategoryPage.tsx
import React, { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useMetaActions } from '@jsarc/meta/hooks';
import ProductGrid from '../components/ProductGrid';
import { getCategoryInfo } from '../api/categories';

const CategoryPage = () => {
  const [searchParams] = useSearchParams();
  const categoryId = searchParams.get('category');
  const { setHeader } = useMetaActions();
  const [category, setCategory] = React.useState(null);

  useEffect(() => {
    const loadCategory = async () => {
      const data = await getCategoryInfo(categoryId);
      setCategory(data);
      
      // Mettre à jour les métadonnées
      setHeader({
        title: `\${data.name} - Boutique en ligne`,
        description: `Découvrez notre sélection de \${data.name.toLowerCase()}. \${data.description}`,
        keywords: [data.name, 'achat', 'boutique', ...data.keywords],
        author: 'INICODE E-commerce',
      });
    };
    
    if (categoryId) {
      loadCategory();
    }
  }, [categoryId]);

  return (
    <div>
      {category && (
        <>
          <h1>{category.name}</h1>
          <p>{category.description}</p>
          <ProductGrid categoryId={categoryId} />
        </>
      )}
    </div>
  );
};

Exemple 3 : Application multi-langues

// LocalizedPage.tsx
import React, { useEffect } from 'react';
import { useTranslation } from '@jsarc/intl'; // Intégration avec @jsarc/intl
import { useMetaActions } from '@jsarc/meta/hooks';

const LocalizedPage = () => {
  const { t, currentLocale } = useTranslation();
  const { setHeader } = useMetaActions();

  useEffect(() => {
    // Utiliser les traductions pour les métadonnées
    setHeader({
      title: t('page.title'),
      description: t('page.description'),
      keywords: t('page.keywords', { returnObjects: true }),
      author: t('common.author'),
      language: currentLocale,
    });
  }, [currentLocale, t]);

  return (
    <div>
      <h1>{t('page.title')}</h1>
      <p>{t('page.content')}</p>
    </div>
  );
};

🔧 Configuration

Variables d'environnement

# .env
VITE_APP_TITLE="Mon Application"
VITE_DEFAULT_AUTHOR="Équipe de développement"

Configuration TypeScript

{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["DOM", "DOM.Iterable", "ES2020"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "types": ["vite/client"]
  }
}

🛡️ Gestion des Erreurs

Fallback automatique

// En cas d'erreur, le système utilise des valeurs par défaut
const ErrorExample = () => {
  const { setHeader } = useMetaActions();
  
  const trySetHeader = () => {
    try {
      setHeader({
        title: undefined, // Sera ignoré
        description: 'Description valide',
      });
    } catch (error) {
      // En mode debug, les erreurs sont loggées
      if (import.meta.env.MODE === 'debug') {
        console.error('Erreur de métadonnées:', error);
      }
      
      // Fallback au titre de l'application
      setHeader({
        title: import.meta.env.VITE_APP_TITLE,
      });
    }
  };
  
  return <button onClick={trySetHeader}>Tester</button>;
};

Validation des métadonnées

// Fonction utilitaire de validation
const validateMetadata = (metadata: any) => {
  const errors: string[] = [];
  
  if (metadata.title && metadata.title.length > 60) {
    errors.push('Le titre ne doit pas dépasser 60 caractères pour le SEO');
  }
  
  if (metadata.description && metadata.description.length > 160) {
    errors.push('La description ne doit pas dépasser 160 caractères pour le SEO');
  }
  
  if (metadata.keywords && metadata.keywords.length > 10) {
    errors.push('Il est recommandé de ne pas dépasser 10 mots-clés');
  }
  
  return errors;
};

// Utilisation
const setValidatedHeader = (config: any) => {
  const errors = validateMetadata(config);
  
  if (errors.length > 0) {
    console.warn('Avertissements SEO:', errors);
  }
  
  setHeader(config);
};

📋 Table des Métadonnées Supportées

Métadonnées standard

| Nom | Description | Exemple | |-----|-------------|---------| | title | Titre de la page (balise <title>) | Page d'Accueil | | description | Description pour le SEO | Bienvenue sur notre site... | | keywords | Mots-clés pour le SEO | ['react', 'typescript', 'vite'] | | author | Auteur de la page | INICODE Team | | subject | Sujet de la page | Technologie | | language | Langue de la page | fr-FR | | copyright | Droits d'auteur | © 2024 | | abstract | Résumé | Résumé du contenu... | | topic | Thème principal | Développement Web | | summary | Sommaire | Sommaire détaillé... |

Métadonnées HTTP-EQUIV

| Nom | Description | Valeur par défaut | |-----|-------------|-------------------| | Content-Type | Type de contenu et encodage | text/html; charset=UTF-8 |

🔧 Build et Développement

Scripts recommandés

{
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "type-check": "tsc --noEmit"
  }
}

Structure de projet recommandée

src/
├── components/
│   ├── MetadataWrapper.tsx  # Wrapper personnalisé
│   └── SeoManager.tsx       # Gestionnaire SEO avancé
├── hooks/
│   └── useMetadata.ts       # Hook personnalisé étendu
├── utils/
│   └── metadata-validator.ts # Validateur de métadonnées
└── main.tsx

📄 Licence

MIT License - Voir le fichier LICENSE pour plus de détails.

🐛 Signaler un Bug

Envoyez-nous un mail à l'adresse [email protected] pour :

  • Signaler un bug
  • Proposer une amélioration
  • Poser une question sur l'utilisation
  • Demander une nouvelle fonctionnalité

@jsarc/meta - La solution simple et efficace pour gérer les métadonnées dans React.

Développé par l'équipe INICODE