Dynamic section JSON
A dynamic section stores one JSON source and expands it at viewer startup into a root page and a nested tree of virtual pages. The source, page content, and Base64 resources are embedded in the exported HTML; no external JSON endpoint is used.
Complete structure
{
"schemaVersion": "1.0",
"settings": {
"navigation": {
"expandedByDefault": false,
"placement": "toc",
"showRootInToc": true
},
"search": { "enabled": true },
"toc": {
"enabled": true,
"minHeadingLevel": 2,
"maxHeadingLevel": 4
}
},
"styles": ".dynamic-badge { color: #2563eb; }",
"scripts": "console.log('Dynamic section page opened');",
"resources": [
{
"id": "logo",
"contentType": "image/png",
"encoding": "base64",
"content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=",
"fileName": "logo.png"
}
],
"root": {
"contentType": "markdown",
"content": "# Catalog\n\n",
"toc": true,
"styles": ".dynamic-badge { font-weight: 700; }"
},
"pages": [
{
"id": "overview",
"title": "Overview",
"slug": "overview",
"contentType": "markdown",
"content": "## Introduction\n\nOpen the [details](ofd-page:details).",
"hidden": false,
"searchable": true,
"toc": true,
"scripts": "document.getElementById('main-article')?.setAttribute('data-page-ready', 'true');",
"children": [
{
"id": "details",
"title": "Details",
"slug": "details",
"contentType": "html",
"content": "<h2>Details</h2><img src=\"res://logo\" alt=\"Logo\">"
}
]
}
]
}Required fields
schemaVersionmust be"1.0".resourcesandpagesmust be arrays, including when empty.rootmust containcontentTypeand stringcontent.- Every page requires unique
id, non-emptytitle,contentType, and stringcontent.
contentType is html or markdown. A page may use either independently of the root and other pages.
Settings
settings.navigation.expandedByDefaultexpands page navigation initially.settings.navigation.placementistoc,header-toc, ortoc-otp. These place pages and current-page headings in the table of contents, header, or On This Page panel.settings.navigation.showRootInToccontrols whether the main section link appears in Contents. The default istrue.settings.search.enabledcontrols whether the dynamic section is included in search. The default istrue.settings.toc.enabledis the default heading-TOC behavior for the root and pages.minHeadingLevelandmaxHeadingLevelaccept values from 1 to 6, and the minimum cannot exceed the maximum.
Missing settings are normalized to collapsed navigation in toc with the main section shown, enabled search, and disabled heading TOC with levels 2 through 4.
Styles and scripts
Optional top-level styles and scripts strings apply to the root and every virtual page. The root object and each page may define their own optional styles and scripts. Saved section code runs first, followed by common dynamic code and then page-specific code. Styles are active only while that page is open; scripts run on every page opening.
Sources that omit these fields remain valid schema 1.0 sources and behave as before.
Pages and routes
slug becomes the page's route segment. It must contain lowercase Latin letters, digits, and single hyphens. If omitted, it is generated from the title. Slugs must be unique among siblings; page IDs must be unique across the whole source.
children contains nested pages. A source can contain at most 2,000 pages and be at most 10 levels deep. hidden hides a page from navigation, searchable excludes only that page from search when false, and toc overrides the section TOC default.
Use ofd-page:page-id to link to another virtual page. The referenced ID must exist.
Embedded resources
Each resource requires a unique lowercase id, a non-empty MIME contentType, encoding: "base64", and valid non-empty Base64 content. The optional fileName is used when opening or downloading a file. IDs may contain Latin letters, digits, dots, hyphens, and underscores.
Reference a resource as res://resource-id from HTML or Markdown. Every referenced ID must exist. Executable MIME types, HTML documents, scripts, inline event handlers, executable URLs, and resources loaded through http:, https:, data:, or blob: are rejected.
Validation
The editor reports errors with the path to the invalid field, such as pages[2].content. Validate and review the page count, resource count, and maximum depth before applying the source. Generated pages are not stored as separate sections; update their structure or content by replacing the JSON.