note2cms Publisher

pending

by garrul4ik

One-click publishing of notes to note2cms backend. Supports folder/tag publishing, offline queue, mobile confirmation, and automatic permalink saving.

4 starsUpdated 11d agoMITDiscovered via Obsidian Unofficial Plugins
View on GitHub

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)

  1. Open Obsidian Settings
  2. Navigate to Community pluginsBrowse
  3. Search for "note2cms Publisher"
  4. Click Install and then Enable

BRAT (Beta Testing)

For testing the latest features before official release:

  1. Install the BRAT plugin
  2. Open BRAT settings
  3. Click Add Beta plugin
  4. Enter: garrul4ik/note2cms-publisher
  5. Enable the plugin

Manual Installation

For developers or advanced users:

  1. Clone the repository:
    git clone https://github.com/garrul4ik/note2cms-publisher.git
    cd note2cms-publisher
    
  2. Install dependencies and build:
    npm install
    npm run build
    
  3. Copy files to your vault:
    cp main.js manifest.json styles.css /path/to/vault/.obsidian/plugins/note2cms-publisher/
    
  4. Reload Obsidian and enable the plugin

⚙️ Configuration

Initial Setup

  1. Open Settingsnote2cms Publisher
  2. Configure required settings:
    • API URL: Your note2cms backend URL (e.g., Leapcell deployment)
    • API Token: Authentication token from your backend
  3. 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 publish
    • Publish only: Send to API without modifying local file
    • Publish and save: Update local file with normalized content

🎮 Commands

Access these commands via Command Palette (Ctrl/Cmd + P):

CommandDescription
Publish current notePublish the active note (respects folder/tag filters)
Publish current note (any)Publish active note, bypassing all filters
Preview notePreview content before publishing
Bulk publishSelect and publish multiple notes at once
Manage published postsSearch, edit, and delete published content
View queueDisplay pending publications in offline queue

🚀 Usage

Basic Publishing

  1. Open a note you want to publish
  2. Press Ctrl/Cmd + P to open Command Palette
  3. Type "Publish current note" and press Enter
  4. If successful, a permalink modal appears with the published URL

Bulk Publishing

  1. Run Bulk publish command
  2. Select notes from the list (checkbox selection)
  3. Click Publish button
  4. Progress notification shows success/failure count

Managing Published Posts

  1. Run Manage published posts command
  2. Use search bar to filter posts by title or slug
  3. Click Edit to modify content directly
  4. Click Delete to remove posts (with confirmation)

Offline Queue

When offline or WiFi-only mode is active:

  1. Notes are automatically added to queue
  2. Run View queue to see pending publications
  3. Queue processes automatically when connection is restored
  4. 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:

  1. Issue List: Shows all detected problems
  2. Preview: Displays normalized markdown
  3. Edit: Modify content before publishing
  4. 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 textContent instead of innerHTML
  • 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 title and date
  • 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 mode
  • npm run build - Production build
  • npm run typecheck - TypeScript type checking
  • npm run lint - ESLint validation
  • npm 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:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes:
    • Follow existing code style
    • Add tests if applicable
    • Update documentation
  4. Run quality checks:
    npm run typecheck
    npm run lint
    npm run build
    
  5. Commit your changes: git commit -m 'Add amazing feature'
  6. Push to branch: git push origin feature/amazing-feature
  7. 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 deployment
    • GITHUB_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

📄 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.