0
# Navigation & Structure
1
2
Tools for building navigation elements and extracting structural information from Notion pages including table of contents generation and workspace traversal.
3
4
## Capabilities
5
6
### Get Page Table of Contents
7
8
Generates a table of contents by parsing H1, H2, and H3 header elements from a page.
9
10
```typescript { .api }
11
/**
12
* Gets the metadata for a table of contents block by parsing the page's H1, H2, and H3 elements
13
* @param page - The page block to analyze
14
* @param recordMap - Extended record map containing all blocks
15
* @returns Array of TOC entries with hierarchy information
16
*/
17
function getPageTableOfContents(
18
page: PageBlock,
19
recordMap: ExtendedRecordMap
20
): Array<TableOfContentsEntry>;
21
22
interface TableOfContentsEntry {
23
/** Block ID of the header */
24
id: string;
25
/** Block type (header_1, header_2, header_3) */
26
type: BlockType;
27
/** Header text content */
28
text: string;
29
/** Indentation level (0, 1, 2) */
30
indentLevel: number;
31
}
32
```
33
34
**Usage Example:**
35
36
```typescript
37
import { getPageTableOfContents } from "notion-utils";
38
39
const toc = getPageTableOfContents(pageBlock, recordMap);
40
toc.forEach(entry => {
41
const indent = " ".repeat(entry.indentLevel);
42
console.log(`${indent}- ${entry.text} (${entry.type})`);
43
});
44
45
// Example output:
46
// - Introduction (header_1)
47
// - Overview (header_2)
48
// - Getting Started (header_2)
49
// - Installation (header_3)
50
// - Advanced Topics (header_1)
51
```
52
53
### Get All Pages in Space
54
55
Performs a traversal over a Notion workspace to collect all reachable pages.
56
57
```typescript { .api }
58
/**
59
* Performs a traversal over a Notion workspace starting from a seed page
60
* @param rootPageId - Starting page ID for traversal
61
* @param rootSpaceId - Space ID containing the pages (can be undefined)
62
* @param getPage - Function to fetch page data by ID
63
* @param options - Traversal configuration options
64
* @returns Promise resolving to a map of all discovered pages
65
*/
66
function getAllPagesInSpace(
67
rootPageId: string,
68
rootSpaceId: string | undefined,
69
getPage: (pageId: string) => Promise<ExtendedRecordMap>,
70
options?: TraversalOptions
71
): Promise<PageMap>;
72
73
interface TraversalOptions {
74
/** Number of concurrent page requests (default: 4) */
75
concurrency?: number;
76
/** Whether to traverse collection database items (default: true) */
77
traverseCollections?: boolean;
78
/** Optional target page ID to stop at when found */
79
targetPageId?: string;
80
/** Maximum traversal depth (default: Infinity) */
81
maxDepth?: number;
82
}
83
84
type PageMap = Record<string, ExtendedRecordMap>;
85
```
86
87
**Usage Example:**
88
89
```typescript
90
import { getAllPagesInSpace } from "notion-utils";
91
92
// Function to fetch a page (you provide this)
93
async function fetchPage(pageId: string): Promise<ExtendedRecordMap> {
94
// Your implementation to fetch page data
95
return await notion.getPage(pageId);
96
}
97
98
// Traverse workspace starting from a root page
99
const allPages = await getAllPagesInSpace(
100
"root-page-id",
101
"space-id",
102
fetchPage,
103
{
104
concurrency: 6,
105
traverseCollections: true,
106
maxDepth: 10
107
}
108
);
109
110
console.log(`Found ${Object.keys(allPages).length} pages`);
111
112
// Access individual pages
113
Object.entries(allPages).forEach(([pageId, recordMap]) => {
114
const title = getPageTitle(recordMap);
115
console.log(`Page ${pageId}: ${title}`);
116
});
117
```
118
119
### Get Page Content Block IDs
120
121
Gets all block IDs contained within a page, including nested content.
122
123
```typescript { .api }
124
/**
125
* Gets the IDs of all blocks contained on a page starting from a root block ID
126
* @param recordMap - Extended record map containing all blocks
127
* @param blockId - Starting block ID (uses first block if not provided)
128
* @returns Array of all block IDs found on the page
129
*/
130
function getPageContentBlockIds(recordMap: ExtendedRecordMap, blockId?: string): string[];
131
```
132
133
**Usage Example:**
134
135
```typescript
136
import { getPageContentBlockIds } from "notion-utils";
137
138
// Get all block IDs for a page
139
const blockIds = getPageContentBlockIds(recordMap);
140
console.log(`Page contains ${blockIds.length} blocks`);
141
142
// Get blocks starting from specific block
143
const childBlockIds = getPageContentBlockIds(recordMap, "specific-block-id");
144
console.log(`Section contains ${childBlockIds.length} blocks`);
145
146
// Use block IDs to access individual blocks
147
blockIds.forEach(blockId => {
148
const block = recordMap.block[blockId]?.value;
149
if (block) {
150
console.log(`Block ${blockId}: ${block.type}`);
151
}
152
});
153
```
154
155
## Types
156
157
```typescript { .api }
158
// Re-exported from notion-types
159
interface ExtendedRecordMap {
160
block: Record<string, Block>;
161
collection?: Record<string, Collection>;
162
collection_view?: Record<string, CollectionView>;
163
notion_user?: Record<string, NotionUser>;
164
collection_query?: Record<string, any>;
165
signed_urls?: Record<string, string>;
166
preview_images?: Record<string, string>;
167
}
168
169
interface PageBlock extends Block {
170
type: "page";
171
properties?: {
172
title?: Decoration[];
173
};
174
format?: {
175
page_icon?: string;
176
page_cover?: string;
177
page_cover_position?: number;
178
page_full_width?: boolean;
179
page_small_text?: boolean;
180
};
181
}
182
183
// Navigation-specific types
184
interface TableOfContentsEntry {
185
id: string;
186
type: BlockType;
187
text: string;
188
indentLevel: number;
189
}
190
191
interface TraversalOptions {
192
concurrency?: number;
193
traverseCollections?: boolean;
194
targetPageId?: string;
195
maxDepth?: number;
196
}
197
198
type PageMap = Record<string, ExtendedRecordMap>;
199
type BlockType = 'header_1' | 'header_2' | 'header_3' | 'text' | 'bulleted_list' | 'numbered_list' | 'page' | /* ... many other block types */;
200
```