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

smart-seo-kit

v1.0.0

Published

Production-ready, config-driven technical SEO automation for React and Next.js. Deterministic metadata, JSON-LD schemas, sitemap/robots generators, and SEO audit tools.

Readme

smart-seo-kit

Production-ready, config-driven technical SEO automation for React and Next.js.
Deterministic metadata, JSON-LD schemas, sitemap/robots generators, and SEO audit tools.
No AI. No LLMs. Pure config-driven logic.

npm version TypeScript License: MIT


Features

  • 🧩 React Component — Drop-in <SEO /> component for any React app
  • Next.js MetadatabuildMetadata() for App Router generateMetadata
  • 📊 JSON-LD Schemas — 10+ schema builders (Organization, Article, Product, FAQ, etc.)
  • 🗺️ Sitemap Generator — XML sitemap with hreflang support
  • 🤖 robots.txt Generator — Config-driven robots.txt generation
  • SEO Audit — Automated scoring, grading, and recommendations
  • 🌍 Multilingual — hreflang, alternates, locale support
  • 🔧 Config-Driven — One config, all pages. Overridable per page.
  • 📦 Tree-Shakable — Three entry points: core, React, Next.js
  • 🛡️ TypeScript First — Full type safety with .d.ts exports
  • 🟢 Zero Runtime Deps — No external dependencies

Installation

npm install smart-seo-kit
yarn add smart-seo-kit
pnpm add smart-seo-kit

Quick Start

1. Create SEO Config

import { createSEOConfig } from 'smart-seo-kit';

const seoConfig = createSEOConfig({
  siteName: 'My Site',
  siteUrl: 'https://example.com',
  defaultTitle: 'My Site',
  titleTemplate: '%s | My Site',
  defaultDescription: 'Default site description',
  defaultImage: '/og-default.png',
  locale: 'en',
  locales: ['en', 'ar'],
  twitterHandle: '@mysite',
  companyName: 'My Company',
  defaultRobots: { index: true, follow: true },
});

2. Use in React

import { SEO, createSEOConfig } from 'smart-seo-kit/react';

function AboutPage() {
  return (
    <>
      <SEO
        config={seoConfig}
        title="About Us"
        description="Learn more about our company"
        path="/about"
        type="webpage"
      />
      <main>
        <h1>About Us</h1>
      </main>
    </>
  );
}

3. Use in Next.js

// app/about/page.tsx
import { buildMetadata } from 'smart-seo-kit/next';

export const metadata = buildMetadata(seoConfig, {
  title: 'About Us',
  description: 'Learn more about our company',
  path: '/about',
  type: 'webpage',
});

export default function AboutPage() {
  return <main><h1>About Us</h1></main>;
}

Entry Points

| Import Path | Description | React Required | |---|---|---| | smart-seo-kit | Core utilities, schemas, generators, audit | ❌ | | smart-seo-kit/react | React <SEO /> component and hooks | ✅ | | smart-seo-kit/next | Next.js metadata builders | ✅ |


Config API

const config = createSEOConfig({
  // Required
  siteName: 'My Site',
  siteUrl: 'https://example.com',
  defaultTitle: 'My Site',

  // Optional
  titleTemplate: '%s | My Site',       // %s = page title
  defaultDescription: 'Site desc',
  defaultImage: '/og.png',
  defaultImageAlt: 'Site preview',
  locale: 'en',                        // Primary locale
  locales: ['en', 'ar', 'fr'],         // All supported locales
  twitterHandle: '@handle',
  twitterCardType: 'summary_large_image',
  companyName: 'Company Inc.',
  defaultAuthor: 'Author Name',
  includeWebSiteSchema: true,          // Auto-include WebSite schema

  defaultRobots: {
    index: true,
    follow: true,
    maxSnippet: -1,
    maxImagePreview: 'large',
  },

  urlNormalization: {
    trailingSlash: false,
    forceLowercase: true,
  },

  organization: {
    name: 'Company Inc.',
    url: 'https://example.com',
    logo: 'https://example.com/logo.png',
    sameAs: ['https://twitter.com/company'],
  },

  verification: {
    google: 'google-verification-code',
    bing: 'bing-verification-code',
  },
});

Page-Level SEO Props

All page-level properties can be passed to <SEO />, buildMetadata(), or resolveSEO():

