Organization Layer

Map of Content (MOC) Generator

Source Files: mocGenerator.ts, semanticSearch.ts Complexity: Medium

The Map of Content (MOC) Generator automatically groups and indexes notes in your vault. By clustering notes into high-level topic categories using the LLM, it generates structured markdown indexes that act as table of contents files for your vault.

1. Overview

As a note vault grows, it becomes harder to get an overview of what is in it. While folders and tags help, they don't provide a narrative index. A Map of Content (MOC) solves this:

  • Clustering: Evaluates all notes in the vault and groups them into 3 to 7 logical topic clusters.
  • Narrative Topic Pages: Generates a dedicated markdown file for each topic (e.g. _moc/artificial-intelligence.md) containing a one-sentence topic description and links to all matching notes.
  • Central Index: Generates a central _moc/index.md listing all topic clusters and linking to their respective topic files.

2. Under the Hood & Code Walkthrough

2.1 Topic Clustering Prompt

The generator gathers note information and asks the LLM to group them into 3 to 7 clusters. It uses strict JSON response formatting to make it easy to parse:

const prompt = `Group these notes into 3-7 topic clusters based on their content and tags. Return ONLY a JSON array: [{ "topic": "Topic Name", "description": "One sentence description", "noteIndices": [1, 3, 5] }]

Notes:
${noteList}`;

2.2 Writing Topic Files & Index

The extension clears the _moc/ directory, converts topic names into clean slugs, and writes the markdown files:

// Generate topic files
const indexEntries: string[] = [];
for (const cluster of clusters) {
    const slug = slugify(cluster.topic);
    const noteLinks = cluster.noteIndices
        .filter(i => i >= 1 && i <= notes.length)
        .map(i => {
            const note = notes[i - 1];
            const relativePath = path.relative(mocDir, note.filePath);
            return `- [${path.basename(note.filePath)}](${relativePath})`;
        })
        .join('\n');

    const topicContent = `# ${cluster.topic}\n\n${cluster.description}\n\n## Notes\n\n${noteLinks}\n`;
    await fsp.writeFile(path.join(mocDir, `${slug}.md`), topicContent, 'utf8');

    indexEntries.push(`- [${cluster.topic}](${slug}.md) β€” ${cluster.description}`);
}

// Generate central index
const indexContent = `# Map of Content\n\n${indexEntries.join('\n')}\n`;
const indexPath = path.join(mocDir, 'index.md');
await fsp.writeFile(indexPath, indexContent, 'utf8');