Customize the "Overview" title of your Starlight Table of Contents

This guide shows how you can customize the first heading in the right sidebar (table of contents) of every Starlight page globally and individually.

Each Starlight page contains a table of contents on the right side (except if disabled). To be able to link to the top of the page, the first entry of this sidebar has the title "Overview" (as you can also see on this page's sidebar), which can be customized globally and even on a per-page basis.

Global definition

If you want to set the title of the first table of contents entry once for all pages, you can follow these steps to achieve this for monolingual and multilingual sites:

Create route middleware to customize the data shown by Starlight.

Use this example code to configure the "Overview" title:

// src/routeData.ts
import { defineRouteMiddleware } from "@astrojs/starlight/route-data";

export const onRequest = defineRouteMiddleware((context) => {
const { starlightRoute } = context.locals;

const overviewItem = starlightRoute.toc?.items[0];
if (overviewItem) overviewItem.text = "Back to top";
});

If your site is multilingual, you can also assign different titles depending on the locale:

// src/routeData.ts
import { defineRouteMiddleware } from "@astrojs/starlight/route-data";
import starlightConfig from "virtual:starlight/user-config";

const defaultLang =
starlightConfig.defaultLocale.lang ??
starlightConfig.defaultLocale.locale ??
"en";

const translations: Record<string, string> = {
en: "Back to top",
de: "Zurück nach oben",
};

export const onRequest = defineRouteMiddleware((context) => {
const { starlightRoute } = context.locals;
const { locale } = starlightRoute;

const overviewItem = starlightRoute.toc?.items[0];
if (overviewItem) overviewItem.text = translations[locale ?? defaultLang];
});

Frontmatter override

In order to set the first table of contents heading to something different on individual pages, follow the steps below:

Extend your frontmatter schema in src/content.config.ts:

// src/content.config.ts
import { defineCollection, z } from 'astro:content';
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';

export const collections = {
docs: defineCollection({
loader: docsLoader(),
schema: docsSchema({
extend: z.object({
overviewTitle: z.string().optional(),
}),
}),
}),
};

This allows you to use the overviewTitle in your middleware like that:

// src/routeData.ts
import { defineRouteMiddleware } from "@astrojs/starlight/route-data";

export const onRequest = defineRouteMiddleware((context) => {
const { starlightRoute } = context.locals;
const individualOverviewTitle = starlightRoute.entry.data.overviewTitle;

const overviewItem = starlightRoute.toc?.items[0];
if (overviewItem)
overviewItem.text = individualOverviewTitle ?? "Back to top";
});

For the sake of completeness, here is a multilingual middleware that supports overriding on individual pages:

// src/routeData.ts
import { defineRouteMiddleware } from "@astrojs/starlight/route-data";
import starlightConfig from "virtual:starlight/user-config";

const defaultLang =
starlightConfig.defaultLocale.lang ??
starlightConfig.defaultLocale.locale ??
"en";

const translations: Record<string, string> = {
en: "Back to top",
de: "Zurück nach oben",
};

export const onRequest = defineRouteMiddleware((context) => {
const { starlightRoute } = context.locals;
const { locale } = starlightRoute;
const individualOverviewTitle = starlightRoute.entry.data.overviewTitle;
const overviewItem = starlightRoute.toc?.items[0];
if (overviewItem)
overviewItem.text =
individualOverviewTitle ?? translations[locale ?? defaultLang];
});

Source code

You can also find the complete source code for all four variants on GitHub or open the project directly in StackBlitz.