{
  title: 'Page Title',
  description: 'Page description',
  path: '/page-path',
  canonical: 'https://example.com/page',  // Override canonical
  image: '/page-og.png',
  imageAlt: 'Page image description',
  imageWidth: 1200,
  imageHeight: 630,
  keywords: ['keyword1', 'keyword2'],
  author: 'Author Name',
  type: 'article',                         // webpage | article | product | service | faq | project | ...
  locale: 'en',
  noindex: false,
  nofollow: false,
  publishedTime: '2026-01-01T00:00:00Z',
  modifiedTime: '2026-04-01T00:00:00Z',
  skipTitleTemplate: false,
  ogType: 'article',
  alternates: [
    { hreflang: 'ar', href: 'https://example.com/ar/page' },
  ],
  breadcrumbs: [
    { name: 'Home', url: 'https://example.com' },
    { name: 'Page', url: 'https://example.com/page' },
  ],
  faq: [
    { question: 'What?', answer: 'Something.' },
  ],
  product: { name: 'Widget', price: 29.99, ... },
  service: { name: 'Dev', serviceType: 'Web', ... },
  article: { section: 'Tech', tags: ['react'] },
  organization: { name: 'Org', ... },
  localBusiness: { name: 'Shop', ... },
  creativeWork: { name: 'Project', ... },
  pagination: { prev: '/page?p=1', next: '/page?p=3' },
  customSchemas: [{ '@type': 'Event', name: '...' }],
}

React Usage

<SEO /> Component

import { SEO, createSEOConfig } from 'smart-seo-kit/react';

<SEO
  config={seoConfig}
  title="Page Title"
  description="Page description"
  path="/page"
  type="webpage"
/>

useSEO Hook

import { useSEO, createSEOConfig } from 'smart-seo-kit/react';

function MyPage() {
  const seo = useSEO(seoConfig, {
    title: 'My Page',
    path: '/my-page',
  });

  // Access resolved data: seo.title, seo.metaTags, seo.linkTags, seo.schemas
  return <h1>{seo.title}</h1>;
}

<JsonLd /> Component

import { JsonLd } from 'smart-seo-kit/react';
import { buildOrganizationSchema } from 'smart-seo-kit';

<JsonLd schema={buildOrganizationSchema({ name: 'My Org', url: '...' })} />

Next.js Usage

Static Metadata

// app/about/page.tsx
import { buildMetadata } from 'smart-seo-kit/next';

export const metadata = buildMetadata(seoConfig, {
  title: 'About',
  description: 'About page',
  path: '/about',
});

Dynamic Metadata

// app/blog/[slug]/page.tsx
import { buildMetadata } from 'smart-seo-kit/next';

export async function generateMetadata({ params }) {
  const post = await getPost(params.slug);
  return buildMetadata(seoConfig, {
    title: post.title,
    description: post.excerpt,
    path: `/blog/${post.slug}`,
    type: 'article',
    publishedTime: post.publishedAt,
  });
}

Viewport

import { buildViewport } from 'smart-seo-kit/next';

export const viewport = buildViewport({
  themeColor: '#ffffff',
  colorScheme: 'light dark',
});

JSON-LD (Server Component)

import { SeoJsonLd, buildSchemaGraph, buildWebSiteSchema } from 'smart-seo-kit/next';

export default function Layout({ children }) {
  const schema = buildSchemaGraph([buildWebSiteSchema(seoConfig)]);
  return (
    <html>
      <body>
        <SeoJsonLd schema={schema} />
        {children}
      </body>
    </html>
  );
}

Sitemap Generation

import { generateSitemap } from 'smart-seo-kit';

const xml = generateSitemap({
  siteUrl: 'https://example.com',
  routes: [
    { path: '/', lastModified: '2026-04-14', changeFrequency: 'weekly', priority: 1.0 },
    { path: '/about', lastModified: '2026-04-10', changeFrequency: 'monthly', priority: 0.8 },
    {
      path: '/blog',
      alternates: [
        { hreflang: 'en', href: 'https://example.com/blog' },
        { hreflang: 'ar', href: 'https://example.com/ar/blog' },
      ],
    },
  ],
  defaultChangeFrequency: 'monthly',
  defaultPriority: 0.5,
});

// In Next.js: app/sitemap.xml/route.ts
export function GET() {
  return new Response(xml, { headers: { 'Content-Type': 'application/xml' } });
}

Sitemap Index (for large sites)

import { generateSitemapIndex } from 'smart-seo-kit';

const index = generateSitemapIndex('https://example.com', [
  '/sitemap-pages.xml',
  '/sitemap-blog.xml',
  '/sitemap-products.xml',
]);

robots.txt Generation

import { generateRobotsTxt } from 'smart-seo-kit';

