astro-sitemap
This Astro integration generates a sitemap.xml for your Astro project during build.
The sitemap.xml file provides information about structure of your website, about its content: pages, images, videos and relations between them. See Google's advice on sitemap to learn more.
Why astro-sitemap?
Some of functionality from astro-sitemap v0.2.2 became an update for the official integration @astrojs/sitemap from v0.1.2 to v0.2.0.
From now you can use the official integration in most cases.
Shared functionality with the official @astrojs/sitemap:
- Split up your large sitemap into multiple sitemaps by custom limit.
- Ability to add sitemap specific attributes such as
changefreq
, lastmod
, priority
. - Final output customization via JS function (sync or async).
- The most important: localization support. In a build time the integration analyses the pages urls for presence of locale signatures in paths to establish relations between pages.
- Reliability: all config options are validated.
astro-sitemap key extras:
- More control on sitemap output:
- manage xml namespaces;
lastmod
format option;- possibility to add a link to custom xsl.
- Automatically creates a link to sitemap in
<head>
section of generated pages. - Flexible configuration: configure the integration with external config, astro.config or combine both.
Installation
There are two ways to add astro-sitemap integration to your Astro project.
Astro CLI tool
You should run astro add
command in your project directory. This command after prompt will install required dependencies and apply changes to astro.config.*.
npx astro add astro-sitemap
yarn astro add astro-sitemap
pnpx astro add astro-sitemap
If you run into any troubles, feel free to log an issue on my GitHub.
Install dependencies manually
First, install the astro-sitemap integration like so:
npm install --save-dev astro-sitemap
yarn add -D astro-sitemap
pnpm add -D astro-sitemap
Then apply this integration to your astro.config.*. All details below in Getting started.
Getting started
The astro-sitemap
integration requires a deployment / site URL for generation. Add your site's URL under your astro.config.* using the site
property.
:exclamation: Provide the experimental
property to your astro.config.*, because only official @astrojs/* integrations are currently supported by Astro. Set the experimental.integrations
value to true
.
Then, apply this integration to your astro.config.* file using the integrations
property.
astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from 'astro-sitemap';
export default defineConfig({
site: 'https://example.com',
experimental: {
integrations: true,
},
integrations: [sitemap()],
});
Now, build your site for production via the astro build
command. You should find your sitemap under dist/sitemap-index.xml
and dist/sitemap-0.xml
!
Generated sitemap content for two pages website:
sitemap-index.xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-0.xml</loc>
</sitemap>
</sitemapindex>
sitemap-0.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>https://example.com/</loc>
</url>
<url>
<loc>https://example.com/second-page/</loc>
</url>
</urlset>
All pages generated during build will contain in <head>
section a link to sitemap:
<link rel="sitemap" type="application/xml" href="/sitemap-index.xml">
You can also check Astro Integration Documentation for more on integrations.
Configuration
Options
Name | Type | Required | Default | Description |
---|
filter | (page: String):
Boolean | No | | The same as official. Function to filter generated pages to exclude some paths from a sitemap. |
customPages | String[] | No | | The same as official. Absolute url list. It will be merged with generated pages urls. |
canonicalURL | String | No | | The same as official. Absolute url. The integration needs site from astro.config or canonicalURL . If both values are provided then only canonicalURL will be used by the integration. |
entryLimit | Number | No | 45000 | Number of entries per sitemap file, a sitemap index and multiple sitemaps are created if you have more entries. See more on [Google]((https://developers.google.com/search/docs/advanced/sitemaps/large-sitemaps/) |
xslUrl | String | No | | Absolute URL of XSL file to transform XML to other format. Ignored by search engines. |
xmlns | NSArgs | No | | Manage xml namespaces in the <urlset> |
lastmodDateOnly | Boolean | No | | If it's true the XML output will contain a date part only. |
search/docs/advanced/sitemaps/large-sitemaps) | | | | |
changefreq | ChangeFreq | No | | Sitemap specific. Ignored by Google. How frequently the page is likely to change. Available values: always |hourly |daily |weekly |monthly | yearly |never |
lastmod | Date | No | | Sitemap specific. The date of page last modification. |
priority | Number | No | | Sitemap specific. Ignored by Google. The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0 |
serialize | (item: SitemapItem):
SitemapItemLoose |undefined | Promise<SitemapItemLoose |undefined > | No | | Function to process an array of sitemap entries just before writing them to disk. Async or sync. The undefined return value excludes the passed entry from sitemap. |
createLinkInHead | Boolean | No | true | Create a link on the sitemap in <head> of generated pages. The final output reprocessing is used for this. It could impact on a build time for large sites. |
i18n | object | No | | Provide this object to start |
defaultLocale | String | Yes | | Its value has to be exists as one of locales keys. |
locales | Record<String, String> | Yes | | Key/value - pairs. The key is used to look for a locale part in a page path. The value is a language attribute, only English alphabet and hyphen allowed. See more on MDN |
:bulb: See detailed explanation of sitemap specific options on sitemap.org.
:exclamation: This integration uses 'astro:build:done' hook (official @astrojs/sitemap does the same). The hook exposes only generated page paths. So with present version of Astro the integration has no abilities to analyze a page source, frontmatter etc. The integration can add changefreq
, lastmod
and priority
attributes only in a batch or nothing.
NSArgs
Name | Type | Required | Default | Description |
---|
xhtml | Boolean | No | true | xmlns:xhtml="http://www.w3.org/1999/xhtml" |
news | Boolean | No | | xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" |
video | Boolean | No | | xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" |
image | Boolean | No | | xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" |
custom | String[] | No | | Any custom namespace. Elements of array are used as is , no validation. |
SitemapItem
Name | Type | Required | Description |
---|
url | String | Yes | Absolute url |
changefreq | ChangeFreq | No | |
lastmod | String | No | ISO formatted date |
priority | Number | No | |
links | LinkItem[] | No | for localization |
SitemapItemLoose
The SitemapItemLoose
interface is a base for the SitemapItem
.
It has properties video
, img
and many others.
More details about SitemapItemLoose
interface see in the sitemap.js repo readme and types source code.
LinkItem
Name | Type | Required | Description |
---|
url | String | Yes | Absolute url |
lang | String | Yes | hreflag, example: 'en-US' |
Sample of astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from 'astro-sitemap';
export default defineConfig({
site: 'https://your-awesome-site.com',
experimental: {
integrations: true,
},
integrations: [
sitemap({
filter: (page: string) => !/exclude-this/.test(page),
customPages: [
'https://example.com/virtual-one.html',
'https://example.com/virtual-two.html',
],
canonicalURL: 'https://example.com',
lastmodDateOnly: false,
xslUrl: 'https://example.com/style.xsl',
xmlns: {
xhtml: true,
news: true,
image: true,
video: true,
custom: [
'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"',
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
],
},
serialize(item: SitemapItem): SitemapItem {
if (/special-page/.test(item.url)) {
item.changefreq = 'daily';
item.lastmod = new Date();
item.priority = 0.9;
}
return item;
},
entryLimit: 1000,
changefreq: 'yearly',
lastmod: new Date('May 01, 2019 03:24:00'),
priority: 0.2,
createLinkInHead: true,
}),
],
});
Generated sitemap content for this configuration:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://example/style.xsl"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
<url>
<loc>https://example.com/</loc>
<lastmod>2019-05-01</lastmod>
<changefreq>yearly</changefreq>
<priority>0.2</priority>
</url>
...
<url>
<loc>https://example.com/virtual-one.html</loc>
<lastmod>2019-05-01</lastmod>
<changefreq>yearly</changefreq>
<priority>0.2</priority>
</url>
...
<url>
<loc>https://example.com/some-special-path.html</loc>
<lastmod>2022-06-07</lastmod>
<changefreq>daily</changefreq>
<priority>0.9</priority>
</url>
...
Localization
Supply the integration config with the i18n
options. The integration will check generated page paths on presence of locale keys in paths.
Read more about localization on Google in Advanced SEO.
Let's have the following integration config:
...
canonicalURL: 'https://example.com',
i18n: {
defaultLocale: 'en',
locales: {
en: 'en-US',
es: 'es-ES',
fr: 'fr-CA',
}
}
...
The sitemap content will be:
...
<url>
<loc>https://example.com/</loc>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/"/>
<xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/"/>
<xhtml:link rel="alternate" hreflang="fr-CA" href="https://example.com/fr/"/>
</url>
<url>
<loc>https://example.com/es/</loc>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/"/>
<xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/"/>
<xhtml:link rel="alternate" hreflang="fr-CA" href="https://example.com/fr/"/>
</url>
<url>
<loc>https://example.com/fr/</loc>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/"/>
<xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/"/>
<xhtml:link rel="alternate" hreflang="fr-CA" href="https://example.com/fr/"/>
</url>
<url>
<loc>https://example.com/es/second-page/</loc>
<xhtml:link rel="alternate" hreflang="es-ES" href="https://example.com/es/second-page/"/>
<xhtml:link rel="alternate" hreflang="fr-CA" href="https://example.com/fr/second-page/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/second-page/"/>
</url>
...
Using Configuration Files
You could configure the integration with external file sitemap.config.*
(js
, cjs
, mjs
). Put it to the application root
folder (see about root
in official docs).
The external config must contain a default export statement:
export default {
...
};
or
module.exports = {
...
};
:exclamation: The current version of integration doesn't support typescript configs.
How does the integration internally resolve a config?
Options parameter provided? | External config exists? | Result |
---|
No | No | Default config used |
Yes | No | Options parameter used |
No | Yes | External config used |
Yes | Yes | External config is merged with options parameter |
The external configuration usage example is in this demo repo.
:exclamation: Important Notes
Only official @astrojs/* integrations are currently supported by Astro.
There are two possibilities to make astro-sitemap integration working with current version of Astro.
Set the experimental.integrations
option to true
in your astro.config.*.
export default defineConfig({
experimental: {
integrations: true,
},
});
Or use the --experimental-integrations
flag for build command.
astro build --experimental-integrations
Inspiration
The astro-sitemap
is based on the official integration @astrojs/sitemap. Many thanks to the Astro team for their work!