Skip to content

Architecture Overview (v3.0.0+)

This document describes the complete architecture of the MkDocs-Note plugin in v3.0.0+, which adopts a simplified, lightweight design philosophy focused on core documentation needs.


Project Overview

Project Positioning

MkDocs Note is now a lightweight documentation plugin designed specifically for MkDocs and Material for MkDocs theme. It focuses on essential note management features with minimal complexity.

It just a simple python-based tool that help you manage your notes in MkDocs documentation site, why not make it simpler and concise?

Core Design Philosophy

  • Simplicity First: Minimal code, focused features, easy to understand and maintain

  • Co-located Resources: Asset directories placed alongside note files following the pattern note_file.parent / "assets" / note_file.stem

  • Metadata-driven: Simple frontmatter-based metadata (date, title, publish status)

  • MkDocs Integration: Seamless integration with MkDocs ecosystem, leveraging existing infrastructure


Architecture Evolution

Architecture Timeline

Version Date Philosophy Code Size Complexity
v1.x Early Basic functionality ~3,000 lines Low
v2.0.0 Oct, 2025 Feature-rich, modular ~12,000 lines High
v3.0.0 2025-11-04 Lightweight, simple ~2,700 lines Low

From v2.x to v3.0.0 (Major Simplification)

v2.x Problems:

  • ❌ Over-engineered: Complex modular architecture (assetps/, dataps/, docsps/, fileps/, graphps/)

  • ❌ Too many abstractions: 9,300+ lines of code, hard to maintain

  • ❌ Feature creep: Template system, validation, initialization commands

  • ❌ High maintenance burden: Many moving parts, potential bugs

