๐Ÿ› ๏ธ Developer Guide

โ† Back to Main Page

Technical documentation for plugin development and customization

๐Ÿ“ Architecture Overview

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      DOCUMENT MANAGER                           โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                                 โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚    Plugin    โ”‚  โ”‚  DocumentView   โ”‚  โ”‚   SettingTab     โ”‚   โ”‚
โ”‚  โ”‚   (main.ts)  โ”‚โ”€โ”€โ”‚ (document-view) โ”‚โ”€โ”€โ”‚   (settings)     โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚         โ”‚                  โ”‚                     โ”‚              โ”‚
โ”‚         โ–ผ                  โ–ผ                     โ–ผ              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚                     DATA LAYER                          โ”‚   โ”‚
โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚   โ”‚
โ”‚  โ”‚  โ”‚  Models   โ”‚  โ”‚ Thumbnails โ”‚  โ”‚  Document Index   โ”‚  โ”‚   โ”‚
โ”‚  โ”‚  โ”‚ (models)  โ”‚  โ”‚(thumbnails)โ”‚  โ”‚   (in-memory)     โ”‚  โ”‚   โ”‚
โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚         โ”‚                                                       โ”‚
โ”‚         โ–ผ                                                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”‚
โ”‚  โ”‚                   OBSIDIAN VAULT                        โ”‚   โ”‚
โ”‚  โ”‚  Markdown (.md) | PDF (.pdf) | EPUB (.epub) | Images    โ”‚   โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚
โ”‚                                                                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ—‚๏ธ File Structure

document-manager/ โ”‚ โ”œโ”€โ”€ main.ts # Plugin entry point โ”‚ โ”œโ”€โ”€ DocumentManagerPlugin # Main plugin class โ”‚ โ”œโ”€โ”€ onload() # Plugin initialization โ”‚ โ”œโ”€โ”€ activateView() # View activation โ”‚ โ””โ”€โ”€ indexDocuments() # Document scanning โ”‚ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ document-view.ts # Main view component โ”‚ โ”‚ โ”œโ”€โ”€ DocumentManagerView (ItemView) โ”‚ โ”‚ โ”œโ”€โ”€ buildSidebar() # Filter sidebar โ”‚ โ”‚ โ”œโ”€โ”€ buildToolbar() # View controls โ”‚ โ”‚ โ””โ”€โ”€ renderDocuments() # Document rendering โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ models.ts # Data models & utilities โ”‚ โ”œโ”€โ”€ settings.ts # Settings tab โ”‚ โ””โ”€โ”€ thumbnails.ts # Thumbnail generation โ”‚ โ”œโ”€โ”€ styles.css # All CSS styles โ”œโ”€โ”€ manifest.json # Plugin metadata โ”œโ”€โ”€ package.json # Dependencies โ”œโ”€โ”€ tsconfig.json # TypeScript config โ””โ”€โ”€ esbuild.config.mjs # Build configuration

๐Ÿ”ง Development Setup

Prerequisites

# Required
$ node --version # v16.0.0 or higher
$ npm --version # v7.0.0 or higher

Initial Setup

# Navigate to plugin folder
$ cd /path/to/vault/.obsidian/plugins/document-manager
# Install dependencies
$ npm install
# Start development mode
$ npm run dev

Build Commands

Command Description
npm run dev Development with watch mode
npm run build Production build
npx tsc --noEmit Type checking only

๐Ÿ“Š Data Models

Document Interface

TypeScript Document
interface Document {
    id: string;              // File path as unique ID
    file: TFile;             // Obsidian file reference
    title: string;           // Display title
    type: DocumentType;      // 'markdown' | 'pdf' | 'epub' | 'image'
    path: string;            // Full vault path
    folder: string;          // Parent folder
    
    // Metadata from frontmatter
    cover?: string;          // Cover image path
    category?: string;       // Category property
    tags: string[];          // Tags array
    author?: string;         // Author name
    description?: string;    // Brief description
    status?: string;         // Workflow status
    rating?: number;         // 1-5 star rating
    
    // Timestamps
    dateCreated: number;
    dateModified: number;
    
    // Computed properties
    thumbnail?: string;
    excerpt?: string;
    wordCount?: number;
    size: number;
}

Type Definitions

TypeScript Types
type DocumentType = 'markdown' | 'pdf' | 'epub' | 'image';

type SortOption = 'title' | 'dateCreated' | 'dateModified' | 'type' | 'category' | 'rating';

type ViewMode = 'grid' | 'list' | 'table';

FilterOptions Interface

TypeScript FilterOptions
interface FilterOptions {
    type?: DocumentType | 'all';
    category?: string;
    tags?: string[];
    status?: string;
    folder?: string;
    search?: string;
    rating?: number;
}

๐Ÿ”Œ Plugin Lifecycle

Initialization (onload)

