Visual editing /Visual Editor /

Sitemap navigator

Populating the sitemap navigator allows you to use it for navigating website pages. The sitemap navigator provides a single point from which to access all editable pages on a website.

sitemap navigator

The sitemap provides two ways to navigate:

# Tree view

The sitemap is built in a hierarchical way using the urlPath from page documents. (More on this below.)

It is collapsed by default, so that only top-level pages are visible. Each page can be expanded and collapsed as needed.

sitemap navigator toggle

# Search pages

On larger sites, it's usually easier to search for a page. The search field is automatically focused when opening the sitemap. Search values query a page document's title and urlPath properties.

sitemap navigator search

# Populate the sitemap

The sitemap will be populated by default, according to your content schema. But it can also be customized as needed.

# Default sitemap from pages

By default, the sitemap is populated by retrieving the urlPath value from all documents of models with the type property set to page.

For content sources with inferred schemas (most headless CMSs), this typically involves extending the models that represent pages.

// stackbit.config.ts
import { defineStackbitConfig } from "@stackbit/types";

export default defineStackbitConfig({
  contentSources: [
    // ...
  modelExtensions: [
    { name: "page", type: "page", urlPath: "/{slug}" },
    { name: "post", type: "page", urlPath: "/blog/{slug}" }

In this case, all pages and posts will show up in the sitemap.

# Custom sitemap

To override default behavior, use the siteMap property. (See the reference.)

The siteMap property provides an array of SiteMapEntry objects. These objects can specify URL paths or be tied directly to a document. We suggest using TypeScript to introspect the expected properties.

Here's an example that implements a similar approach to the default sitemap behavior.

// stackbit.config.ts
import {
} from "@stackbit/types";

export default defineStackbitConfig({
  contentSources: [
    // ...
  modelExtensions: [{ name: "page", type: "page", urlPath: "/{slug}" }],
  siteMap: ({ documents, models }) => {
    const pageModels = models.filter(m => m.type === "page").map(m =>;
    return documents
      .filter(d => pageModels.includes(d.modelName))
      .map(document => {
        const slug = getLocalizedFieldForLocale(document.fields.slug);
        if (!slug.value) return null;
        const urlPath = "/" + slug.value.replace(/^\/+/, "");
        return {
          isHomePage: urlPath === "/"
      .filter(Boolean) as SiteMapEntry[];