CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sitemap

Sitemap-generating library and CLI tool for creating XML sitemaps that comply with the sitemaps.org protocol

Pending
Overview
Eval results
Files

simple-api.mddocs/

Simple API

High-level convenience functions for quickly generating sitemaps and indices with minimal configuration. This API provides the easiest way to create sitemaps for most common use cases.

Capabilities

simpleSitemapAndIndex

A comprehensive function that handles sitemap generation, file management, and index creation automatically.

/**
 * Creates sitemaps and sitemap index files with automatic file management
 * Handles large datasets by splitting into multiple sitemap files
 * @param options - Configuration object for sitemap generation
 * @returns Promise that resolves when all files are written
 */
function simpleSitemapAndIndex(options: {
  /** Base hostname for all URLs */
  hostname: string;
  
  /** Hostname for sitemap URLs if different from main hostname */
  sitemapHostname?: string;
  
  /** Source data: array, file path, stream, or array of URLs */
  sourceData: SitemapItemLoose[] | string | Readable | string[];
  
  /** Directory where sitemaps and index will be written */
  destinationDir: string;
  
  /** Base path for sitemap URLs relative to hostname */
  publicBasePath?: string;
  
  /** Maximum URLs per sitemap file (default: 50000) */
  limit?: number;
  
  /** Whether to gzip compress output files (default: true) */
  gzip?: boolean;
}): Promise<void>;

Usage Examples:

import { simpleSitemapAndIndex } from "sitemap";

// Basic usage with URL array
await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: [
    { url: "/", changefreq: "daily", priority: 1.0 },
    { url: "/about", changefreq: "monthly", priority: 0.7 },
    { url: "/contact", changefreq: "monthly", priority: 0.5 }
  ],
  destinationDir: "./public/sitemaps/"
});

// From file (line-separated URLs or JSON)
await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: "./urls.txt", // File path
  destinationDir: "./public/sitemaps/",
  limit: 45000,
  gzip: true
});

// From stream
import { Readable } from "stream";

const urlStream = Readable.from([
  "/page-1",
  "/page-2", 
  "/page-3"
]);

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: urlStream,
  destinationDir: "./dist/sitemaps/",
  publicBasePath: "/sitemaps/",
  sitemapHostname: "https://cdn.example.com"
});

// Large dataset with custom settings
const largeUrls = Array.from({ length: 100000 }, (_, i) => ({
  url: `/product/${i}`,
  changefreq: "weekly" as const,
  priority: 0.6,
  lastmod: new Date().toISOString()
}));

await simpleSitemapAndIndex({
  hostname: "https://shop.example.com",
  sourceData: largeUrls,
  destinationDir: "./public/sitemaps/",
  limit: 50000,
  gzip: true,
  publicBasePath: "/sitemaps/"
});

Source Data Formats

The sourceData parameter accepts multiple input formats:

Array of Sitemap Items

Direct array of sitemap item objects:

const sitemapItems: SitemapItemLoose[] = [
  {
    url: "/",
    changefreq: "daily",
    priority: 1.0,
    lastmod: "2023-01-01T00:00:00.000Z"
  },
  {
    url: "/products",
    changefreq: "weekly", 
    priority: 0.8,
    img: [
      {
        url: "https://example.com/product-image.jpg",
        caption: "Product showcase",
        title: "Featured Product"
      }
    ]
  }
];

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: sitemapItems,
  destinationDir: "./sitemaps/"
});

File Path (String)

Path to a file containing URLs or sitemap items:

// urls.txt (line-separated URLs)
/*
/
/about
/contact
/products
*/

// urls.json (JSON array)
/*
[
  {"url": "/", "priority": 1.0},
  {"url": "/about", "priority": 0.7}
]
*/

// urls.jsonl (line-separated JSON objects)
/*
{"url": "/", "changefreq": "daily", "priority": 1.0}
{"url": "/about", "changefreq": "monthly", "priority": 0.7}
*/

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: "./urls.txt", // or ./urls.json or ./urls.jsonl
  destinationDir: "./sitemaps/"
});

Stream

Any readable stream of URLs or sitemap items:

import { Readable } from "stream";
import { createReadStream } from "fs";

// From file stream
await simpleSitemapAndIndex({
  hostname: "https://example.com", 
  sourceData: createReadStream("./large-urls.txt"),
  destinationDir: "./sitemaps/"
});

// From generated stream
async function* generateUrls() {
  for (let i = 0; i < 10000; i++) {
    yield { url: `/page-${i}`, priority: 0.5 };
  }
}

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: Readable.from(generateUrls()),
  destinationDir: "./sitemaps/"
});

Array of URL Strings

Simple array of URL strings:

const urls = [
  "/",
  "/about", 
  "/contact",
  "/products",
  "/services"
];

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: urls,
  destinationDir: "./sitemaps/"
});

Advanced Configuration

Custom Public Path

Control how sitemap URLs appear in the index:

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: [...],
  destinationDir: "./public/sitemaps/",
  publicBasePath: "/static/sitemaps/", // Sitemaps accessible at /static/sitemaps/
  sitemapHostname: "https://cdn.example.com" // Different hostname for sitemaps
});

File Size Management

await simpleSitemapAndIndex({
  hostname: "https://example.com",
  sourceData: [...],
  destinationDir: "./sitemaps/",
  limit: 25000, // Smaller files for faster processing
  gzip: true    // Compress for bandwidth savings
});

Error Handling

try {
  await simpleSitemapAndIndex({
    hostname: "https://example.com",
    sourceData: "./invalid-file.txt",
    destinationDir: "./sitemaps/"
  });
} catch (error) {
  console.error("Sitemap generation failed:", error.message);
  
  if (error.code === 'ENOENT') {
    console.error("Source file not found");
  }
}

Output Files

The function creates the following files in the destination directory:

Without Gzip

  • sitemap-0.xml - First sitemap file
  • sitemap-1.xml - Second sitemap file (if needed)
  • sitemap-index.xml - Index file referencing all sitemaps

With Gzip (default)

  • sitemap-0.xml.gz - Compressed first sitemap
  • sitemap-1.xml.gz - Compressed second sitemap (if needed)
  • sitemap-index.xml.gz - Compressed index file

Integration Examples

Express.js Route

import express from "express";
import { simpleSitemapAndIndex } from "sitemap";
import { join } from "path";

const app = express();

app.get("/generate-sitemap", async (req, res) => {
  try {
    const urls = await getUrlsFromDatabase(); // Your data source
    
    await simpleSitemapAndIndex({
      hostname: "https://example.com",
      sourceData: urls,
      destinationDir: join(__dirname, "public", "sitemaps"),
      publicBasePath: "/sitemaps/"
    });
    
    res.json({ success: true, message: "Sitemap generated" });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Build Script

// scripts/generate-sitemap.ts
import { simpleSitemapAndIndex } from "sitemap";
import { resolve } from "path";

async function buildSitemap() {
  console.log("Generating sitemap...");
  
  await simpleSitemapAndIndex({
    hostname: process.env.SITE_URL || "https://example.com",
    sourceData: resolve(__dirname, "../data/urls.json"),
    destinationDir: resolve(__dirname, "../dist/sitemaps"),
    limit: 50000,
    gzip: true
  });
  
  console.log("Sitemap generation complete!");
}

buildSitemap().catch(console.error);

Install with Tessl CLI

npx tessl i tessl/npm-sitemap

docs

cli-interface.md

error-handling.md

index.md

simple-api.md

sitemap-index.md

sitemap-parsing.md

sitemap-streams.md

validation-utilities.md

xml-validation.md

tile.json