Skip to content

Static prerendering: Duplicate crawled/sitemap entries for nested index pages #6978

@dotnize

Description

@dotnize

Which project does this relate to?

Start

Describe the bug

Example route structure:

├── blog
│   ├── $slug.tsx
│   └── index.tsx
├── contact
│   └── index.tsx
├── index.tsx
└── __root.tsx

For /blog/index.tsx and /contact/index.tsx page routes, when building with static prerendering and sitemaps enabled, they are crawled twice and result in duplicate sitemap entries.

[prerender] Prerendering pages...
[prerender] Concurrency: 12
...
[prerender] Crawling: /blog/
[prerender] Crawling: /contact/
[prerender] Crawling: /blog
[prerender] Crawling: /contact
...
[prerender] Prerendered 8 pages:
...
[prerender] - /blog/
[prerender] - /contact/
[prerender] - /blog
[prerender] - /contact
...
[sitemap] Building Sitemap...

These routes do not have any layout routes, so only the page routes with no trailing slashes must be crawled and added to the sitemap. This trailing-slash consistency is important for SEO.

Router is configured for no trailing slashes (which is also the default afaik) so this should be followed for the output:
https://github.com/dotnize/start-static-test/blob/main/src/router.tsx#L19

Same behavior with

blog.index.tsx
contact.index.tsx

but this route structure works fine. These will only be crawled once, but only works well for routes that don't have child routes:

blog.tsx // breaks /blog/$slug
contact.tsx // OK for /contact, since this has no child routes

With that structure, I assume blog.tsx is treated as a layout route, so blog/$slug.tsx contents are never rendered since blog.tsx doesn't have an Outlet.

Your Example Website or App

https://github.com/dotnize/start-static-test

Steps to Reproduce the Bug or Issue

  1. pnpm install
  2. pnpm build
  3. See build logs, and dist/client/sitemap.xml. Duplicate entries for /blog and /contact are generated, one with a trailing slash, and one without

Expected behavior

Only one entry should be generated for each page, for structures like blog.index.tsx or blog/index.tsx

Screenshots or Videos

No response

Platform

  • Router / Start Version: 1.167.5 / 1.166.17
  • OS: Fedora Linux 43
  • Bundler: Vite
  • Bundler Version: 8.0.1

Additional context

Workarounds:

  • As mentioned above, a flat route structure like contact.tsx works fine if it doesn't have child routes, otherwise it will get treated like a layout route.
  • For routes that have child routes like /blog, These pages can be manually excluded in the Start Vite plugin
    {
      // Workaround to exclude "/blog/" from sitemap, so we only get "/blog"
      path: "/blog/",
      prerender: { enabled: false },
      sitemap: { exclude: true },
    },
    ref: https://github.com/dotnize/start-static-test/blob/main/vite.config.ts#L35-L40

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions