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.jsmanifest.jsonstyles.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 |