Guide
What are nested documents?
Nested Documents are a powerful feature in Fibery that allows users to create a hierarchy of documents to organize information more effectively. Here are some use cases:
Knowledge base: Use nested documents to create a knowledge base for your team or company. You can have a top-level document for each category, with sub-documents for specific topics. This makes it easy to find and share information.
Customer support: Use nested documents to create a customer support system and user guides. You can write a user guide for your product as a set of nested documents and make it public via Publish Space to Web.
Notes: Capture notes and other unstructured information in documents. You can transform these notes into real entities such as tasks, projects, bugs, etc. later.
Research: Use nested documents to organize research and information for a project or paper. Create a top-level document for the project, with sub-documents for specific topics or sources. This makes it easy to keep track of information and sources.
Personal to-do: Manage your personal to-do list in Private Space. Create a top-level document named "My To-Do" and create large tasks as nested documents. This way, you can write articles, posts, ideas, and more:
How to create a nested document?
There are three ways to create a nested document.
1. From the sidebar
Click the + button in the sidebar next to the document, and it will be created immediately.
2. Using the /document command
Type / anywhere in a document and find the Document command.
Type the name of a document and click the Create option below:
3. Using the /insert entity command
Type / anywhere in a document and find the Insert Entity command (or just type # in a document).
Select Document from the drop-down menu and create a new document.
How to move and re-nest nested documents?
Simply drag any document and drop it where needed. You may nest documents by dropping a document onto the name of the parent document. Check out this GIF for a visual example:
How to delete a nested document?
There are two ways to delete a document:
Click on ... in the sidebar near the document and select the Delete Document option.
Click on ... in the top right corner of the document and select the Delete Document option.
🚨 When you delete a document, all nested documents will also be deleted. If you recover a deleted document using the Trash feature, all nested documents will also be recovered.
When you delete a reference to a nested document from a parent document, you are only deleting the reference, not the nested document itself.
FAQ
I want to see the full hierarchy of nested documents.
Currently, you can only view it in the sidebar. However, we plan to make it more explicit in the future.
You may also use a script workaround, suggested by Yuri_BC.
This script automates the creation and updating of a hierarchical Table of Contents (TOC) for a Fibery entity (in this case of database ‘Page’) and its sub entities (sub Pages), facilitating easier navigation and organization of content.
const fibery = context.getService('fibery');
const pageType = 'YourSpaceName/Page'; // Replace YourSpaceName
const tocType = 'YourSpaceName/TOC'; // Replace YourSpaceName
const baseUrl = 'https://YourAccountName.fibery.io/YourSpaceName/Page/'; // Replace YourAccountName and YourSpaceName
const databaseId = '8ff09230-0883-11ee-a2e3-dd72e97a05a2'; // Replace with the UUID of your Page database
async function generateTOCAndAppendForSubPages() {
const currentPageEntity = args.currentEntities[0];
let pageEntity = await fibery.getEntityById(pageType, currentPageEntity.id, ['Sub Pages', 'TOC', 'Name']);
if (!pageEntity) return;
let parentTocEntity;
if (pageEntity.TOC && pageEntity.TOC.id) {
parentTocEntity = await fibery.getEntityById(tocType, pageEntity.TOC.id, ['Description', 'Level']);
} else {
parentTocEntity = await fibery.createEntity(tocType, { 'Name': `Aggregated Table Of Contents of Subpages`, 'Page': pageEntity.id });
}
if (!parentTocEntity.Level) {
await fibery.updateEntity(tocType, parentTocEntity.id, { 'Level': 'bbed5bd0-f38c-11ee-8ba1-7bd35f7e50e0' });
parentTocEntity = await fibery.getEntityById(tocType, parentTocEntity.id, ['Description', 'Level']);
}
const maxDepth = getMaxDepthFromLevelEntity(parentTocEntity.Level ? parentTocEntity.Level.Name : '3');
let tocContent = [];
for (const subPage of pageEntity['Sub Pages']) {
const subPageEntity = await fibery.getEntityById(pageType, subPage.id, ['Description', 'Public Id', 'Name']);
if (subPageEntity && subPageEntity.Description && subPageEntity.Description.Secret) {
let descriptionContentJson = await fibery.getDocumentContent(subPageEntity.Description.Secret, 'json');
tocContent = tocContent.concat(createHierarchicalTOCJson(descriptionContentJson, subPageEntity['Public Id'], subPageEntity.Name, subPage.id, maxDepth));
}
}
if (parentTocEntity.Description && parentTocEntity.Description.Secret && tocContent.length > 0) {
await fibery.setDocumentContent(parentTocEntity.Description.Secret, JSON.stringify({ doc: { type: "doc", content: tocContent } }), 'json');
}
}
function createHierarchicalTOCJson(descriptionContentJson, publicId, pageTitle, pageId, maxDepth) {
const tocEntry = { type: "paragraph", content: [{ type: "entity", attrs: { id: pageId, text: pageTitle, typeId: databaseId, }, marks: [{ type: "strong" }] }] };
const baseIndent = " ";
const additionalIndent = " ";
let isFirstHeading = true;
descriptionContentJson.doc.content.forEach(block => {
if (block.type === 'heading' && block.attrs.level <= maxDepth) {
if (isFirstHeading) {
tocEntry.content.push({ type: "hard_break" });
isFirstHeading = false;
} else {
tocEntry.content.push({ type: "hard_break" });
}
const indent = baseIndent + additionalIndent.repeat(block.attrs.level - 1);
const bulletPoint = "• ";
const textContent = block.content.map(element => element.text || '').join('');
tocEntry.content.push({ type: "text", text: indent + bulletPoint }, { type: "text", text: textContent, marks: [{ type: "link", attrs: { href: `${baseUrl}${publicId}/anchor=${block.attrs.guid}` } }] });
}
});
return [tocEntry];
}
function getMaxDepthFromLevelEntity(levelText) {
if (!levelText) return 3;
const match = levelText.match(/\d+/);
return match ? parseInt(match[0], 10) : 3;
}
await generateTOCAndAppendForSubPages();
Can I share the nested documents?
Yes! you can share nested documents with the public and all nested documents are shared automatically. Note that nested views will not be shared though.