Types
Source: src/runtime/types.ts.
TocLink
One heading entry in the TOC tree — mirrors what @nuxt/content puts at page.body.toc.links on both Content v2 and v3.
// src/runtime/types.ts:12
export interface TocLink {
/** Anchor id used in `href="#id"` and on the heading element itself (`<h2 id="…">`). */
id: string
/** Visible label — heading text stripped of Markdown. */
text: string
/** Heading depth from Content, when provided (2 for `##`, 3 for `###`, …). */
depth?: number
/** Nested entries under this heading (e.g. h3 under an h2). */
children?: TocLink[]
}Toc
Root payload handed to :toc (or extracted from a full document by normalizeToc).
// src/runtime/types.ts:37
export interface Toc {
/** Top-level links for the document. Empty array `[]` is valid → empty TOC. */
links: TocLink[]
}normalizeToc(doc) (src/runtime/utils/normalize-toc.ts:21) extracts a Toc from three accepted shapes:
Tocitself —{ links: [...] }- Full document —
{ body: { toc: { links: [...] } } }(preferred input:page.body.toc) - Document with root
toc—{ toc: { links: [...] } }
So inside pages this is idiomatic:
const toc: Toc | null = page.value?.body?.toc ?? nullNuxtTocFetch
Runtime helper injected by the version-specific plugin. You rarely call it directly — <TableOfContents> does when :toc is omitted.
// src/runtime/types.ts:54
export type NuxtTocFetch = (
path: string, // Content document path, e.g. '/docs/intro'
collection?: string, // Content v3 collection (default 'content'); ignored on v2
) => Promise<{ body?: { toc?: Toc } | null } | null | undefined>Augmentations:
// src/runtime/types.ts:62 — typed on the Nuxt app + Vue instance
declare module '#app' {
interface NuxtApp {
$nuxtTocFetch?: NuxtTocFetch
}
}
declare module 'vue' {
interface ComponentCustomProperties {
$nuxtTocFetch?: NuxtTocFetch
}
}Accessible via useNuxtApp().$nuxtTocFetch.
Module & runtime config types
// src/module.ts:31
export interface ModuleOptions {
collection?: string // default 'content' (v3)
depth?: number // default 2
scrollSpy?: boolean // default true
rootMargin?: string // default '0px 0px -80% 0px'
smooth?: boolean // default false
scrollOffset?: number // default 0
}
// src/module.ts:73
export interface NuxtTocPublicRuntimeConfig {
collection: string
depth: number
scrollSpy: boolean
rootMargin: string
smooth: boolean
scrollOffset: number
contentMajor: 2 | 3 | null // detection result — see detect-content-major.ts
}
// src/utils/detect-content-major.ts:13
export type ContentMajor = 2 | 3Full runtime config view: Runtime config. Detection helper: detectContentMajor(rootDir) — exported for testing/advanced use, not needed in app code.
Concrete example
<script setup lang="ts">
import type { Toc } from '#build/types' // generated by nuxi
const route = useRoute()
const { data: page } = await useAsyncData(route.path, () =>
queryCollection('content').path(route.path).first(),
)
const toc = computed<Toc | null>(() => page.value?.body?.toc ?? null)
</script>
<template>
<TableOfContents :toc="toc" title="On this page" :depth="2" />
</template>Content always returns { links: TocLink[] } even when deeply nested (children arrays). See Writing content for how Markdown headings map to this shape, and Props — depth for how limitTocDepth trims it before rendering.
