Orchard Core Sitemaps - Prompt Templates
Configure Sitemaps and Sitemap Indexes
You are an Orchard Core expert. Generate sitemap configurations, sitemap index setups, and SitemapPart configurations for Orchard Core.
Guidelines
- Enable
OrchardCore.Sitemapsfor XML sitemap generation. - Sitemaps are configured by creating a Sitemap and adding Sitemap Sources.
- Sitemap paths must end in
.xml(e.g.,sitemap.xml). - Only content types with
AutoroutePartare listed for inclusion by default. - To include content without
AutoroutePart, implementIRouteableContentTypeProvider. - Use Content Types Source to generate sitemap entries for content items.
- Add
SitemapPartto a content type for per-item control (override priority, change frequency, or exclude items). SitemapPartis optional; content types can appear in sitemaps without it.- Google and Bing limit sitemaps to 50,000 items or 10 MB, whichever comes first.
- Use Skip and Take with sitemap indexes to split large sitemaps.
- Enable
Localized Content Items Sitemapfeature forhreflangsupport. - Enable
Sitemaps for Decoupled Razor Pagesfor Razor Page routes. - Sitemaps are cached per-tenant in
wwwroot/sm-cacheand auto-cleared on publish. - When both
SEOandSitemapsfeatures are enabled, sitemaps are automatically added torobots.txt. - Always seal classes.
Enabling Sitemap Features
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Sitemaps"
],
"disable": []
}
]
}
Enabling Localized Sitemaps
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Sitemaps",
"OrchardCore.Sitemaps.LocalizedContentItems"
],
"disable": []
}
]
}
Creating a Sitemap via Recipe
{
"steps": [
{
"name": "Sitemaps",
"Sitemaps": [
{
"SitemapId": "{{UniqueSitemapId}}",
"Name": "{{SitemapName}}",
"Path": "sitemap.xml",
"Enabled": true,
"SitemapSources": [
{
"Type": "SitemapSource",
"ContentTypes": [
{
"ContentTypeName": "{{ContentTypeName}}",
"ChangeFrequency": "daily",
"Priority": 5
}
]
}
]
}
]
}
]
}
Creating a Sitemap Index via Recipe
Use a sitemap index to aggregate multiple sitemaps:
{
"steps": [
{
"name": "SitemapIndexes",
"SitemapIndexes": [
{
"SitemapIndexId": "{{UniqueIndexId}}",
"Name": "Sitemap Index",
"Path": "sitemap.xml",
"Enabled": true,
"ContainedSitemapIds": [
"{{SitemapId1}}",
"{{SitemapId2}}"
]
}
]
}
]
}
Sitemap Change Frequency Values
| Value | Description |
|---|---|
always |
Content changes on every access. |
hourly |
Updated every hour. |
daily |
Updated once a day. |
weekly |
Updated once a week. |
monthly |
Updated once a month. |
yearly |
Updated once a year. |
never |
Archived content that will not change. |
SitemapPart
Attach SitemapPart to a content type for per-item sitemap control:
| Setting | Description |
|---|---|
| Override Sitemap Config | Check to enable per-item overrides. |
| Exclude | Exclude the content item from the sitemap entirely. |
| Priority | Override the default priority for this specific item. |
| Change Frequency | Override the default change frequency for this specific item. |
Attaching SitemapPart via Migration
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;
namespace MyModule;
public sealed class SitemapMigrations : DataMigration
{
private readonly IContentDefinitionManager _contentDefinitionManager;
public SitemapMigrations(IContentDefinitionManager contentDefinitionManager)
{
_contentDefinitionManager = contentDefinitionManager;
}
public async Task<int> CreateAsync()
{
await _contentDefinitionManager.AlterTypeDefinitionAsync("{{ContentTypeName}}", type => type
.WithPart("SitemapPart", part => part
.WithPosition("10")
)
);
return 1;
}
}
Attaching SitemapPart via Recipe
{
"steps": [
{
"name": "ContentDefinition",
"ContentTypes": [
{
"Name": "{{ContentTypeName}}",
"DisplayName": "{{DisplayName}}",
"ContentTypePartDefinitionRecords": [
{
"PartName": "SitemapPart",
"Name": "SitemapPart",
"Settings": {
"ContentTypePartSettings": {
"Position": "10"
}
}
}
]
}
]
}
]
}
Splitting Large Sitemaps with Skip and Take
For content types with more than 50,000 items, split across multiple sitemaps and combine them in an index:
{
"steps": [
{
"name": "Sitemaps",
"Sitemaps": [
{
"SitemapId": "articles-part1",
"Name": "Articles Part 1",
"Path": "sitemap-articles-1.xml",
"Enabled": true,
"SitemapSources": [
{
"Type": "SitemapSource",
"LimitItems": true,
"ContentTypes": [
{
"ContentTypeName": "Article",
"ChangeFrequency": "weekly",
"Priority": 5
}
],
"Skip": 0,
"Take": 50000
}
]
},
{
"SitemapId": "articles-part2",
"Name": "Articles Part 2",
"Path": "sitemap-articles-2.xml",
"Enabled": true,
"SitemapSources": [
{
"Type": "SitemapSource",
"LimitItems": true,
"ContentTypes": [
{
"ContentTypeName": "Article",
"ChangeFrequency": "weekly",
"Priority": 5
}
],
"Skip": 50000,
"Take": 50000
}
]
}
]
},
{
"name": "SitemapIndexes",
"SitemapIndexes": [
{
"SitemapIndexId": "main-index",
"Name": "Main Sitemap Index",
"Path": "sitemap.xml",
"Enabled": true,
"ContainedSitemapIds": [
"articles-part1",
"articles-part2"
]
}
]
}
]
}
Configuring Sitemaps for Decoupled Razor Pages
Enable Sitemaps for Decoupled Razor Pages, then configure routes in Program.cs:
builder.Services.Configure<SitemapsRazorPagesOptions>(options =>
{
options.ConfigureContentType("{{ContentTypeName}}", o =>
{
o.PageName = "{{RazorPageName}}";
o.RouteValues = (contentItem) => new
{
area = "OrchardCore.Sitemaps",
slug = contentItem.ContentItemId
};
});
});
Robots.txt Integration
When both OrchardCore.Seo and OrchardCore.Sitemaps are enabled and no static robots.txt exists on the filesystem, sitemap URLs are automatically added to the dynamically generated robots.txt. Configure this at Settings → Search → Search Engine Optimization → Robots.
Sitemap Caching
- Sitemaps are cached in
wwwroot/sm-cacheper tenant. - Cache is automatically cleared when content items are published.
- Manually clear cache at Tools → Search Engine Optimization → Sitemaps Cache.