Sitemap-generating library and CLI tool for creating XML sitemaps that comply with the sitemaps.org protocol
—
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.
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/"
});The sourceData parameter accepts multiple input formats:
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/"
});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/"
});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/"
});Simple array of URL strings:
const urls = [
"/",
"/about",
"/contact",
"/products",
"/services"
];
await simpleSitemapAndIndex({
hostname: "https://example.com",
sourceData: urls,
destinationDir: "./sitemaps/"
});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
});await simpleSitemapAndIndex({
hostname: "https://example.com",
sourceData: [...],
destinationDir: "./sitemaps/",
limit: 25000, // Smaller files for faster processing
gzip: true // Compress for bandwidth savings
});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");
}
}The function creates the following files in the destination directory:
sitemap-0.xml - First sitemap filesitemap-1.xml - Second sitemap file (if needed)sitemap-index.xml - Index file referencing all sitemapssitemap-0.xml.gz - Compressed first sitemapsitemap-1.xml.gz - Compressed second sitemap (if needed)sitemap-index.xml.gz - Compressed index fileimport 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 });
}
});// 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