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

@rumenx/sitemap

v1.0.2

Published

A comprehensive TypeScript package for generating XML sitemaps in Node.js applications with support for images, videos, translations, and Google News

Readme

@rumenx/sitemap

CI CodeQL Dependabot codecov npm version

A comprehensive TypeScript package for generating XML sitemaps in Node.js applications

Supporting images, videos, translations, Google News, and more with 100% type safety

✨ Features

  • 🎯 Full TypeScript Support - Complete type safety and IntelliSense
  • 🏗️ Modern Architecture - ESM/CJS dual package with tree-shaking support
  • 🌐 Comprehensive Support - Images, videos, translations, Google News, alternates
  • High Performance - Optimized for large sitemaps with streaming support
  • 🔍 Advanced Validation - Built-in URL validation and data sanitization
  • 📊 Statistics & Analytics - Detailed sitemap statistics and insights
  • 🎨 Flexible Output - XML, TXT formats with customizable styling
  • 🌍 Internationalization - Full hreflang and multilingual support
  • 📱 Modern Standards - Follows latest XML sitemap protocol specifications
  • 🧪 Battle Tested - 97%+ test coverage with 376+ test cases

💡 Inspiration

📦 Multi-Language Sitemap Family

This package is part of a comprehensive sitemap generation suite created by the same author for multiple programming languages:

All three implementations share the same core philosophy and feature set:

  • Comprehensive support - Images, videos, news, translations, and multilingual content
  • Production-ready architecture - Built for real-world applications handling large-scale sitemaps
  • Standards compliance - Full adherence to XML sitemap protocol specifications
  • Developer-friendly APIs - Intuitive, well-documented interfaces with extensive configuration options

Node.js/TypeScript enhancements:

  • Full TypeScript support with complete type safety and IntelliSense
  • ESM/CJS dual package compatibility for maximum compatibility
  • Tree-shaking support for optimal bundle sizes
  • Modern async/await patterns and Promise-based workflows
  • Enhanced validation with detailed error reporting
  • Zero runtime dependencies for minimal footprint

📦 Installation

# npm
npm install @rumenx/sitemap

# yarn
yarn add @rumenx/sitemap

# pnpm
pnpm add @rumenx/sitemap

🚀 Quick Start

import { Sitemap } from '@rumenx/sitemap';

// Create a new sitemap
const sitemap = new Sitemap();

// Add URLs
sitemap
  .add('https://example.com/')
  .add('https://example.com/about', {
    lastmod: new Date(),
    changefreq: 'monthly',
    priority: 0.8,
  })
  .add('https://example.com/products', {
    lastmod: '2023-12-01',
    changefreq: 'weekly',
    priority: 0.9,
    images: [
      {
        url: 'https://example.com/images/product.jpg',
        caption: 'Our amazing product',
      },
    ],
  });

// Generate XML
const xml = sitemap.toXML();
console.log(xml);

📚 Advanced Usage

Creating Sitemaps with Rich Media

import { Sitemap, SitemapItem } from '@rumenx/sitemap';

const sitemap = new Sitemap({
  baseUrl: 'https://example.com',
  validate: true,
  escapeContent: true,
});

// Add a page with images and videos
const richMediaItem: SitemapItem = {
  loc: '/blog/amazing-post',
  lastmod: new Date(),
  changefreq: 'monthly',
  priority: 0.7,
  images: [
    {
      url: '/images/hero.jpg',
      caption: 'Hero image for amazing post',
      title: 'Amazing Post Hero',
      license: 'https://creativecommons.org/licenses/by/4.0/',
      geoLocation: 'New York, NY',
    },
  ],
  videos: [
    {
      thumbnail_url: '/images/video-thumb.jpg',
      title: 'How to be amazing',
      description: 'A comprehensive guide to being amazing',
      content_url: '/videos/amazing.mp4',
      duration: 300,
      rating: 4.8,
      view_count: 10000,
      publication_date: '2023-12-01',
      family_friendly: true,
      tags: ['tutorial', 'amazing', 'guide'],
    },
  ],
};

sitemap.addItem(richMediaItem);

Multilingual Sitemaps with Hreflang

