A TypeScript CLI tool and library for publishing markdown files to WordPress, with automatic image upload and management.
π§ This project is in active development - Currently completing Step 2/13: Core library implementation
# Install (coming soon to npm)
npm install -g @md2wp/cli
# Initialize configuration
md2wp init
# Publish a markdown file to WordPress
md2wp publish my-post.md- @md2wp/core - Core library for WordPress API integration and markdown processing
- @md2wp/cli - Command-line interface for publishing markdown to WordPress
- @md2wp/vscode - VS Code extension (scaffold only for v1)
- docs - VitePress documentation site
This is a monorepo managed with pnpm and Turborepo.
- Node.js >= 18.0.0
- pnpm >= 8.0.0
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Lint and format
pnpm lint
pnpm format
# Run documentation site locally
pnpm docs:devpnpm build- Build all packagespnpm dev- Run all packages in watch modepnpm test- Run tests in all packagespnpm lint- Lint all packagespnpm lint:fix- Fix lint issuespnpm format- Format code with Prettierpnpm typecheck- Type check all packagespnpm clean- Clean build artifactspnpm changeset- Create a changeset for version management
- π Publish markdown files directly to WordPress
- π¨ Converts markdown to Gutenberg blocks (not plain HTML!)
- πΌοΈ Automatic image upload and URL replacement
- π Intelligent image caching (avoid duplicate uploads)
- βοΈ Flexible configuration via
.md2wprc.json - π― Support for GFM: paragraphs, headings, lists, images, links, code blocks
- π Secure authentication using WordPress Application Passwords
- π§ͺ Dry-run mode to preview changes (coming soon)
- π¦ Published as both CLI tool and library
md2wp uses WordPress Application Passwords for secure authentication. These are special passwords just for apps (not your main WordPress password).
-
Initialize md2wp in your project:
md2wp init
This creates two files:
.md2wprc.json- WordPress site URL and username.env- Your Application Password (keep this secret!)
-
Create an Application Password in WordPress:
- Log into your WordPress admin
- Go to Users β Profile (or
/wp-admin/profile.php) - Scroll to "Application Passwords" section
- Enter
md2wpas the application name - Click "Add New Application Password"
- Copy the generated password (it looks like:
xxxx xxxx xxxx xxxx)
-
Add password to
.env:# .env MD2WP_PASSWORD=xxxx xxxx xxxx xxxx -
Update
.md2wprc.jsonwith your site details:{ "wordpress": { "siteUrl": "https://yoursite.com", "username": "your-username" }, "posts": { "defaultStatus": "draft" } } -
β οΈ Important: Add.envto your.gitignore:.env
You can also set credentials via environment variables:
export MD2WP_PASSWORD="xxxx xxxx xxxx xxxx"
export MD2WP_SITE_URL="https://yoursite.com"
export MD2WP_USERNAME="your-username"Environment variables take precedence over config file settings.
Create a markdown file with frontmatter:
---
title: 'My First Post'
status: draft
tags:
- tutorial
- markdown
categories:
- development
---
# Hello WordPress!
This is my **first post** published with md2wp.

- Markdown is converted to Gutenberg blocks
- Images are automatically uploaded
- Links work perfectly
Check out my [website](https://example.com)!Publish it:
md2wp publish my-first-post.md---
title: 'Post Title' # Required
slug: custom-url-slug # Optional
status: draft | publish # Optional (default: draft)
featured_image: ./images/hero.jpg # Optional
tags: # Optional
- tag1
- tag2
categories: # Optional
- category1
excerpt: 'Short description' # Optional
date: 2024-01-15 # Optional
---# Initialize config files
md2wp init
# Publish a post
md2wp publish post.md
# Publish as draft (override frontmatter)
md2wp publish post.md --draft
# Dry run (preview without publishing)
md2wp publish post.md --dry-run
# Validate frontmatter and config
md2wp validate post.md
# Show current config
md2wp config- Parse - Reads your markdown file and extracts frontmatter
- Process Images - Finds local images, uploads to WordPress Media Library
- Transform - Converts markdown to Gutenberg block HTML format
- Publish - Sends to WordPress REST API
- Cache - Remembers uploaded images (avoids duplicates)
md2wp converts your markdown to proper Gutenberg blocks:
# Headingβ
<!-- wp:heading {"level":1} -->
<h1 class="wp-block-heading">Heading</h1>
<!-- /wp:heading -->β
<!-- wp:image {"id":123,"sizeSlug":"large"} -->
<figure class="wp-block-image size-large">
<img
src="https://site.com/wp-content/uploads/image.jpg"
alt="Alt text"
class="wp-image-123"
/>
</figure>
<!-- /wp:image -->This means:
- β WordPress knows these are "real" images (not just HTML)
- β Automatic responsive srcsets
- β Native Gutenberg editing experience
- β Future-proof with WordPress
See ROADMAP.md for planned features and improvements.
MIT Β© Nicholas Hart