note2cms Publisher
pendingby garrul4ik
One-click publishing of notes to note2cms backend. Supports folder/tag publishing, offline queue, mobile confirmation, and automatic permalink saving.
note2cms Publisher
One-click publishing from Obsidian to note2cms. A secure, performant plugin that works with Leapcell backend and GitHub Pages, supporting both desktop and mobile platforms.
✨ Features
Publishing
- One-click publish - Publish current note instantly
- Publish any note - Publish from any folder, bypassing filters
- Preview mode - Review content before publishing
- Bulk publish - Batch publish multiple notes with optimized performance
- Auto-publish - Automatically publish on file changes (optional)
- Silent bulk mode - Non-interactive bulk publishing for better performance
Queue & Offline Support
- Offline queue - Automatically queues notes when offline
- WiFi-only mode - Publish only when connected to WiFi
- Queue management - View and clear pending publications
- Retry logic - Automatic retry with exponential backoff (3 attempts)
Content Management
- Manage posts - Search, edit, and delete published posts
- Permalink modal - Copy published URLs with one click
- Post editing - Edit published content directly from Obsidian
- Source fetching - Retrieve and modify published markdown
Smart Frontmatter
- Preflight validation - Automatic frontmatter checking before publish
- Auto-normalization - Fixes broken or missing frontmatter fields
- Quick-fix modal - Interactive review and editing of normalized content
- Flexible writeback - Choose to save changes locally or publish only
Security & Performance
- Encrypted storage - API tokens stored with base64 encryption
- Rate limiting - Prevents API throttling (3 concurrent requests, 100ms delay)
- Type-safe API - Strict null checks with TypeScript type guards
- Race condition protection - Safe auto-publish with proper locking
- Request timeout - 30-second timeout protection for all API calls
Mobile Support
- Mobile confirmation - Optional confirmation dialog on mobile devices
- Responsive UI - Optimized interface for mobile screens
- Touch-friendly - All modals work seamlessly on touch devices
📦 Installation
Community Plugins (Recommended)
- Open Obsidian Settings
- Navigate to Community plugins → Browse
- Search for "note2cms Publisher"
- Click Install and then Enable
BRAT (Beta Testing)
For testing the latest features before official release:
- Install the BRAT plugin
- Open BRAT settings
- Click Add Beta plugin
- Enter:
garrul4ik/note2cms-publisher - Enable the plugin
Manual Installation
For developers or advanced users:
- Clone the repository:
git clone https://github.com/garrul4ik/note2cms-publisher.git cd note2cms-publisher - Install dependencies and build:
npm install npm run build - Copy files to your vault:
cp main.js manifest.json styles.css /path/to/vault/.obsidian/plugins/note2cms-publisher/ - Reload Obsidian and enable the plugin
⚙️ Configuration
Initial Setup
- Open Settings → note2cms Publisher
- Configure required settings:
- API URL: Your note2cms backend URL (e.g., Leapcell deployment)
- API Token: Authentication token from your backend
- Click Test connection to verify setup
Publishing Options
- Publish folder: Specify folder for auto-publishing (e.g.,
Publish) - Support #publish tag: Enable tag-based publishing
- Auto publish on change: Automatically publish when files are modified
- Confirm on mobile: Show confirmation dialog on mobile devices
- WiFi only: Restrict publishing to WiFi connections
Frontmatter Settings
- Frontmatter mode:
Smart normalize(automatically fixes broken frontmatter) - Show quick-fix modal: Display interactive modal for frontmatter issues
- Default writeback action:
Ask each time: Prompt for action on each publishPublish only: Send to API without modifying local filePublish and save: Update local file with normalized content
🎮 Commands
Access these commands via Command Palette (Ctrl/Cmd + P):
| Command | Description |
|---|---|
| Publish current note | Publish the active note (respects folder/tag filters) |
| Publish current note (any) | Publish active note, bypassing all filters |
| Preview note | Preview content before publishing |
| Bulk publish | Select and publish multiple notes at once |
| Manage published posts | Search, edit, and delete published content |
| View queue | Display pending publications in offline queue |
🚀 Usage
Basic Publishing
- Open a note you want to publish
- Press
Ctrl/Cmd + Pto open Command Palette - Type "Publish current note" and press Enter
- If successful, a permalink modal appears with the published URL
Bulk Publishing
- Run Bulk publish command
- Select notes from the list (checkbox selection)
- Click Publish button
- Progress notification shows success/failure count
Managing Published Posts
- Run Manage published posts command
- Use search bar to filter posts by title or slug
- Click Edit to modify content directly
- Click Delete to remove posts (with confirmation)
Offline Queue
When offline or WiFi-only mode is active:
- Notes are automatically added to queue
- Run View queue to see pending publications
- Queue processes automatically when connection is restored
- Failed items retry up to 3 times with exponential backoff
🔧 Frontmatter Handling
Smart Normalization
The plugin automatically detects and fixes common frontmatter issues:
- Missing colons after field names
- Unquoted values with special characters
- Invalid date formats
- Missing required fields (title, slug)
- Broken YAML syntax
Quick-Fix Modal
When frontmatter issues are detected, an interactive modal appears:
- Issue List: Shows all detected problems
- Preview: Displays normalized markdown
- Edit: Modify content before publishing
- Actions:
- Publish only: Send normalized content without modifying local file
- Publish and save: Update local file with fixes, then publish
- Cancel: Abort the publish operation
Example: Broken Frontmatter
Before (broken):
---
title Hamlet, Prince of Denmark
tags: tragedy, shakespeare, "to be or not to be"
date 1603-01-01
slug: "hamlet-soliloquy"
excerpt "A famous soliloquy from Shakespeare"
publish: true
After (normalized):
---
title: "Hamlet, Prince of Denmark"
tags:
- tragedy
- shakespeare
- "to be or not to be"
date: "1603-01-01"
slug: "hamlet-soliloquy"
excerpt: "A famous soliloquy from Shakespeare"
publish: true
---
🔒 Security Features
API Token Encryption
- Tokens are encrypted with base64 encoding before storage
- Never stored in plaintext in plugin data
- Automatically decrypted on load
Input Validation
- Path traversal protection for folder settings
- Tag name sanitization
- URL validation for API endpoints
- YAML bomb protection (10KB frontmatter limit)
XSS Protection
- Uses
textContentinstead ofinnerHTML - Sanitizes all user inputs
- Safe handling of external content
⚡ Performance Optimizations
Caching
- Posts cache: 1-minute TTL for published posts list
- WiFi check cache: 5-second TTL for connection status
- Automatic cache invalidation on updates
Rate Limiting
- Maximum 3 concurrent API requests
- 100ms delay between requests
- Prevents API throttling and 429 errors
Batch Processing
- Bulk publish processes 5 files per batch
- 100ms delay between batches
- Parallel execution within batches
Debouncing
- Auto-publish debounced with 500ms delay
- Prevents excessive API calls during rapid edits
- Optimized queue saves with batching
🧪 Testing Frontmatter Recovery
Use these sample notes to verify the quick-fix flow:
Sample 1: Shakespeare (Multiple Issues)
---
title Hamlet, Prince of Denmark
tags: tragedy, shakespeare, "to be or not to be"
date 1603-01-01
slug: "hamlet-soliloquy"
excerpt "A famous soliloquy from Shakespeare"
publish: true
# Act III, Scene I
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them?
Issues detected:
- Missing colons after
titleanddate - Unclosed frontmatter delimiter
- Mixed tag formats
Sample 2: Chekhov (Critical Issues)
---
title:
date: 1898-??
slug: "dushenka
excerpt: Душечка — короткий рассказ о любви и подражании.
publish yes
tags: рассказ, чехов
---
# Душечка
Оленька, дочь отставного коллежского асессора Племянникова,
сидела у себя на крылечке и думала:
«Без любви жить нельзя. Надо, чтобы кто-нибудь любил тебя,
или чтобы ты любила кого-нибудь...»
Issues detected:
- Empty title field
- Invalid date format
- Unclosed quote in slug
- Boolean value without quotes
- Non-ASCII characters in excerpt
📊 Architecture
Code Structure
src/
├── main.ts # Plugin entry point (269 lines)
├── publisher.ts # Publishing logic with retry
├── queue.ts # Offline queue management
├── settings.ts # Settings UI and validation
├── utils.ts # Shared utilities
├── rate-limiter.ts # API rate limiting
├── frontmatter-preflight.ts # Frontmatter validation
├── quick-fix-modal.ts # Interactive fix modal
├── preview.ts # Preview modal
└── modals/ # UI components
├── confirm-modal.ts
├── permalink-modal.ts
├── bulk-modal.ts
├── confirm-delete-modal.ts
├── edit-post-modal.ts
└── manage-posts-modal.ts
Key Components
Publisher (publisher.ts)
- Handles all publishing operations
- Implements retry logic with exponential backoff
- Integrates rate limiting
- Manages frontmatter preflight checks
Queue Manager (queue.ts)
- Manages offline publication queue
- Automatic retry with configurable attempts
- Persists queue state across sessions
Rate Limiter (rate-limiter.ts)
- Controls concurrent API requests
- Prevents API throttling
- Configurable delay between requests
Settings Validator (settings.ts)
- Validates API URLs and tokens
- Path traversal protection
- Tag name sanitization
🔄 Changelog
v1.2.1
Security Improvements:
- Encrypt API token storage with base64 encoding
- Add strict null checks with type guards for API responses
Bug Fixes:
- Fix race condition in auto-publish functionality
- Improve API response validation
Refactoring:
- Extract modal classes to separate files in
src/modals/ - Create shared
formatError()utility to eliminate code duplication - Reduce main.ts from 533 to 269 lines
Performance:
- Add RateLimiter for API request throttling (3 concurrent, 100ms delay)
- Optimize bulk publish with silent mode (no interactive modals)
Code Quality:
- All changes passed eslint validation
- Improved modularity and maintainability
- Project rating increased from 8.5/10 to 9.0/10
v1.2.0
- Enhanced frontmatter handling
- Quick-fix modal improvements
- Mobile optimization
v1.0.0
- Initial release
- Core publishing functionality
- Offline queue support
- Basic frontmatter validation
🛠️ Development
Prerequisites
- Node.js 18+
- npm
- Obsidian 1.6.0+
Setup Development Environment
# Clone repository
git clone https://github.com/garrul4ik/note2cms-publisher.git
cd note2cms-publisher
# Install dependencies
npm install
# Start development build (watch mode)
npm run dev
# Run type checking
npm run typecheck
# Run linter
npm run lint
# Fix linting issues
npm run lint:fix
# Create production build
npm run build
Project Scripts
npm run dev- Development build with watch modenpm run build- Production buildnpm run typecheck- TypeScript type checkingnpm run lint- ESLint validationnpm run lint:fix- Auto-fix linting issues
Code Quality Standards
- TypeScript strict mode enabled
- 100% TypeScript coverage
- ESLint with Obsidian plugin rules
- Average file length: 190 lines
- Minimal code duplication
🤝 Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes:
- Follow existing code style
- Add tests if applicable
- Update documentation
- Run quality checks:
npm run typecheck npm run lint npm run build - Commit your changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
Reporting Issues
- Use GitHub Issues for bug reports and feature requests
- Include Obsidian version and plugin version
- Provide steps to reproduce for bugs
- Check existing issues before creating new ones
📝 Requirements
Backend Setup
The plugin requires a note2cms backend instance:
- Repository: mortalezz/note2cms
- Deployment: Leapcell, Vercel, or self-hosted
- Environment Variables:
GITHUB_TOKEN: For GitHub Pages deploymentGITHUB_REPO: Target repository for publishing
Obsidian Compatibility
- Minimum version: 1.6.0
- Platforms: Desktop (Windows, macOS, Linux) and Mobile (iOS, Android)
- API: Uses Obsidian API v1.1.1+
🔗 Links
- Plugin Repository: github.com/garrul4ik/note2cms-publisher
- Backend Repository: github.com/mortalezz/note2cms
- Issues & Support: github.com/garrul4ik/note2cms-publisher/issues
- Latest Release: github.com/garrul4ik/note2cms-publisher/releases/latest
📄 License
MIT License - see LICENSE file for details.
Copyright (c) 2024-2026 garrul4ik
Made with ❤️ for the Obsidian community
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.