0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
JPPINTO
  • Home
  • Certifications
  • About
  • Contact
  • Gallery
  • Current Setup
Contact

Search

June 23, 2026 / Deployment, WordPress, WP-CLI

Move WordPress Articles from Dev to Production with WP-CLI

Tags: content deployment, dev to production, powershell, wordpress, wordpress posts, wp-cli

When WordPress articles are written outside the block editor, a repeatable sync process keeps the source files, release notes, and published posts aligned. This workflow stores article drafts in a .posts folder, runs a WP-CLI helper against the WordPress install, and then reviews the results in wp-admin before the articles are considered ready.

What It Does

  • Keeps article source files in a versioned .posts folder.
  • Uses WP-CLI to create missing WordPress posts from local Markdown drafts.
  • Supports an overwrite mode for intentional content refreshes.
  • Preserves the original WordPress publish date when an existing post is overwritten.
  • Keeps categories, tags, title, slug, and post content tied to the source article metadata.
  • Leaves final editorial review in wp-admin, where images, formatting, previews, and publish status are easiest to inspect.

Folder Layout

A simple source repository can keep the content and helper script side by side:

C:\DevOps\DEV-Site
|-- .posts
|   `-- 2026.06.23
|       |-- example-article.md
|       `-- assets
|           `-- example-screenshot.png
|-- .codex
|   `-- scripts
|       `-- sync-posts-from-posts.php
`-- .releases
    `-- 2026-06-23-sync-posts-via-wp-admin.md

The source repository does not have to be the WordPress install. The important part is that wp --path points to the actual WordPress folder.

Create the Source Folder Structure

If the articles already exist in WordPress because they were written by hand, start by creating a source folder that can hold future article versions. This does not change WordPress by itself. It gives you a place to store a clean copy of each article, its metadata, release notes, and any pictures used by the post.

From the source repository root, create the folders:

Set-Location C:\DevOps\DEV-Site
New-Item -ItemType Directory -Force -Path .posts\2026.06.23
New-Item -ItemType Directory -Force -Path .posts\2026.06.23\assets
New-Item -ItemType Directory -Force -Path .codex\scripts
New-Item -ItemType Directory -Force -Path .releases

Save the sync helper as:

.codex\scripts\sync-posts-from-posts.php

Save the export helper as:

.codex\scripts\export-post-to-posts.php

Create a release note for the batch:

New-Item -ItemType File -Force -Path .releases\2026-06-23-sync-posts-via-wp-admin.md

When converting an existing hand-written WordPress article into a source file, use the export helper. It reads the post from WordPress, pulls the title, slug, publish date, categories, tags, and body content, then writes a Markdown file under .posts.

Export a Post Without Pictures

Start with a post that was already created visually in WordPress. For example, an editor writes the article in wp-admin, sets the title, categories, tags, and slug, then publishes it or saves it as a draft.

Find the post ID in wp-admin, or use the post slug. Then export it from WordPress into .posts:

Set-Location C:\DevOps\DEV-Site
wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\export-post-to-posts.php slug=example-wordpress-article-without-pictures

You can also export by ID:

wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\export-post-to-posts.php post=123

The export creates a Markdown file based on the post date and slug:

.posts\2026.06.23\example-wordpress-article-without-pictures.md

The generated source file looks like this:

---
title: "Example WordPress Article Without Pictures"
slug: "example-wordpress-article-without-pictures"
date: "2026-06-23"
status: "draft"
categories:
  - WordPress
  - Deployment
tags:
  - wordpress
  - wp-cli
  - content sync
---

# Example WordPress Article Without Pictures

This article was originally written visually in WordPress. The exported source copy now lives in the `.posts` folder so it can be reviewed, versioned, and synced again later.

## What It Does

- Keeps the post title, slug, publish date, categories, and tags from WordPress.
- Converts normal headings, paragraphs, lists, links, and code blocks into Markdown.
- Uses the same slug as the existing WordPress post so targeted overwrite mode updates the right article later.

## Main Article Section

This is content that came from the WordPress editor.

If the Markdown file already exists, the exporter stops by default. Use overwrite=1 only when you intentionally want to replace the source file:

wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\export-post-to-posts.php slug=example-wordpress-article-without-pictures overwrite=1

The default sync skips the existing WordPress post because the slug already exists. Use targeted overwrite only when you intentionally want the exported and edited source copy to replace the current WordPress content.

Export a Post with Pictures

For an article with pictures, the starting point is still the visual WordPress editor. Add the images in the post, set meaningful alt text in the Media Library, and save the post.

Then export the post:

Set-Location C:\DevOps\DEV-Site
wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\export-post-to-posts.php slug=example-wordpress-article-with-pictures

The exporter creates the Markdown file and copies local Media Library files into the dated assets folder when it can find them:

.posts\2026.06.23\example-wordpress-article-with-pictures.md
.posts\2026.06.23\assets\example-wordpress-article-with-pictures-example-screenshot.png

The Markdown keeps the public WordPress Media Library URL in the article body so the image still loads after the source is synced back into WordPress:

---
title: "Example WordPress Article with Pictures"
slug: "example-wordpress-article-with-pictures"
date: "2026-06-23"
status: "draft"
categories:
  - WordPress
  - Media Library
tags:
  - wordpress
  - images
  - media library
---

# Example WordPress Article with Pictures

This article was originally written visually in WordPress and included screenshots. The Markdown source keeps the article text and public image reference.

## What It Does

- Keeps the article text in `.posts`.
- Copies a source copy of the screenshot into `.posts\2026.06.23\assets` when the file exists locally.
- Keeps the WordPress Media Library URL in the Markdown image line.

## Screenshot

![Example screenshot](https://example.com/wp-content/uploads/2026/06/example-screenshot.png)

If you need to import a new picture before writing the visual post, import it first:

wp --path="C:\inetpub\sites\example.com" media import .\.posts\2026.06.23\assets\example-screenshot.png --title="Example screenshot"

Do not leave public article images pointing at .posts\2026.06.23\assets\example-screenshot.png, because that path exists only in the source repository and will not load for visitors.

Sync New Posts

From the source repository root, run the helper with an absolute WordPress install path:

Set-Location C:\DevOps\DEV-Site
wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\sync-posts-from-posts.php

This creates posts that do not already exist. Existing posts with matching slugs are skipped by default so a normal sync does not overwrite live content unexpectedly.

If the PowerShell prompt is inside .releases, use a parent-relative helper path and keep the same absolute WordPress path:

Set-Location C:\DevOps\DEV-Site\.releases
wp --path="C:\inetpub\sites\example.com" eval-file ..\.codex\scripts\sync-posts-from-posts.php

Overwrite Existing Posts

Use overwrite mode when a source article needs to replace the current WordPress content:

$env:JP_SYNC_OVERWRITE='1'
wp --path="C:\inetpub\sites\example.com" eval-file .\.codex\scripts\sync-posts-from-posts.php
Remove-Item Env:\JP_SYNC_OVERWRITE

Overwrite mode should update the title, slug, content, categories, and tags while keeping the existing WordPress publish date. That keeps refreshed articles from moving to the top of date-based archives unless you intentionally change the date in WordPress.

Posts with Pictures

Image-based articles need one extra review step because Markdown source files and WordPress media files are different assets. Keep source images near the article, such as .posts\2026.06.23\assets\example-screenshot.png, so the draft and its pictures travel together.

Before publishing, upload the images to the WordPress Media Library or import them with WP-CLI:

wp --path="C:\inetpub\sites\example.com" media import .\.posts\2026.06.23\assets\example-screenshot.png --post_id=123 --title="Example screenshot"

After import, use the public Media Library URL in the post content, not a local filesystem path. Review the post preview and confirm that each image loads, has useful alt text, fits within the article width, and points to wp-content/uploads or another intentional public media location.

Review in wp-admin

After the sync finishes, open wp-admin and check:

  • The post title and slug match the source article.
  • Categories and tags are correct.
  • Code blocks render with the site's syntax highlighter.
  • Images load from public WordPress media URLs.
  • The publish date is correct.
  • There are no duplicate posts with the same slug.

WP-CLI Setup

If wp is not available in the terminal yet, install WP-CLI first. The setup steps and basic command examples are covered in Install WP-CLI on Windows and Run Basic WordPress Commands.

Post Views: 6
<- Install WP-CLI on Windows and Run Basic WordPress Commands
Copy WordPress Plugin Settings from Dev to Production with WP-CLI ->

Categories

  • Active Directory (5)
  • AI (1)
  • Amazon Cloud Services (1)
  • Blazor (1)
  • C# (C-Sharp) (3)
  • CI/CD Pipelines (1)
  • Containers (4)
  • Deployment (2)
  • Development (3)
  • Docker (3)
  • General (5)
  • IIS 6.0 (4)
  • IIS 7.0 (10)
  • IIS 8.0 (1)
  • Infrastructure as Code (IaC) (1)
  • Kubernetes (3)
  • Microsoft 365 (2)
  • MySQL (1)
  • Office 2010 (1)
  • PHP (1)
  • PowerShell (6)
  • SharePoint 2007 (8)
  • SharePoint 2010 (19)
  • SharePoint 2013 (2)
  • SharePoint Online (1)
  • SMTP (4)
  • SQL Server 2008 (1)
  • SQL Server 2008 R2 (1)
  • SQL Server 2012 (2)
  • SQL Server 2019 (1)
  • Uncategorized (1)
  • URL Rewrite (2)
  • Visual Studio 2019 (1)
  • Visual Studio Code (1)
  • Windows 10 (4)
  • Windows 2003 (9)
  • Windows 2008 (18)
  • Windows 2012 (6)
  • Windows 7 (3)
  • Windows Firewall (1)
  • Windows Vista (1)
  • WordPress (4)
  • WP-CLI (3)

Recent Posts

  • Use AGENTS.md, CLAUDE.md, Cursor Rules, and Prompt Logs to Keep AI Coding Bots in Context
  • Copy WordPress Plugin Settings from Dev to Production with WP-CLI
  • Move WordPress Articles from Dev to Production with WP-CLI
  • Install WP-CLI on Windows and Run Basic WordPress Commands
  • Make Sure PowerShell Scripts Can Run on Windows

Advertisement

Tags

backconnectionhostnames custom column dev to production disable shutdown event tracker error opening exe exe permissions externalize blob externalize sharepoint data filezilla server firewall rules filazilla full installation http redirect https https redirect IIS iis7 iis 7 installation IIS installation index server configuration installing cumulative updates load balance central administration microsoft 365 moss advanced search nlb no default gateway powerpoint powershell redirect http to https search column sharepoint 2010 cumulative updates sharepoint 2010 farm build sharepoint 2010 farm configuration sharepoint 2010 farm installation sharepoint data externalization shutdown event tracker shutdown tracker SMTP storagepoint Windows 7 windows firewall configuration windows server 2008 wlbs wordpress wp-cli x86
© 2026 JPPinto.com – Tech Blog. All rights reserved.