Note2cms Publisher
One-click publishing from Obsidian to note2cms. Works with Leapcell backend and GitHub Pages, supports desktop and mobile.
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
How to Install
- Download the template file from GitHub
- Move it anywhere in your vault
- Open it in Obsidian — done!
Stats
Stars
4
Forks
0
License
MIT
Last updated 19d ago