// Add multilingual content
sitemap.add('https://example.com/en/about', {
  translations: [
    { language: 'en', url: 'https://example.com/en/about' },
    { language: 'es', url: 'https://example.com/es/acerca-de' },
    { language: 'fr', url: 'https://example.com/fr/a-propos' },
    { language: 'de', url: 'https://example.com/de/uber-uns' },
  ],
});

Google News Sitemaps

sitemap.add('https://example.com/news/breaking-news', {
  news: {
    sitename: 'Example News',
    language: 'en',
    publication_date: new Date(),
    title: 'Breaking: Amazing Discovery Made',
    keywords: 'breaking, news, discovery, science',
  },
});

Mobile and AMP Pages

sitemap.add('https://example.com/article', {
  alternates: [
    {
      url: 'https://m.example.com/article',
      media: 'only screen and (max-width: 640px)',
    },
    {
      url: 'https://amp.example.com/article',
    },
  ],
});

🗂️ Sitemap Index Management

import { SitemapIndex } from '@rumenx/sitemap';

const sitemapIndex = new SitemapIndex({
  baseUrl: 'https://example.com',
});

// Add multiple sitemaps
sitemapIndex
  .addSitemap('https://example.com/sitemap-posts.xml', {
    lastmod: new Date(),
  })
  .addSitemap('https://example.com/sitemap-pages.xml')
  .addSitemap('https://example.com/sitemap-products.xml');

// Generate sitemap index XML
const indexXml = sitemapIndex.toXML();

🛠️ Configuration Options

Sitemap Configuration

interface SitemapConfig {
  /** Base URL for resolving relative URLs */
  baseUrl?: string;
  /** Enable validation of URLs and data */
  validate?: boolean;
  /** Enable XML content escaping */
  escapeContent?: boolean;
  /** Pretty print XML output */
  prettyPrint?: boolean;
  /** Custom XML stylesheet */
  stylesheet?: string;
  /** Maximum items per sitemap (for splitting) */
  maxItems?: number;
  /** Maximum file size in bytes */
  maxFileSize?: number;
  /** Allowed domains for URL validation */
  allowedDomains?: string[];
}

Usage with Configuration

const sitemap = new Sitemap({
  baseUrl: 'https://example.com',
  validate: true,
  escapeContent: true,
  prettyPrint: true,
  stylesheet: '/sitemap.xsl',
  maxItems: 50000,
  allowedDomains: ['example.com', 'cdn.example.com'],
});

📊 Statistics and Analysis

// Get detailed sitemap statistics
const stats = sitemap.getStats();
console.log(stats);
// Output:
// {
//   totalItems: 150,
//   totalImages: 45,
//   totalVideos: 12,
//   totalTranslations: 300,
//   totalAlternates: 75,
//   totalNews: 8,
//   averagePriority: 0.7,
//   lastModified: '2023-12-01T10:30:00.000Z',
//   sizeEstimate: 125000
// }

// Check if sitemap should be split
if (sitemap.shouldSplit()) {
  console.log('Sitemap exceeds size limits and should be split');
}

🔍 Validation and Error Handling

// Validate sitemap content
const errors = sitemap.validate();
if (errors.length > 0) {
  console.error('Sitemap validation errors:', errors);
}

// Handle validation in configuration
const sitemap = new Sitemap({
  validate: true, // Throws errors on invalid data
});

try {
  sitemap.add('invalid-url'); // Will throw validation error
} catch (error) {
  console.error('Validation error:', error.message);
}

📄 Output Formats

XML Output (Default)

const xml = sitemap.toXML({
  prettyPrint: true,
  escapeContent: true,
});

Text Output

const txt = sitemap.toTXT();
// Output:
// https://example.com/
// https://example.com/about
// https://example.com/products

Custom Rendering

const html = sitemap.render('html'); // Custom HTML format
const xml = sitemap.render('xml', { prettyPrint: false });

🎨 Advanced Features

Custom Item Processing

// Remove items based on conditions
sitemap.removeItems(item => item.priority < 0.5 || new Date(item.lastmod) < new Date('2023-01-01'));

// Get specific items
const items = sitemap.getItems();
const highPriorityItems = items.filter(item => item.priority > 0.8);

