feat(notion-api): restore Notion sidebar hierarchy in import tree#520
Open
oliviermattei wants to merge 1 commit intoobsidianmd:masterfrom
Open
feat(notion-api): restore Notion sidebar hierarchy in import tree#520oliviermattei wants to merge 1 commit intoobsidianmd:masterfrom
oliviermattei wants to merge 1 commit intoobsidianmd:masterfrom
Conversation
- Default preserveHierarchy to true so folders mirror the Notion sidebar - Ensure intermediate ancestor folders are created before importing each item - Always import databases explicitly even when disabled (they are not cascaded as child_page blocks by their parent page) - Build rawParentMap from all raw Search items (including filtered) so buildTree can escalate past missing/filtered parents to the nearest visible ancestor instead of dropping to root - Resolve block_id parent chains via targeted API calls so items nested inside columns/toggles are correctly attached to their workspace page (fixes pages like Antibes, Architecture appearing at vault root)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Notion API importer now mirrors your Notion sidebar structure as nested folders in Obsidian.
Previously all imported pages and databases were dumped flat into the output folder regardless of how they were organised in Notion. This was caused by three bugs: the hierarchy option defaulted to off, databases that were children of a selected page were silently skipped, and any item nested inside a layout block (column, toggle, callout) had its parent chain broken by the API, landing it at vault root.
This fix enables hierarchy preservation by default, ensures databases are always imported explicitly, and resolves the block chain by making targeted API calls at load time to recover the missing parent links.
Problem
When importing from Notion via the API importer, the vault output was completely flat: every page and database ended up at the root of the output folder regardless of its position in the Notion sidebar. Users with a structured workspace would get hundreds of unrelated files dumped at the same level, making the result unusable without manual reorganisation.
There were three distinct root causes.
1.
preserveHierarchydefaulted tofalseThe option to mirror the Notion sidebar structure existed but was opt-in and off by default. Most users would never discover it, and a flat output is rarely what anyone wants when their Notion workspace has meaningful structure.
2. Databases selected as children were silently skipped
When a user selects a parent page that contains a database,
selectAllChildren()marks the database node asdisabled. The import loop filtered out alldisablednodes — including databases.Unlike sub-pages, databases are not imported as
child_pageblocks inside their parent page's content: the Notion API returns them as independentdata_sourceobjects. They must always be imported with an explicit call regardless of theirdisabledstate, otherwise any database that is a child of a selected page is simply never imported.3. Items nested inside layout blocks fell to vault root
This was the most impactful bug. Some Notion pages and databases live inside a layout block (column, toggle, callout…) rather than directly under a page. The Search API marks these items with
parent.type = "block_id". Because block objects are not returned by Search,extractParentId()resolvesblock_idtonull, silently breaking the ancestry chain. Every item whose parent chain passed through a block was orphaned at vault root.Example — Notion sidebar structure:
Before this fix — vault output:
After — vault output:
Solution
preserveHierarchydefaults totrueThe toggle is now enabled by default so the output mirrors the Notion sidebar out of the box. Users can disable it for a flat import if they prefer.
Databases always imported explicitly
getSelectedNodeIds()now includesdisablednodes of typedatabasein the import list, regardless of whether their parent was selected.Ancestry escalation via
rawParentMap+ block chain resolutionTwo additions to
loadPageTree():rawParentMap— a map built from all raw Search results (including filtered items) that records every item's direct parent ID. This is passed tobuildTree().Ancestor escalation in
buildTree()— when a node's directparentIdis not present in the visible tree,resolveVisibleParent()walks uprawParentMapuntil it finds the nearest visible ancestor (cycle-safe). This handles items whose parent is inaccessible or was filtered for another reason.Block chain resolution — for filtered items whose parent is a
block_id, the importer makes targetedblocks.retrieve()calls at load time, walking up the block chain until it reaches apage_id. This page ID is written back intorawParentMap, giving the escalation logic the missing link it needs to attach those items to the correct workspace page.The number of extra API calls equals the number of unique
block_idvalues across all filtered items — typically a handful per workspace.Changes
src/formats/notion-api.tsNo changes to other importers, helper modules, or test data.
Testing
Validated against a real Notion workspace with ~2 200 items including pages nested 4–5 levels deep, databases inside columns and toggles, and databases marked as children of selected parent pages.