const robotsTxt = generateRobotsTxt({
  siteUrl: 'https://example.com',
  rules: [
    {
      userAgent: '*',
      allow: ['/'],
      disallow: ['/admin', '/api', '/private'],
    },
    {
      userAgent: 'Googlebot',
      allow: ['/'],
      crawlDelay: 2,
    },
  ],
  sitemaps: ['/sitemap.xml'],
  host: 'example.com',
});

// In Next.js: app/robots.txt/route.ts
export function GET() {
  return new Response(robotsTxt, { headers: { 'Content-Type': 'text/plain' } });
}

SEO Audit

import { reportSEO, formatReport } from 'smart-seo-kit';

const report = reportSEO({
  url: 'https://example.com/about',
  title: 'About Us | My Site',
  description: 'Learn more about our company and what we do.',
  canonical: 'https://example.com/about',
  image: 'https://example.com/og-about.png',
  hasStructuredData: true,
  hasH1: true,
  ogTitle: 'About Us | My Site',
  ogDescription: 'Learn more about our company.',
  locales: ['en', 'ar'],
  alternates: [
    { hreflang: 'en', href: 'https://example.com/about' },
    { hreflang: 'ar', href: 'https://example.com/ar/about' },
  ],
  breadcrumbs: [
    { name: 'Home', url: 'https://example.com' },
    { name: 'About', url: 'https://example.com/about' },
  ],
  hasBreadcrumbSchema: true,
});

console.log(report.score);    // 95
console.log(report.grade);    // "A"
console.log(report.errors);   // []
console.log(report.warnings); // [...]
console.log(report.passed);   // [...]
console.log(report.recommendations); // [...]

// Pretty print
console.log(formatReport(report));

Audit Checks

| Check | Severity | Description | |---|---|---| | title-missing | Error | Page has no title | | title-too-short | Warning | Title < 30 characters | | title-too-long | Warning | Title > 60 characters | | description-missing | Error | No meta description | | description-too-short | Warning | Description < 50 chars | | description-too-long | Warning | Description > 160 chars | | canonical-missing | Error | No canonical URL | | og-image-missing | Warning | No OG image | | structured-data-missing | Warning | No JSON-LD | | h1-missing | Warning | No H1 heading | | alternates-missing | Warning | Missing hreflang links | | breadcrumb-schema-missing | Warning | Breadcrumbs without schema | | og-title-missing | Warning | Missing og:title | | og-description-missing | Warning | Missing og:description | | duplicate-url | Warning | Duplicate URL in route map | | noindex-detected | Info | Page set to noindex |


Supported Schemas

import {
  buildOrganizationSchema,
  buildWebSiteSchema,
  buildWebPageSchema,
  buildArticleSchema,
  buildProductSchema,
  buildServiceSchema,
  buildFAQSchema,
  buildBreadcrumbSchema,
  buildLocalBusinessSchema,
  buildCreativeWorkSchema,
  buildSchemaGraph,
} from 'smart-seo-kit';

| Schema | Builder | Auto-Included | |---|---|---| | Organization | buildOrganizationSchema() | When org data exists | | WebSite | buildWebSiteSchema() | Always (configurable) | | WebPage | buildWebPageSchema() | Always | | Article | buildArticleSchema() | When type: 'article' | | Product | buildProductSchema() | When type: 'product' | | Service | buildServiceSchema() | When type: 'service' | | FAQPage | buildFAQSchema() | When type: 'faq' or FAQ data | | BreadcrumbList | buildBreadcrumbSchema() | When breadcrumbs data | | LocalBusiness | buildLocalBusinessSchema() | When type: 'local-business' | | CreativeWork | buildCreativeWorkSchema() | When type: 'project' |

Schema Graph

Combine multiple schemas into a single @graph:

const graph = buildSchemaGraph([
  buildOrganizationSchema({ name: 'My Org', url: '...' }),
  buildWebSiteSchema(config),
  buildBreadcrumbSchema([
    { name: 'Home', url: '/' },
    { name: 'About', url: '/about' },
  ]),
]);
// Output: { "@context": "https://schema.org", "@graph": [...] }

Supported Page Types

| Type | OG Type | Auto Schemas | |---|---|---| | website | website | WebSite, WebPage | | webpage | website | WebPage | | article | article | WebPage, Article | | blog | article | WebPage, Article | | service | website | WebPage, Service | | product | product | WebPage, Product | | project | website | WebPage, CreativeWork | | faq | website | WebPage, FAQPage | | profile | profile | WebPage | | organization | website | WebPage, Organization | | local-business | business | WebPage, LocalBusiness |


Extending

Custom Schema

<SEO
  config={seoConfig}
  title="Event Page"
  path="/events/conference-2026"
  customSchemas={[
    {
      '@context': 'https://schema.org',
      '@type': 'Event',
      name: 'Tech Conference 2026',
      startDate: '2026-09-15',
      location: { '@type': 'Place', name: 'Convention Center' },
    },
  ]}
