<aside> 💡 Update: The priority is changed to low because I think that it's not a good idea anymore. First, nested sub-pages are outside of Notablog table, so it doesn't have properties that those pages in the table have, making it not manageable. Second, recursive traversal is dirty, since we don't know when will it stop and there is no consensus for on what condition it should stop. To keep Notablog's concept and consistent, it comes to me that, it's important to encourage users to consciously separate what's inside Notablog's scope and what's not. Therefore, a better model is that we require users to put the pages they want to be rendered in the table, and use "link to page" blocks, inline mention pages, or inline links to link to them, creating a "web of pages" inside one table.

</aside>

This feature requires changes in both Notablog and NAST, which effects the whole architecture, so it is considered a core change and must be planned carefully.

For context, Notablog now uses [getOnePageAsTree()](<https://github.com/dragonman225/nast/tree/master/packages/nast-util-from-notionapi#async-getonepageastreepageid-agent>) from [nast-util-from-notionapi](<https://github.com/dragonman225/nast/tree/master/packages/nast-util-from-notionapi>) to get an intermediate representation (IR) of a Notion page, and renders that IR to HTML with [renderToHTML()](<https://github.com/dragonman225/nast/tree/master/packages/nast-util-to-react#rendertohtmltree>) from nast-util-to-react.

Changes for nast-util-from-notionapi

In order to support nested sub-pages, first we need to know if there're other pages in a page. To get that information, we would modify getOnePageAsTree(). Instead of returning only the IR, it would also return the ids of the sub-pages inside the page it's processing.

For example, change the return value of getOnePageAsTree() from [NAST.Block](<https://github.com/dragonman225/nast/blob/04a345f334f8232c2627bc47d2db0141b199036a/packages/nast-types/index.d.ts#L12>) to

{
	content: [NAST.Block](<https://github.com/dragonman225/nast/blob/04a345f334f8232c2627bc47d2db0141b199036a/packages/nast-types/index.d.ts#L12>),
	subPages: [NAST.UUID](<https://github.com/dragonman225/nast/blob/04a345f334f8232c2627bc47d2db0141b199036a/packages/nast-types/util.d.ts#L34>)[]
}

To get the ids of the sub-pages, one could collect them when converting the raw Notion page tree to the NAST IR (refer to this).

Changes for Notablog

Once we can get the ids of sub-pages, we can use getOnePageAsTree() with the ids to get IR of sub-pages. (Bonus: use [TaskManager2](<https://github.com/dnpr/task-manager/blob/1f3724a7328b63be065a58371bb03f6d850a264c/src/task-manager-2.js#L6>) from [@dnpr/task-manager](<https://github.com/dnpr/task-manager>) to queue the function calls and execute them concurrently, since inside getOnePageAsTree() it makes many requests to Notion API so it is sloooow.) After getting IR of all top-level pages and their sub-pages, we use renderToHTML() as usual to render them.

Link everything

Finally, there is one last thing to do — handle the links between pages. In Notion, when we click a page block, Notion will bring us to that page. Likewise, when we click a page block in a static HTML generated by Notablog, we jump to another static HTML. Therefore, the goal is to map the links in Notion to the links in Notablog. We need a map. (Notablog should prepare such a map)

In Notion, internally it uses id to link pages, and in Notablog, we use <a> element with href attribute to link two HTML files. So, the map would be in the form of

Map<NAST.UUID, string>

, where the string is a path to the HTML file generated from the Notion page NAST.UUID.

Then, we need to modify renderToHTML() in nast-util-to-react so that it is able to use the map to fill in correct href attribute for the <a> element in the [Page component](https://github.com/dragonman225/nast/blob/master/packages/nast-util-to-react/src/components/Page.tsx).

The benefit of this approach is that renderToHTML() would be flexible. For example, if someone not using Notablog wants to use renderToHTML() to generate a single page and keep the sub-pages blocks linked to their original Notion pages, he/she would just need to provide a map in the same format as the above map, but where the string is an URL of the Notion page NAST.UUID.

Additional issue

Beside page blocks, inline links also can link to other Notion pages. However, handling them is more tricky. Inline links are part of [SemanticString](<https://github.com/dragonman225/nast/blob/04a345f334f8232c2627bc47d2db0141b199036a/packages/nast-types/SemanticString.d.ts#L162>), and it is used in so many blocks. Currently I'm not clear enough about how much the work is if we want to modify such a fundamental stuff, and I'm not confident enough to make the change now. So, it may be better that we just treat all these links as external links and keep them untouched for now.