Sitemap
Ecopages can emit a sitemaps.org urlset during static export. The file lists absolute <loc> URLs for indexable pages plus any non-page URLs you add in config.
Sitemap generation is opt in and disabled by default. Enable it when you want search engines to discover your statically exported routes without maintaining sitemap.xml by hand.
Enable sitemap generation
Add setSitemap() to eco.config.ts:
import { ConfigBuilder } from '@ecopages/core/config-builder';
const config = await new ConfigBuilder()
.setRootDir(process.cwd())
.setBaseUrl(process.env.ECOPAGES_BASE_URL ?? 'https://example.com')
.setSitemap({
enabled: true,
extraUrls: ['/rss.xml'],
exclude: ['/admin/**'],
})
.build();
export default config;| Option | Default | Purpose |
|---|---|---|
enabled | false | Write a sitemap file during static export |
fileName | sitemap.xml | Output file name inside dist/ |
exclude | [] | Pathname patterns to omit after eligibility checks |
extraUrls | [] | Additional URLs to append (feeds, manifests, integration artifacts) |
Set ECOPAGES_BASE_URL (or setBaseUrl()) to your production origin before ecopages build. Every page URL in the sitemap is resolved against that base.
See Configuration and Canonical Base URL for precedence rules.
What gets included
During static export, Ecopages builds the sitemap in two passes:
- Eligibility — collect pathnames for pages that exported successfully and pass metadata robots checks.
- Assembly — apply
exclude, resolve absolute locations, appendextraUrls, dedupe.
Pipeline for each page URL:
- Static export renders the page (or reuses a cached render).
- Metadata must resolve; resolution errors omit the URL.
metadata.robots.index: falseomits the URL.- Matching
excludepatterns omit the URL. - Remaining pathnames become
<loc>entries;extraUrlsappend afterward. sitemap.xmlis written afterafterStaticExport.
Eligible pages
A pathname is eligible when all of the following are true:
- The page is part of the static export run (filesystem routes and
app.static()views with a static cache strategy). - Static HTML for that pathname was written or reused from the incremental static cache.
- Page metadata resolves during export.
metadata.robots.indexis notfalse.
Ecopages is fail-closed on metadata: if metadata resolution throws, the URL is omitted even when HTML was generated.
Page-level noindex
Use metadata.robots.index: false to keep a page out of the sitemap and emit a noindex robots meta tag:
import { eco } from '@ecopages/core';
export default eco.page({
metadata: () => ({
title: 'Draft',
description: 'Not ready for indexing',
robots: { index: false },
}),
render: () => <p>Draft content</p>,
});The same rule applies to explicit static views registered with app.static() when they expose metadata.
Bulk exclusion with exclude
After eligibility, exclude removes matching pathnames. Supported patterns:
| Pattern | Matches |
|---|---|
/admin | Exact pathname /admin |
/admin/** | /admin and every descendant (/admin/users, …) |
This is not a full glob engine. Patterns outside these forms are treated as exact pathnames.
Extra URLs with extraUrls
extraUrls append non-page URLs after page URLs. Typical uses:
- RSS or Atom feeds (
/rss.xml) - Web app manifests
- Files an integration writes in
afterStaticExport
Relative paths resolve against baseUrl. Absolute http(s) URLs pass through unchanged.
Build timing
Static export runs in this order:
beforeStaticExportrobots.txtgeneration- Static page rendering
afterStaticExport(integration hooks)- Sitemap write (when
enabled: true)
The sitemap is written after afterStaticExport so integrations can finish generating artifacts before you list them in extraUrls.
StaticExportContext.routes exposes the full static-generation route list without sitemap filtering. Integrations that emit custom files should add those URLs to extraUrls (or maintain a separate sitemap) rather than assuming every route in routes appears in sitemap.xml.
Output format
Ecopages writes a sitemap.org 0.9 urlset with one <url><loc>…</loc></url> entry per location. XML special characters in URLs are escaped.
The generator does not emit lastmod, changefreq, or priority, and does not produce sitemap index files. For large sites that need those fields, generate a custom sitemap in an integration hook or check in a static file under public/.
Verify the output
After a production build:
ECOPAGES_BASE_URL=https://example.com pnpm run build
grep -o '<loc>[^<]*</loc>' dist/sitemap.xmlConfirm production robots.txt references the sitemap if you want crawlers to discover it automatically — Ecopages does not add a Sitemap: directive for you.
Related configuration
- Configuration —
setSitemap()andsetRobotsTxt() - Pages — page metadata and cache strategies
- Deployment — set
ECOPAGES_BASE_URLbefore building for production