/>

Direct Schema Usage

import { buildOrganizationSchema, serializeSchema } from 'smart-seo-kit';

const schema = buildOrganizationSchema({
  name: 'Company',
  url: 'https://example.com',
  logo: 'https://example.com/logo.png',
  sameAs: ['https://twitter.com/company'],
  address: {
    streetAddress: '123 Main St',
    addressLocality: 'Springfield',
    addressCountry: 'US',
  },
});

// Serialize for manual injection
const json = serializeSchema(schema);

URL Utilities

import { normalizeUrl, joinUrl, resolveCanonical, createAlternateLinks } from 'smart-seo-kit';

normalizeUrl('https://example.com/About/', { trailingSlash: false, forceLowercase: true });
// → 'https://example.com/about'

joinUrl('https://example.com', '/about');
// → 'https://example.com/about'

createAlternateLinks('https://example.com', { en: '/about', ar: '/ar/about' });
// → [{ hreflang: 'en', href: '...' }, { hreflang: 'ar', href: '...' }]

TypeScript Support

Full type definitions are included and exports are strongly typed:

import type {
  SEOConfig,
  SEOPageInput,
  ResolvedSEO,
  MetaTag,
  LinkTag,
  PageType,
  AuditReport,
  SitemapConfig,
  RobotsTxtConfig,
  OrganizationData,
  ProductData,
  ArticleData,
  // ... and more
} from 'smart-seo-kit';

JavaScript Support

Works identically for JavaScript consumers:

const { createSEOConfig, generateSitemap, reportSEO } = require('smart-seo-kit');

const config = createSEOConfig({
  siteName: 'My Site',
  siteUrl: 'https://example.com',
  defaultTitle: 'My Site',
});

API Reference

Core

| Function | Description | |---|---| | createSEOConfig(input) | Create a validated, frozen SEO config | | resolveSEO(config, input) | Resolve all SEO data (title, meta, links, schemas) | | validateSEO(config, input) | Validate SEO input and return issues | | isValidSEO(config, input) | Returns true if no critical errors |

Builders

| Function | Description | |---|---| | buildTitle(config, input) | Resolve page title with template | | buildCanonical(config, input) | Resolve canonical URL | | buildMetaTags(config, input) | Build core meta tags | | buildOpenGraphTags(config, input) | Build OG meta tags | | buildTwitterTags(config, input) | Build Twitter Card tags | | buildRobotsTags(config, input) | Build robots meta tags | | buildAlternateTags(config, input) | Build hreflang link tags | | createAlternateLinks(siteUrl, map) | Helper for locale-path maps |

Schemas

| Function | Description | |---|---| | buildSchemasForPage(config, input) | Auto-build all relevant schemas | | buildSchemaGraph(schemas) | Combine schemas into @graph | | buildOrganizationSchema(data) | Organization JSON-LD | | buildWebSiteSchema(config) | WebSite JSON-LD | | buildWebPageSchema(config, input) | WebPage JSON-LD | | buildArticleSchema(config, input) | Article JSON-LD | | buildProductSchema(data) | Product JSON-LD | | buildServiceSchema(data) | Service JSON-LD | | buildFAQSchema(items) | FAQPage JSON-LD | | buildBreadcrumbSchema(items) | BreadcrumbList JSON-LD | | buildLocalBusinessSchema(data) | LocalBusiness JSON-LD | | buildCreativeWorkSchema(data) | CreativeWork JSON-LD |

Generators

| Function | Description | |---|---| | generateSitemap(config) | Generate XML sitemap string | | generateSitemapIndex(siteUrl, paths) | Generate sitemap index XML | | generateRobotsTxt(config) | Generate robots.txt string |

Audit

| Function | Description | |---|---| | auditSEO(input) | Run audit, return findings | | scoreSEO(findings) | Calculate score (0-100) | | scoreToGrade(score) | Convert score to letter grade | | reportSEO(input) | Full audit report with score | | formatReport(report) | Format report for display |

React

| Export | Description | |---|---| | <SEO /> | All-in-one SEO component | | <JsonLd /> | JSON-LD script injector | | useSEO(config, input) | Hook for resolved SEO data |

Next.js

| Export | Description | |---|---| | buildMetadata(config, input) | Build Next.js Metadata object | | buildViewport(options) | Build Next.js Viewport object | | buildAlternates(config, input) | Build alternates for metadata | | <SeoJsonLd /> | Server Component JSON-LD |


License

MIT © abanobwagih