TypeScript Plugin onload()
async onload(): Promise<void> {
    // 1. Load settings
    await this.loadSettings();
    
    // 2. Initialize thumbnail generator
    this.thumbnailGenerator = new ThumbnailGenerator(this.app, this);
    
    // 3. Register view
    this.registerView(
        DOCUMENT_VIEW_TYPE,
        (leaf) => new DocumentManagerView(leaf, this)
    );
    
    // 4. Add ribbon icon
    this.addRibbonIcon('library', 'Document Manager', () => {
        this.activateView();
    });
    
    // 5. Add commands
    this.addCommand({
        id: 'open-document-manager',
        name: 'Open Document Manager',
        callback: () => this.activateView()
    });
    
    // 6. Add settings tab
    this.addSettingTab(new DocumentManagerSettingTab(this.app, this));
}

Document Indexing

TypeScript indexDocuments()
async indexDocuments(): Promise<Document[]> {
    const files = this.app.vault.getFiles();
    const documents: Document[] = [];

    for (const file of files) {
        // Check if file should be included
        if (!shouldIncludeFile(file, this.settings)) {
            continue;
        }

        // Check file type
        const docType = getDocumentType(file);
        if (!docType) continue;

        // Parse document metadata
        const doc = await parseDocument(file, this.app, this.settings);
        documents.push(doc);
    }

    this.documents = documents;
    return documents;
}

๐Ÿ–ผ๏ธ View Component

DocumentManagerView Structure

TypeScript DocumentManagerView
class DocumentManagerView extends ItemView {
    plugin: DocumentManagerPlugin;
    private documents: Document[] = [];
    private filteredDocuments: Document[] = [];
    private filters: FilterOptions = {};
    private viewMode: ViewMode = 'grid';

    async onOpen(): Promise<void> {
        this.mainContainer = this.contentEl.createDiv({ cls: 'dm-container' });
        
        // Sidebar with filters
        this.sidebarEl = this.mainContainer.createDiv({ cls: 'dm-sidebar' });
        this.buildSidebar();

        // Main content area
        this.mainContentEl = this.mainContainer.createDiv({ cls: 'dm-main' });
        
        // Toolbar
        this.toolbarEl = this.mainContentEl.createDiv({ cls: 'dm-toolbar' });
        this.buildToolbar();

        // Document grid
        this.documentGridEl = this.mainContentEl.createDiv({ cls: 'dm-documents' });

        // Load documents
        await this.loadDocuments();
    }
}

๐Ÿ–ผ๏ธ Thumbnail Generator

TypeScript ThumbnailGenerator
class ThumbnailGenerator {
    private cache: Map<string, string> = new Map();

    async getThumbnail(doc: Document): Promise<string | null> {
        // 1. Check for custom cover in frontmatter
        if (doc.cover) {
            const coverPath = this.resolveCoverPath(doc.cover, doc.file);
            const coverFile = this.app.vault.getAbstractFileByPath(coverPath);
            if (coverFile instanceof TFile) {
                return this.app.vault.getResourcePath(coverFile);
            }
        }

        // 2. Check cache
        if (this.cache.has(doc.id)) {
            return this.cache.get(doc.id) || null;
        }

        // 3. Generate based on type
        switch (doc.type) {
            case 'markdown':
                return this.generateMarkdownThumbnail(doc);
            case 'image':
                return this.app.vault.getResourcePath(doc.file);
            default:
                return this.getPlaceholder(doc.type);
        }
    }
}

๐ŸŽจ CSS Architecture

Key CSS Classes

Class Description
.dm-container Main flex container
.dm-sidebar Filter sidebar
.dm-main Main content area
.dm-toolbar View controls toolbar
.dm-documents Document grid/list container
.dm-document-card Individual document card
.dm-tag Tag badge

BEM-like Naming

CSS Naming Pattern
/* Block */
.dm-container { }
.dm-sidebar { }

/* Element */
.dm-sidebar-section { }
.dm-toolbar-group { }

/* Modifier */
.dm-sidebar.collapsed { }
.dm-view-btn.active { }

๐Ÿงช Testing

Manual Testing Checklist

Plugin loads without errors
All view modes render correctly (Grid/List/Table)
Filtering works for all filter types
Sorting works in both directions
Thumbnails generate for markdown files
Custom covers load from frontmatter
Context menu actions work
Settings persist across reload
File watchers update view on changes
Performance acceptable with large vaults

๐Ÿš€ Deployment

Pre-release Checklist

TypeScript compiles without errors
No console errors in production
manifest.json version updated
README.md accurate
Tested on Windows/Mac/Linux

Build for Release

$ rm -rf node_modules
$ npm install
$ npm run build

๐Ÿ“ฆ Files to Distribute

  • main.js
  • manifest.json
  • styles.css

๐Ÿ“ API Reference

Plugin Commands

Command ID Description
open-document-manager Open the document manager view
reindex-documents Force reindex all documents
clear-thumbnail-cache Clear cached thumbnails

Utility Functions

Function Description
getDocumentType(file) Get document type from file extension
parseDocument(file, app, settings) Parse document metadata from file
filterDocuments(docs, filters) Filter documents by criteria
sortDocuments(docs, sortBy, desc) Sort documents by option
getAllTags(docs) Get all unique tags from documents
getAllCategories(docs) Get all unique categories

๐Ÿ“š Resources

Obsidian API

TypeScript

CSS