v3.0.0 Solutions (PR #60):

  • Flat Structure: Moved core modules to package root

  • Minimal Utils: Only essential utilities (meta.py, scanner.py, cli/)

  • Removed Features: Asset management system, template system, validation commands

  • Retained Core: Recent notes, network graph, basic CLI commands

  • Code Reduction: From ~12,000 to ~2,700 lines (77% reduction)

Design Trade-offs

What We Removed:

  • ❌ Asset management subsystem (utils/assetps/)

  • ❌ Data models and frontmatter system (utils/dataps/)

  • ❌ Document operations (creator, cleaner, mover, remover - utils/docsps/)

  • ❌ File I/O abstraction layer (utils/fileps/)

  • ❌ Advanced CLI commands (init, validate, template)

  • ❌ Custom logging module

What We Kept:

  • ✅ Recent notes display

  • ✅ Network graph visualization

  • ✅ Basic CLI: new, remove, move, clean

  • ✅ Simple metadata extraction


Simplified Architecture (v3.0.0+)

Overall Structure Diagram

mkdocs-note/
├── src/mkdocs_note/
│   ├── __init__.py              # Package initialization
│   ├── plugin.py                # MkDocs plugin entry point
│   ├── cli.py                   # Command-line interface entry point
│   ├── config.py                # Configuration management
│   ├── graph.py                 # Network graph functionality
│   │
│   ├── static/                  # Static assets for graph visualization
│   │   ├── graph.js
│   │   └── graph.css
│   │
│   └── utils/                   # Minimal utility modules
│       ├── __init__.py
│       ├── meta.py              # Metadata extraction (title, date, frontmatter validation)
│       ├── scanner.py           # File scanning
│       └── cli/                 # CLI command implementations
│           ├── __init__.py
│           ├── commands.py      # NewCommand, RemoveCommand, MoveCommand, CleanCommand
│           └── common.py        # Common utilities (asset paths, directory cleanup)
│
└── tests/                       # Test suite
    ├── __init__.py
    ├── smoke_test.py            # Smoke tests
    ├── test_config.py           # Configuration tests
    ├── test_plugin.py           # Plugin tests
    ├── test_cli_*.py            # CLI tests
    └── test.sh                  # Test runner script

Module Responsibilities

Module Responsibility Key Functions
plugin.py MkDocs plugin integration File processing, recent notes insertion, graph integration
cli.py CLI entry point Command registration, argument parsing, error handling
config.py Configuration Plugin settings (notes_root, recent_notes_config, graph_config)
graph.py Network graph Node/edge creation, link detection, static asset management
utils/meta.py Metadata Frontmatter validation, title/date extraction
utils/scanner.py File scanning Note file discovery and validation
utils/cli/commands.py CLI commands new, remove, move, clean implementations
utils/cli/common.py CLI utilities Asset directory paths, directory cleanup

Dependency Diagram

graph TB
    subgraph "Entry Points"
        Plugin[plugin.py<br/>MkdocsNotePlugin]
        CLI[cli.py<br/>CLI Entry]
    end

    subgraph "Independet Modules"
        Config[config.py<br/>MkdocsNoteConfig]
        Graph[graph.py<br/>Graph<br/>add_static_resources<br/>inject_graph_script<br/>copy_static_assets]
    end

    subgraph "Utils Layer"
        Meta[utils/meta.py<br/>validate_frontmatter<br/>extract_date<br/>extract_title]
        Scanner[utils/scanner.py<br/>scan_notes]

        subgraph "CLI Submodule"
            Commands[cli/commands.py<br/>NewCommand<br/>RemoveCommand<br/>MoveCommand<br/>CleanCommand]
            Common[cli/common.py<br/>get_asset_directory<br/>cleanup_empty_directories]
        end
    end

    Plugin --> Config
    Plugin --> Scanner
    Plugin --> Meta
    Plugin --> Graph

    CLI ---> Config
    CLI --> Commands

    Commands --> Common
    Scanner --> Meta

    Common -->|Get MkDocsConfig Instance| Plugin

Core Modules Detail

plugin.py - MkDocs Plugin Entry

Responsibility: MkDocs plugin integration and orchestration

Key Components:

class MkdocsNotePlugin(BasePlugin[MkdocsNoteConfig]):
    """MkDocs Note Plugin entry point."""

    notes_list: list[File] = []

    # Event Hooks:
    def on_config(config)           # Add static resources for graph
    def on_pre_build(config)        # Initialize graph if enabled
    def on_files(files, config)     # Scan and validate notes
    def on_nav(nav, config, files)  # Store files reference
    def on_page_markdown(markdown)  # Insert recent notes
    def on_post_page(output)        # Inject graph script
    def on_post_build(config)       # Build graph, copy static assets

Recent Notes Insertion: - Scans notes using scanner.scan_notes() - Validates frontmatter with meta.validate_frontmatter() - Sorts by note_date (extracted from frontmatter) - Replaces marker with HTML list

cli.py - Command Line Interface

Responsibility: Standalone CLI for note management

Architecture:

@click.group()
def cli():
    """MkDocs Note CLI - Manage notes and their assets structure."""

# Commands:
@cli.command("new")      # Create new note
@cli.command("remove")   # Remove note (alias: rm)
@cli.command("move")     # Move/rename note (alias: mv)
@cli.command("clean")    # Clean orphaned assets

Key Features: - Custom command grouping (aliases shown together) - Configuration loading from mkdocs.yml or defaults - Rich feedback with emojis (✅ ❌ 📝 📁) - Confirmation prompts (skip with --yes) - Dry-run support for clean command

config.py - Configuration Management

Responsibility: Plugin configuration schema

Configuration Options:

class MkdocsNoteConfig(Config):
    enabled: bool = True
    notes_root: Path = "docs"

    recent_notes_config: dict = {
        "enabled": False,
        "insert_marker": "<!-- recent_notes -->",
        "insert_num": 10,
    }

    graph_config: dict = {
        "enabled": False,
        "name": "title",      # or "file_name"
        "debug": False,
    }

graph.py - Network Graph Visualization

Responsibility: Generate and visualize note relationships

Core Class:

class Graph:
    LINK_PATTERN = r"\[[^\]]+\]\((?P<url>.*?)\)|\[\[(?P<wikilink>[^\]]+)\]\]"

    def _create_nodes(files)         # Create nodes from documentation pages
    def _create_edges(files)         # Parse markdown for links
    def _find_links(markdown)        # Extract links using regex
    def to_dict()                    # Export graph data

Supporting Functions: - add_static_resources(): Add D3.js and custom JS/CSS to MkDocs config - inject_graph_script(): Inject graph options into HTML - copy_static_assets(): Copy graph.js and graph.css to site directory

Link Detection: - Markdown links: [text](url) - Wiki links: [[page]] - Handles URL escaping, query strings, fragments

utils/meta.py - Metadata Extraction

Responsibility: Simple frontmatter validation and metadata extraction

Key Functions:

def validate_frontmatter(f: File) -> bool:
    """Validate frontmatter, extract date and title.

    Required fields:
    - date: datetime object
    - title: string
    - publish: bool (default True)

    Side effects: Sets f.note_date and f.note_title
    """

def extract_date(f: File) -> Optional[datetime]:
    """Extract date from validated file."""

def extract_title(f: File) -> Optional[str]:
    """Extract title from validated file."""

Validation Rules: - ❌ Skip if publish: false - ❌ Error if missing date or title - ❌ Error if wrong type - ✅ Store metadata as file attributes

utils/scanner.py - File Scanning

Responsibility: Scan and filter note files

Key Function:

def scan_notes(files: Files, config) -> tuple[list[File], list[File]]:
    """Scan notes directory, return (valid_notes, invalid_files).

    Filtering:
    1. Only documentation pages (is_documentation_page())
    2. Within notes_root directory
    3. Valid frontmatter (validate_frontmatter())

    Returns:
        (valid_notes, invalid_files)
    """

MkDocs Integration: - Uses mkdocs.structure.files.Files - Leverages is_documentation_page() for file type filtering - Works with MkDocs' path resolution

utils/cli/commands.py - CLI Command Implementations

Command Classes:

Class Responsibility Key Methods
NewCommand Create new note _generate_note_basic_meta(), execute()
RemoveCommand Remove note and assets _remove_single_document(), _remove_docs_directory()
MoveCommand Move/rename note and assets _move_single_document(), _move_docs_directory()
CleanCommand Clean orphaned assets _scan_note_files(), _find_orphaned_assets()

Common Pattern:

class XxxCommand:
    def _validate_before_execution() -> int
        # Returns 0 (fail), 1 (single file), 2 (directory)

    def execute(path) -> None
        # Main execution logic

utils/cli/common.py - CLI Utilities

Utility Functions:

def get_asset_directory(note_path: Path) -> Path:
    """Co-located asset structure: note.parent / 'assets' / note.stem"""
    return note_path.parent / "assets" / note_path.stem

def cleanup_empty_directories(start_dir: Path, stop_at: Path):
    """Recursively remove empty parent directories."""

def ensure_parent_directory(path: Path):
    """Create parent directory if needed."""

Asset Directory Pattern:

docs/notes/python/intro.md
                 └─ assets/intro/  (asset directory)


Data Models (Simplified)

Core Data Structure

In v3.0.0+, we leverage MkDocs' existing data structures instead of creating custom models:

Primary Data Object: mkdocs.structure.files.File

# MkDocs File object (extended by plugin)
class File:
    src_path: str              # Source path relative to docs_dir
    abs_src_path: str          # Absolute source path
    url: str                   # URL path for the file
    content_string: str        # File content
    page: Optional[Page]       # Associated Page object

    # Plugin-added attributes (via setattr):
    note_date: datetime        # From frontmatter
    note_title: str            # From frontmatter

Frontmatter Schema

Minimal Required Fields:

---
date: 2025-11-05 12:00:00    # datetime (required)
title: My Note Title         # string (required)
permalink:                   # string (optional)
publish: true                # bool (default: true)
---

Processed by MkDocs: - Uses mkdocs.utils.meta.get_data() for parsing - YAML frontmatter automatically converted to Python types - date becomes datetime object

Graph Data Model

Graph JSON Structure:

{
  "nodes": [
    {
      "id": "notes/python/intro.md",
      "path": "/abs/path/to/notes/python/intro.md",
      "name": "Python Introduction",
      "url": "notes/python/intro/"
    }
  ],
  "edges": [
    {
      "source": "notes/python/intro.md",
      "target": "notes/python/basics.md"
    }
  ]
}

Data Flow Diagram

graph LR
    subgraph "Input"
        NoteFiles[Note Files<br/>.md]
        MkDocsConfig[mkdocs.yml]
    end

    subgraph "Plugin Processing"
        Scanner[scanner.scan_notes]
        MetaValidator[meta.validate_frontmatter]
        GraphBuilder[Graph.__call__]
    end

    subgraph "MkDocs Objects"
        FileList[Files<br/>Collection]
        FileObj[File<br/>+ note_date<br/>+ note_title]
        GraphData[Graph JSON<br/>nodes + edges]
    end

    subgraph "Output"
        IndexPage[Index Page<br/>with Recent Notes]
        SiteOutput[Site Output<br/>+ graph.json]
    end

    NoteFiles --> FileList
    MkDocsConfig --> Scanner

    FileList --> Scanner
    Scanner --> MetaValidator
    MetaValidator --> FileObj

    FileObj --> GraphBuilder
    GraphBuilder --> GraphData

    FileObj --> IndexPage
    GraphData --> SiteOutput

Workflows and Data Flow

Plugin Build-time Workflow (v3.0.0+)

sequenceDiagram
    participant MkDocs
    participant Plugin
    participant Scanner
    participant Meta
    participant Graph

    MkDocs->>Plugin: on_config(config)
    Plugin->>Plugin: Add static resources (D3.js, graph.js/css)
    Plugin-->>MkDocs: config

    MkDocs->>Plugin: on_pre_build(config)
    Plugin->>Graph: new Graph(config)
    Plugin-->>MkDocs: void

    MkDocs->>Plugin: on_files(files, config)
    activate Plugin

    Plugin->>Scanner: scan_notes(files, config)
    activate Scanner

    loop For each file in files
        Scanner->>Scanner: Check if in notes_root
        Scanner->>Meta: validate_frontmatter(file)
        Meta->>Meta: Check publish, date, title
        Meta->>Meta: setattr(file, 'note_date', date)
        Meta->>Meta: setattr(file, 'note_title', title)
        Meta-->>Scanner: valid/invalid
    end

    Scanner-->>Plugin: (valid_notes[], invalid_files[])
    deactivate Scanner

    Plugin->>Plugin: Sort notes by note_date
    Plugin->>Plugin: Remove invalid files from files
    Plugin-->>MkDocs: files
    deactivate Plugin

    MkDocs->>Plugin: on_nav(nav, config, files)
    Plugin->>Plugin: Store files reference
    Plugin-->>MkDocs: nav

    loop For each page
        MkDocs->>Plugin: on_page_markdown(markdown, page)

        alt Is index page in notes_root
            Plugin->>Plugin: insert_recent_note_links()
            Plugin->>Plugin: Replace marker with HTML list
        end

        Plugin-->>MkDocs: markdown
    end

    loop For each page
        MkDocs->>Plugin: on_post_page(output, page)
        Plugin->>Plugin: inject_graph_script(output)
        Plugin-->>MkDocs: output
    end

    MkDocs->>Plugin: on_post_build(config)

    alt Graph enabled
        Plugin->>Graph: __call__(files)
        Graph->>Graph: _create_nodes(files)
        Graph->>Graph: _create_edges(files)
        Plugin->>Plugin: Write graph.json
    end

    Plugin->>Plugin: copy_static_assets()
    Plugin-->>MkDocs: void

CLI Command Workflows (v3.0.0+)

new Command (Note Creation)

sequenceDiagram
    participant User
    participant CLI
    participant NewCmd as NewCommand
    participant Common
    participant FS as FileSystem

    User->>CLI: mkdocs-note new note.md
    CLI->>CLI: Load config
    CLI->>NewCmd: execute(note_path)
    activate NewCmd

    NewCmd->>NewCmd: _validate_before_execution()

    alt File exists
        NewCmd-->>CLI: Error
        CLI-->>User: ❌ File already exists
    end

    NewCmd->>Common: ensure_parent_directory(note_path)
    Common->>FS: mkdir -p parent/

    NewCmd->>NewCmd: _generate_note_basic_meta()
    Note over NewCmd: Generate frontmatter:<br/>date, title, permalink, publish

    NewCmd->>FS: Write note file

    NewCmd->>Common: get_asset_directory(note_path)
    Common-->>NewCmd: asset_dir

    NewCmd->>FS: mkdir -p asset_dir/

    NewCmd-->>CLI: success
    deactivate NewCmd

    CLI-->>User: ✅ Note created<br/>📝 Note: path<br/>📁 Assets: path

clean Command (Orphaned Asset Cleanup)

sequenceDiagram
    participant User
    participant CLI
    participant CleanCmd as CleanCommand
    participant Common
    participant FS

    User->>CLI: mkdocs-note clean [--dry-run] [--yes]
    CLI->>CLI: Load config
    CLI->>CleanCmd: new CleanCommand()

    CLI->>CleanCmd: _scan_note_files(notes_root)
    activate CleanCmd
    CleanCmd->>FS: Scan for .md, .ipynb
    CleanCmd-->>CLI: note_files[]

    CLI->>CleanCmd: _find_orphaned_assets(note_files)

    loop For each note
        CleanCmd->>Common: get_asset_directory(note)
        CleanCmd->>CleanCmd: Add to expected_set
    end

    CleanCmd->>FS: Scan all assets/ directories
    loop For each asset dir
        alt Not in expected_set
            CleanCmd->>CleanCmd: Add to orphaned_list
        end
    end

    CleanCmd-->>CLI: orphaned_dirs[]
    deactivate CleanCmd

    alt No orphans
        CLI-->>User: ✅ No orphaned assets
    end

    CLI-->>User: Show orphaned directories

    alt --dry-run
        CLI-->>User: 💡 Run without --dry-run to remove
    else User confirms (or --yes)
        CLI->>CleanCmd: execute(dry_run=False)
        CleanCmd->>FS: Remove orphaned directories
        CleanCmd->>Common: cleanup_empty_directories()
        CleanCmd-->>CLI: success
        CLI-->>User: ✅ Removed N directories
    else User cancels
        CLI-->>User: ⚠️ Cancelled
    end

move Command (Note Move/Rename)

sequenceDiagram
    participant User
    participant CLI
    participant MoveCmd as MoveCommand
    participant Common
    participant FS

    User->>CLI: mkdocs-note mv source.md dest.md [--yes]
    CLI->>CLI: Load config
    CLI->>MoveCmd: new MoveCommand()

    alt Source doesn't exist
        CLI-->>User: ❌ Source does not exist
    end

    alt User confirms (or --yes)
        CLI->>MoveCmd: execute(source, dest)
        activate MoveCmd

        MoveCmd->>MoveCmd: _validate_before_execution()

        MoveCmd->>Common: ensure_parent_directory(dest)
        MoveCmd->>Common: get_asset_directory(source)
        Common-->>MoveCmd: source_asset_dir
        MoveCmd->>Common: get_asset_directory(dest)
        Common-->>MoveCmd: dest_asset_dir

        MoveCmd->>FS: Move source → dest

        alt Assets exist
            MoveCmd->>FS: Move source_asset_dir → dest_asset_dir
            MoveCmd->>Common: cleanup_empty_directories()
        end

        MoveCmd-->>CLI: success
        deactivate MoveCmd

        CLI-->>User: ✅ Successfully moved<br/>📝 From: source<br/>📝 To: dest<br/>📁 Assets moved
    else User cancels
        CLI-->>User: ⚠️ Cancelled
    end

Design Principles (v3.0.0+)

Simplicity First

Core Philosophy: Minimal complexity, maximum clarity

  • Flat Structure: Core modules at package root, not buried in nested subpackages

  • Direct Dependencies: Minimize abstraction layers

  • Standard Library: Prefer Python/MkDocs built-ins over custom solutions

  • Code Minimalism: ~2,700 lines vs. ~12,000 lines in v2.x

Example:

# v3.0.0: Direct, simple
from mkdocs.utils import meta
frontmatter, body = meta.get_data(content)

# v2.x: Over-abstracted
from mkdocs_note.utils.dataps.frontmatter.handlers import FrontmatterParser
parser = FrontmatterParser()
frontmatter, body = parser.parse(content)

Leverage MkDocs Infrastructure

Principle: Don't reinvent what MkDocs provides

  • Use MkDocs File objects: Extend with setattr() instead of custom wrappers

  • Use MkDocs logging: get_plugin_logger(__name__) instead of custom logger

  • Use MkDocs meta parsing: mkdocs.utils.meta.get_data() for frontmatter

  • Follow MkDocs conventions: Plugin hooks, configuration schema

Benefits: - Better compatibility with MkDocs ecosystem - Less maintenance burden - Familiar API for MkDocs developers

Co-located Resources

Pattern: Assets live next to their notes

docs/notes/python/intro.md
                └─ assets/intro/  (assets for intro.md)

Implementation:

def get_asset_directory(note_path: Path) -> Path:
    return note_path.parent / "assets" / note_path.stem

Advantages:

  • ✅ Easy to understand and manage

  • ✅ Move note → assets move with it (CLI commands handle this)

  • ✅ No complex path calculations

  • ✅ Intuitive for users

Fail Fast, Fail Clear

Principle: Clear error messages, early validation

# Frontmatter validation
if not frontmatter.get("publish", False):
    logger.debug(f"Skipping {f.src_uri} because it is not published")
    return False

if "date" not in frontmatter:
    logger.error(f"Invalid frontmatter for {f.src_uri}: 'date' is required")
    return False

CLI Error Handling:

if not note_path.exists():
    click.echo(f"❌ Error: File does not exist: {note_path}", err=True)
    sys.exit(1)

Testing Strategy

Test Coverage:

  • ✅ Plugin tests: Core MkDocs integration

  • ✅ CLI tests: Command execution, argument parsing

  • ✅ Smoke tests: End-to-end workflows

  • ✅ Config tests: Configuration validation

Testing Principles:

  • Use temporary directories for file operations

  • Test both success and failure paths

  • Clear, descriptive test names

  • Minimal test fixtures


Key Technical Decisions (v3.0.0+)

Why Simplify from v2.x to v3.0.0?

Problem Statement: v2.x was over-engineered for the actual use cases

v2.x Issues:

  • Complexity: 9+ subpackages, 12,000+ lines of code

  • Maintenance Burden: Many abstractions, hard to debug

  • Feature Creep: Template system, validation, initialization - rarely used

  • Learning Curve: New contributors struggled to understand architecture

v3.0.0 Solution:

  • Radical Simplification: Removed 77% of code

  • Focus on Core: Kept only essential features (recent notes, graph, basic CLI)

  • Flat Structure: Easy to navigate and understand

  • Better Integration: Leverage MkDocs infrastructure instead of reimplementing

Result:

  • Faster build times

  • Easier to maintain

  • Clearer purpose

  • Better reliability

Why Keep Co-located Asset Structure?

Decision: Retain co-located pattern from v2.x

docs/notes/python/intro.md
                └─ assets/intro/  (co-located)

Rationale:

  • User-friendly: Easy to understand and manage

  • Portable: Move note → assets move with it

  • Simple: One function, one rule

  • Proven: Worked well in v2.x

Implementation:

# Single source of truth
def get_asset_directory(note_path: Path) -> Path:
    return note_path.parent / "assets" / note_path.stem

Why Use MkDocs' Built-in Frontmatter Parsing?

Decision: Use mkdocs.utils.meta.get_data() instead of custom parser

Rationale:

  • Standard: MkDocs already has YAML frontmatter support

  • Type Conversion: Automatic conversion (dates, booleans)

  • Well-tested: Proven by MkDocs ecosystem

  • Less Code: No need to maintain custom parser

Comparison:

# v2.x: Custom parser (~200 lines)
from mkdocs_note.utils.dataps.frontmatter.handlers import FrontmatterParser
parser = FrontmatterParser()
fm, body = parser.parse_file(path)

# v3.0.0: Built-in (~5 lines)
from mkdocs.utils import meta
with open(path) as f:
    fm, body = meta.get_data(f.read())

Why Remove Template System?

Decision: Remove template system with variable substitution

v2.x Template System:

  • Template files with {date}, {title} placeholders

  • Complex variable replacement logic

  • Template registry and loading mechanism

Why Remove:

  • Low Usage: Most users used default template

  • Complexity: ~500 lines of code for rare feature

  • Maintenance: Breaking changes when frontmatter changed

v3.0.0 Approach:

# Simple, direct frontmatter generation
def _generate_note_basic_meta(self, file_path: Path) -> str:
    return f"""---
date: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
title: {file_path.stem.replace('-', ' ').title()}
permalink: 
publish: true
---
"""

Benefits:

  • Maintainable: 10 lines vs. 500 lines

  • Flexible: Users can edit after creation

Why Keep Network Graph?

Decision: Retain graph visualization despite simplification

Rationale: - ✅ Self-contained: graph.py is independent, ~190 lines

  • Migrated Code: Already ported from mkdocs-network-graph-plugin

  • Low Maintenance: Stable, minimal dependencies

Integration:

  • Uses D3.js for rendering (CDN)

  • Generates graph.json with nodes and edges

  • Injects JavaScript configuration via HTML hook


Migration Guide

Migrating from v2.x to v3.0.0

Breaking Changes

v3.0.0 removes many features from v2.x. Please review the changelog before upgrading.

Step 1: Review Removed Features

No longer available in v3.0.0:

  • ❌ Template system (notes_template config)

  • ❌ Asset management system

  • init and validate CLI commands

  • ❌ Custom frontmatter registry

  • assets_dir configuration option

Still available:

  • ✅ Recent notes display

  • ✅ Network graph visualization

  • ✅ Basic CLI: new, remove, move, clean

  • ✅ Frontmatter metadata (date, title, publish, permalink)

Step 2: Update Configuration

Old (v2.x) config:

plugins:
  - mkdocs-note:
      notes_root: "docs/notes"
      assets_dir: "docs/notes/assets"  # ❌ Removed
      notes_template: "template.md"    # ❌ Removed
      recent_notes_config:
        enabled: true
        insert_num: 10

New (v3.0.0) config:

plugins:
  - mkdocs-note:
      notes_root: "docs/notes"  # ✅ Still supported
      recent_notes_config:      # ✅ Still supported
        enabled: true
        insert_num: 10
      graph_config:             # ✅ Enhanced
        enabled: true
        name: "title"

Step 3: Update Frontmatter (if needed)

v3.0.0 requires these fields:

---
date: 2025-11-05 12:00:00  # Required: datetime
title: My Note              # Required: string
publish: true               # Optional: bool (default: true)
permalink:                  # Optional: string
---

Notes without valid frontmatter will be excluded from builds.

Step 4: Test Your Build

# Clean previous builds
rm -rf site/

# Build with v3.0.0
mkdocs build

# Check for errors
# - Missing frontmatter errors
# - Invalid date/title errors

For Plugin Developers

Module path changes:

# v2.x: Complex paths
from mkdocs_note.utils.dataps.meta import NoteInfo
from mkdocs_note.utils.docsps.handlers import NoteProcessor
from mkdocs_note.utils.dataps.frontmatter.handlers import FrontmatterManager

# v3.0.0: Simplified (or don't import internals)
# Most internal APIs are NOT intended for external use
# Use plugin configuration instead

Recommendation: Don't depend on internal APIs. Use: - Plugin configuration (mkdocs.yml) - CLI commands - Frontmatter metadata


References

External Resources

Design Philosophy References