Indexmap

Gem Version Ruby

indexmap is a small Ruby gem for generating XML sitemap indexes and child sitemaps from explicit section definitions.

It is designed for Rails apps that want:

  • deterministic sitemap output
  • plain Ruby configuration
  • first-party rake tasks instead of a large DSL
  • easy extraction of sitemap logic into app-owned manifests

The default output mode is a sitemap index plus one or more child sitemap files. For simpler sites, indexmap also supports an explicit single-file mode that writes a single urlset directly to sitemap.xml.

Installation

Add this line to your application's Gemfile:

gem "indexmap"

And then execute:

bundle install

Or install it directly:

gem install indexmap

Ruby usage

require "indexmap"

sections = [
  Indexmap::Section.new(
    filename: "sitemap-marketing.xml",
    entries: [
      Indexmap::Entry.new(loc: "https://example.com/"),
      Indexmap::Entry.new(loc: "https://example.com/pricing", lastmod: Date.new(2026, 4, 21))
    ]
  )
]

Indexmap::Writer.new(
  sections: sections,
  public_path: Pathname("public"),
  base_url: "https://example.com"
).write

Rails configuration

In an initializer:

Indexmap.configure do |config|
  config.base_url = -> { "https://example.com" }
  config.public_path = -> { Rails.public_path }
  config.sections = -> do
    [
      Indexmap::Section.new(
        filename: "sitemap-marketing.xml",
        entries: [
          Indexmap::Entry.new(loc: "https://example.com/")
        ]
      )
    ]
  end
end

This enables:

bin/rails sitemap:create
bin/rails sitemap:format

Single-file mode

For sites that only want one public/sitemap.xml file:

Indexmap.configure do |config|
  config.base_url = -> { "https://example.com" }
  config.public_path = -> { Rails.public_path }
  config.format = :single_file
  config.entries = -> do
    [
      Indexmap::Entry.new(loc: "https://example.com/"),
      Indexmap::Entry.new(loc: "https://example.com/about", lastmod: Date.new(2026, 4, 21))
    ]
  end
end

In :single_file mode, indexmap writes a urlset directly to sitemap.xml. In the default :index mode, it writes a sitemap index plus child sitemap files from sections.

Development

Run tests:

bundle exec rake test

Run lint:

bundle exec rake standard

Run the full default task:

bundle exec rake

Note: Gemfile.lock is intentionally not tracked for this gem, following normal Ruby library conventions.

Git hooks

We use lefthook with the Ruby commitlint gem to enforce Conventional Commits on every commit. We also use Standard Ruby to keep code style consistent. CI validates commit messages, Standard Ruby, tests, and git-cliff changelog generation on pull requests and pushes to main/master.

Run the hook installer once per clone:

bundle exec lefthook install

Release

Releases are tag-driven and published by GitHub Actions to RubyGems. Local release commands never publish directly.

Install git-cliff locally before preparing a release. The release task regenerates CHANGELOG.md from Conventional Commits.

Before preparing a release, make sure you are on main or master with a clean worktree.

Then run one of:

bundle exec rake 'release:prepare[patch]'
bundle exec rake 'release:prepare[minor]'
bundle exec rake 'release:prepare[major]'
bundle exec rake 'release:prepare[0.1.0]'

The task will:

  1. Regenerate CHANGELOG.md with git-cliff.
  2. Update lib/indexmap/version.rb.
  3. Commit the release changes.
  4. Create and push the vX.Y.Z tag.

The Release workflow then runs tests, publishes the gem to RubyGems, and creates the GitHub release from the changelog entry.

License

MIT License, see LICENSE.txt

About

Made by the team at Ethos Link — practical software for growing businesses. We build tools for hospitality operators who need clear workflows, fast onboarding, and real human support.

We also build Reviato, “Capture. Interpret. Act.”. Turn guest feedback into clear next steps for your team. Collect private appraisals, spot patterns across reviews, and act before small issues turn into public ones.