How to build a sitemap xml in Node js using Express

Posted on Jun 17, 2020

featured image

A good sitemap.xml will help you a lot in terms of SEO. It’s a nice starting point if you want to index your site. It’s just a standard XML file that search engines understand.

Can be as simple as this one:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="">
You can see the complete list of tags definitions here:
Let’s code a Node.js web app using Express.js framework to expose an endpoint that prints a well-formed sitemap XML

Install Express

Install Express js globally to take advantage of Express generator
sudo npm install express -g
Run this command to generate a default Express structure
express --no-view --git node-sitemap-xml
You should see something like this. It could be different depending on your Express version.
create : node-sitemap-xml/
create : node-sitemap-xml/public/
create : node-sitemap-xml/public/javascripts/
create : node-sitemap-xml/public/images/
create : node-sitemap-xml/public/stylesheets/
create : node-sitemap-xml/public/stylesheets/style.css
create : node-sitemap-xml/routes/
create : node-sitemap-xml/routes/index.js
create : node-sitemap-xml/routes/users.js
create : node-sitemap-xml/public/index.html
create : node-sitemap-xml/.gitignore
create : node-sitemap-xml/app.js
create : node-sitemap-xml/package.json
create : node-sitemap-xml/bin/
create : node-sitemap-xml/bin/www
change directory:
cd node-sitemap-xml 

Install dependencies

npm install 

run the app

DEBUG=node-sitemap-xml:* npm start   
Enter to the created folder
cd node-sitemap-xml
Install dependencies
npm install
Let’s add a dependency to convert JavaScript objects to XML
npm install js2xmlparser --save

Add moment.js

Add Moment js as a dependency to deal with dates. Moment js it’s an awesome module to parse, format and manipulate dates. Strongly recommended
npm install moment --save
Create a new file called sitemap.js at the routes folder and paste this content.

sitemap.xml generation route

const express = require("express");
const router = express.Router();
const js2xmlparser = require("js2xmlparser");
const moment = require("moment");
 * It generates a standard sitemal.xml for SEO purposes
router.get("/", function(req, res, next) {
    try {
        //our records to index
        const records = getRecordsFromDataSource();
        const collection = [];
        let today = moment();
        today = today.format("YYYY-MM-DD");
        //add site root url
        const rootUrl = {};
        rootUrl.loc = "";
        rootUrl.lastmod = today;
        rootUrl.changefreq = "daily";
        rootUrl.priority = "1.0";
        rootUrl["image:image"] = {
            "image:loc": "s://",
                " Software development blog. Java, Node JS, Salesforce among other technologies",
        //add recipes urls
        for (let i = 0; i < records.length; i++) {
            const url = {};
            url.loc = records[i].url;
            url.lastmod = records[i].updated_at;
            url["image:image"] = {
                "image:loc": records[i].featured_image_url,
                "image:caption": records[i].description,
        const col = {
            "@": {
                xmlns: "",
                "xmlns:image": "",
            url: collection,
        const xml = js2xmlparser.parse("urlset", col);
        res.set("Content-Type", "text/xml");
    } catch (e) {
 * @return a collection to index (typically we'll get these records from our database)
function getRecordsFromDataSource() {
    //these records will have our own structure, we return as they are and later we convert them to the xml standard format
    //so let's just define two records hard-coded
    const record1 = {
        url: "",
            "Introduction A good practice in software development is to delegate as much heavy work as possible to background jobs",
        featured_image_url: "",
        updated_at: "2019-07-11",
    const record2 = {
        url: "",
        description: "A small site in Node.js using Express that will have one protected page Http auth basic prompt",
        featured_image_url: "",
        updated_at: "2019-07-11",
    return [record1, record2];
module.exports = router;

Basically, that code builds dynamically our sitemap XML.

  • First, it creates a block for the home page and then iterates on our records that can be a mix of different types of records such as recipes, news, cars, etc.
  • You will have to modify it as necessary.
  • Have in mind pagination if you have a big collection of records.

As a last step modify the file app.js to add our route:
const sitemapRouter = require("./routes/sitemap");
// (...)
app.use("/sitemap.xml", sitemapRouter);
Run locally
npm start
Open your browser at http://localhost:3000/sitemap.xml
And you will see this output:
<?xml version='1.0'?>
<urlset xmlns='' xmlns:image=''>
            <image:caption> Software development blog. Java, Node JS, Salesforce among other technologies</image:caption>
            <image:caption>Introduction A good practice in software development is to delegate as much heavy work as possible to background jobs</image:caption>
            <image:caption>A small site in Node.js using Express that will have one protected page Http auth basic prompt</image:caption>

After deploying the code in production you’ll want to give visibility to your sitemap.xml. I recommend you submit your URL to the most used (nowadays) search engine: Google.

Go to and submit your URL. Google will inspect it periodically

See the full source code here:

Photo by Annie Spratt on Unsplash
nodejs express sitemap dev
Side Widget
You can put anything you want inside of these side widgets. They are easy to use, and feature the new Bootstrap 4 card containers!