spark-ai-boy68 downloadsPublish and update notes as WordPress posts with categories, tags, featured images, scheduling, previews, and multi-site profiles. 中文 / English.
中文 · English
Publish Obsidian notes to WordPress with post creation/updating, categories and tags, featured images, inline media uploads, scheduling, multiple sites, previews, conflict protection, and publish history.
Unofficial project. Not affiliated with Obsidian, WordPress, or Automattic.
| Area | Capability |
|---|---|
| Publishing | Create a post from the current note; automatically update the linked post from frontmatter |
| Statuses | Draft, publish, pending review, private, and scheduled (future) |
| Content | Obsidian Markdown rendered to HTML, including code, tables, task lists, footnotes, and callouts |
| Titles | Use the first H1 as the title and optionally remove the duplicate H1 from the body |
| Categories | Full category tree, search, multi-select, and create a category from the publish dialog |
| Tags | Comma-separated input; existing tags are reused and missing tags are created |
| Featured image | Pick from the vault, enter a URL, use the first content image, or auto-use the first uploaded image |
| Inline media | Upload vault images to the media library and rewrite links; optionally mirror remote images; media cache avoids duplicates |
| Post fields | Slug, excerpt, format, comments, pingbacks, sticky, password protection, and remove an existing password |
| Scheduling | Date/time picker interpreted in the WordPress site timezone |
| Preview | Approximate in-app preview of the title, excerpt, and rendered body |
| Multiple sites | Unlimited profiles with per-site credentials, defaults, categories, and tags |
| Conflict protection | Detects remote edits and requires explicit confirmation before overwriting |
| Workflow | Ribbon, command palette, file context menu, quick publish, status bar, and history |
| Languages | Complete Chinese and English UI, optionally following Obsidian |
| Mobile | Uses Obsidian requestUrl; works on desktop and mobile |
WP_ENVIRONMENT_TYPE=local.publish_posts, edit_posts, upload_files, and manage_categories (for creating terms).This plugin uses the standard WordPress REST API and does not require a companion WordPress plugin. Some security plugins, WAFs, or reverse proxies block
/wp-json/or theAuthorizationheader; allow-list them if needed.
Download main.js, manifest.json, and styles.css from Releases.
Create this folder in your vault:
<your-vault>/.obsidian/plugins/wordpress-publisher-pro/
Copy all three files into the folder.
Restart Obsidian, open Settings → Community plugins, disable Restricted mode, and enable WordPress Publisher.
spark-ai-boy/obsidian-wordpress-publisher.Official Obsidian community plugin listing requires a separate review. The repository follows the standard plugin layout and can be installed manually or with BRAT today.
Obsidian and select Add New Application Password.abcd EFGH 1234 ijkl MNOP 6789). It is shown only once.Never use your main account password. An application password can be revoked independently.
Open this URL in a browser:
https://your-site.example/wp-json/wp/v2/
A JSON response means the API is reachable. A 404, 403, login page, or HTML response means a permalink, security plugin, firewall, or server configuration issue must be fixed first.
Use the site root, without /wp-json:
✅ https://example.com
✅ https://example.com/blog
❌ https://example.com/wp-json/wp/v2
Keep the subdirectory when WordPress is installed in one.
Open Settings → WordPress Publisher.
Choose Auto (follow Obsidian), 中文, or English. Interface text updates immediately; restart Obsidian to refresh command names in the command palette.
| Field | Meaning |
|---|---|
| Display name | A label such as “My Blog” |
| Site URL | WordPress root, optionally including a subdirectory |
| Username | WordPress login name, not the email address |
| Application password | The generated password; spaces are allowed |
| Default status | Default for new posts |
| Default format | WordPress post format |
| Default categories | Per-site defaults, multi-select |
| Default tags | Per-site defaults, comma-separated |
Test connection validates the credentials and loads categories. You can manage multiple sites from the settings page.
The settings page configures these for the active site:
| Setting | Default | Description |
|---|---|---|
| Use first H1 as title | On | Pre-fill the title from a leading H1 |
| Remove duplicate H1 | On | Remove the H1 from the body when it matches the final title |
| Use note tags | On | Pre-fill tags from YAML/inline tags when no WordPress tags are stored |
| Upload local images | On | Upload vault images and rewrite their links |
| Upload remote images | Off | Download and upload http(s) images; off by default to avoid surprises |
| Auto featured image | Off | Use the first uploaded content image when none is selected |
| Wiki links | Text | Optionally link to already-published posts |
On success the plugin writes frontmatter such as:
wordpress_id: 123
wordpress_url: https://example.com/my-post
wordpress_site: https://example.com
wordpress_status: publish
wordpress_last_sync: 2026-10-31T14:00:00.000Z
wordpress_remote_modified: 2026-10-31T22:00:00
The next time you publish that note, the button becomes Update post.
Publish again. The plugin locates the post by wordpress_id + wordpress_site. If the WordPress post changed after the note's last sync, a conflict warning appears and you must confirm the overwrite.
When the note has no explicit slug or excerpt, updates preserve the existing WordPress slug and excerpt so permalinks and custom summaries are not changed accidentally. You can still edit or clear the excerpt in the publish dialog.
Run Quick publish current note (defaults) from the command palette:
Use the Preview tab in the publish dialog, or the command Preview current note for WordPress. The preview is approximate; the WordPress theme controls the final appearance. Local images are displayed from Obsidian and are uploaded only when you publish.
The command Show WordPress publish history lists created/updated posts with site, post ID, status, and note path. You can open the post or note, remove an entry, or clear the list. History is local only and does not affect WordPress or note frontmatter.
When enabled, the status bar shows WordPress: Not published, Draft, Published, Pending review, Private, or Scheduled. Click it to open the publish dialog.
All keys are optional and user-editable. Avoid editing sync timestamps unless you intentionally want to reset conflict detection.
| Key | Type | Purpose |
|---|---|---|
wordpress_id |
number | Post ID; presence means update instead of create |
wordpress_site |
string | Site root URL used to match a configured profile |
wordpress_url |
string | Published post URL |
wordpress_status |
string | draft, publish, pending, private, or future |
wordpress_last_sync |
ISO timestamp | Last successful sync |
wordpress_remote_modified |
WordPress timestamp | Remote modified value at last sync, used for conflict detection |
wordpress_categories |
number[] | Category IDs |
wordpress_tags |
string[] | Tag names |
wordpress_featured_media |
number | Featured media ID |
wordpress_featured_image |
string | Featured image source path or URL |
wordpress_slug |
string | Actual WordPress slug |
wordpress_format |
string | WordPress post format |
| Key | Purpose |
|---|---|
title / wordpress_title |
Title when there is no H1 |
excerpt / wordpress_excerpt / description |
Excerpt |
slug / wordpress_slug |
Slug; wordpress_slug wins |
cover / image / featured_image / featured |
Featured image |
tags / tag |
Pre-fill WordPress tags |
Delete these keys from the copy:
wordpress_id:
wordpress_url:
wordpress_last_sync:
wordpress_remote_modified:
Keep wordpress_site to default the copy to the same site.
Delete wordpress_id and wordpress_site. The remote post is not deleted.
Publishing uses Obsidian's own Markdown renderer so the HTML stays close to what you see in Obsidian.
![[image.png]], , remote URLs[[Note]], [[Note|alias]], [[Note#heading]][text](Note.md)%%...%% are removed[[Note|alias]] → alias.wordpress_url in frontmatter, generate a link; otherwise fall back to display text.Non-image note embeds (![[Note]]) cannot be embedded in WordPress and degrade to text to avoid app:// dead links.
app:// links.<img src="..."> tags are not uploaded automatically; use Markdown or wiki image syntax.These depend on Obsidian plugin runtimes and may not work as plain HTML:
Use the preview before publishing.
wordpress_site is preferred over the active site.wordpress_id before publishing.wordpress_site in linked notes; otherwise the note is treated as belonging to a different site..obsidian/plugins/wordpress-publisher-pro/data.json.data.json.<script>, <style>, <iframe>, inline event handlers, and javascript: links.See SECURITY.md for reporting vulnerabilities.
Authorization header.https://your-site/wp-json/wp/v2/ to verify./wp-json/ blocked by a WAF, CDN, or security plugin?publish_posts, upload_files, and manage_categories?upload_files.filename*.<img> tags are not uploaded; use Markdown/wiki syntax.wordpress_remote_modified to fall back to timestamp comparison, or delete wordpress_last_sync to reset.wordpress_remote_modified when the computer and site use different timezones..obsidian/plugins/wordpress-publisher-pro/.git clone https://github.com/spark-ai-boy/obsidian-wordpress-publisher.git
cd obsidian-wordpress-publisher
npm ci
npm run dev
npm run dev watches the source and writes main.js, but does not copy it to a vault. Link the repository into a test vault:
ln -s "$PWD" "/path/to/your/vault/.obsidian/plugins/wordpress-publisher-pro"
Windows:
mklink /J "C:\path\to\vault\.obsidian\plugins\wordpress-publisher" "C:\path\to\repo"
Reload the plugin in Obsidian after building.
npm run dev # watch and bundle with inline sourcemap
npm run typecheck # strict TypeScript check
npm run test # Vitest unit tests
npm run build # typecheck + production bundle
npm run check # typecheck + tests + build
src/
main.ts Plugin entry, commands, status bar, events
types.ts Shared types
constants.ts Defaults, frontmatter keys, statuses, formats
i18n/ Chinese/English dictionaries and detection
ui/ Publish dialog, site/settings UI, history, image picker
utils/ URL, date, Markdown, frontmatter, path, error helpers
wordpress/
client.ts WordPress REST client
publisher.ts Publish orchestration, conflicts, frontmatter
media.ts Image parsing, uploads, media cache
notes.ts Note reading and default options
renderer.ts Obsidian Markdown → HTML
links.ts Wiki/Markdown internal link conversion
tests/ Vitest tests and Obsidian runtime stub
requestUrl (mobile-compatible, no CORS issues).src/i18n/en.ts and implement every TranslationKey.LanguageSetting / ResolvedLanguage in src/types.ts.src/i18n/index.ts.npm version patch # or minor / major
git push --follow-tags
npm version runs scripts/version-bump.mjs, which keeps package.json, manifest.json, and versions.json in sync. The tag workflow verifies versions, builds, and creates a GitHub release with main.js, manifest.json, and styles.css.
Issues and pull requests are welcome. Please read:
Never paste application passwords, data.json contents, or credential-bearing headers into an issue.
MIT © 2026 spark-ai-boy
WordPress is a trademark of the WordPress Foundation. Obsidian is a trademark of Dynalist Inc. This project is not affiliated with either.