Skip to content

Types ​

Source: src/runtime/types.ts.

One heading entry in the TOC tree — mirrors what @nuxt/content puts at page.body.toc.links on both Content v2 and v3.

ts
// 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).

ts
// 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:

  1. Toc itself — { links: [...] }
  2. Full document — { body: { toc: { links: [...] } } } (preferred input: page.body.toc)
  3. Document with root toc — { toc: { links: [...] } }

So inside pages this is idiomatic:

ts
const toc: Toc | null = page.value?.body?.toc ?? null

NuxtTocFetch ​

Runtime helper injected by the version-specific plugin. You rarely call it directly — <TableOfContents> does when :toc is omitted.

ts
// 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:

ts
// 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 ​

ts
// 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 | 3

Full runtime config view: Runtime config. Detection helper: detectContentMajor(rootDir) — exported for testing/advanced use, not needed in app code.

Concrete example ​

vue
<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.

Released under the MIT License.