Memory Management

// Clear all items
sitemap.clear();

// Get item count without loading all items
const count = sitemap.getItemCount();

URL Resolution

const sitemap = new Sitemap({
  baseUrl: 'https://example.com',
});

// Relative URLs are automatically resolved
sitemap.add('/products'); // Becomes https://example.com/products
sitemap.add('about'); // Becomes https://example.com/about

🧪 TypeScript Support

This package is written in TypeScript and provides complete type definitions:

import {
  Sitemap,
  SitemapIndex,
  SitemapItem,
  SitemapIndexItem,
  SitemapConfig,
  SitemapStats,
  ValidationError,
} from '@rumenx/sitemap';

// Full IntelliSense support
const item: SitemapItem = {
  loc: 'https://example.com/page',
  lastmod: new Date(),
  changefreq: 'weekly', // TypeScript will suggest valid values
  priority: 0.8,
  images: [
    /* Fully typed image objects */
  ],
  videos: [
    /* Fully typed video objects */
  ],
};

📈 Performance

  • Optimized for large sitemaps - Efficiently handles 50,000+ URLs
  • Memory efficient - Stream-friendly architecture
  • Fast XML generation - Optimized string building
  • Minimal dependencies - Zero runtime dependencies
  • Tree-shakable - Import only what you need

🔧 Integration Examples

Express.js Integration

import express from 'express';
import { Sitemap } from '@rumenx/sitemap';

const app = express();

app.get('/sitemap.xml', (req, res) => {
  const sitemap = new Sitemap({ baseUrl: 'https://example.com' });

  // Add your URLs
  sitemap.add('/').add('/about').add('/contact');

  res.set('Content-Type', 'application/xml');
  res.send(sitemap.toXML());
});

Next.js Integration

// pages/api/sitemap.xml.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { Sitemap } from '@rumenx/sitemap';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  const sitemap = new Sitemap({ baseUrl: 'https://yoursite.com' });

  // Add your pages
  sitemap.add('/').add('/about').add('/blog');

  res.setHeader('Content-Type', 'application/xml');
  res.status(200).send(sitemap.toXML());
}

Database Integration

import { Sitemap } from '@rumenx/sitemap';
import { getAllPosts, getAllProducts } from './database';

async function generateSitemap() {
  const sitemap = new Sitemap({ baseUrl: 'https://example.com' });

  // Add static pages
  sitemap.add('/').add('/about').add('/contact');

  // Add dynamic content
  const posts = await getAllPosts();
  posts.forEach(post => {
    sitemap.add(`/blog/${post.slug}`, {
      lastmod: post.updatedAt,
      changefreq: 'weekly',
      priority: 0.7,
    });
  });

  const products = await getAllProducts();
  products.forEach(product => {
    sitemap.add(`/products/${product.slug}`, {
      lastmod: product.updatedAt,
      changefreq: 'monthly',
      priority: 0.8,
      images: product.images.map(img => ({
        url: img.url,
        caption: img.alt,
      })),
    });
  });

  return sitemap.toXML();
}

🛡️ Error Handling

The package provides comprehensive error handling with detailed error messages:

import { ValidationError } from '@rumenx/sitemap';

try {
  sitemap.add('invalid-url');
} catch (error) {
  if (error instanceof ValidationError) {
    console.log('Field:', error.field);
    console.log('Type:', error.type);
    console.log('Message:', error.message);
    console.log('Value:', error.value);
  }
}

🌟 Migration Guide

From other sitemap packages

// Before (other packages)
const sitemap = require('sitemap');
const urls = [{ url: '/', changefreq: 'daily', priority: 1.0 }];
const sm = sitemap.createSitemap({ urls });

// After (@rumenx/sitemap)
import { Sitemap } from '@rumenx/sitemap';
const sm = new Sitemap();
sm.add('/', { changefreq: 'daily', priority: 1.0 });

📋 Requirements

  • Node.js: >= 18.0.0
  • TypeScript: >= 4.5.0 (for TypeScript projects)

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

📄 License

This project is licensed under the MIT License - see the LICENSE.md file for details.

🔗 Links

⭐ Support

If you find this package helpful, please consider giving it a ⭐ on GitHub!