flexweg-import
flexweg-import provides bulk import of posts and pages from two source formats:
- Markdown files with YAML frontmatter — drop a folder of
.mdfiles - WordPress XML exports (WXR) — upload a
.xmlexported fromwp-admin/export.php
Imports auto-create categories / tags (preserving WP hierarchy), upload referenced images to the media library (rewriting image URLs in the body to match), and match authors to existing CMS users by email.
The plugin is must-use so it can ship and iterate independently of the rest of the admin without any plugin-list churn.
Settings
/settings/plugin/flexweg-import is a single-page workflow:
Source picker
Two tabs: Markdown folder (drag-and-drop a directory of .md files) and WordPress XML (file picker for the .xml export).
Preview
After parsing, the page shows:
- N posts, M pages detected
- Category tree with N tags (preserving the WP
parent/childrelationships) - Author list with each author's email — green checkmark for emails matching an existing CMS user, amber warning otherwise
- Image count — total images that'll need to be downloaded + re-uploaded
Options
- Default status — import as
onlineordraft. Defaultdraftso a misconfigured import doesn't go live. - Author fallback — when no email match: skip the post, assign to the current user, or assign to a chosen user from a picker.
- Image handling —
download + upload(default), orkeep external URLs(faster but creates external dependencies). - Skip duplicates — when on, imports skip posts whose
slugalready exists.
Confirm import
Runs the import. Progress bar with per-post log. Errors are listed at the end (typically image-fetch 404s or permission issues).
Markdown frontmatter format
---
title: My first post
slug: my-first-post # optional — derived from filename if absent
date: 2026-03-15T10:00:00Z # createdAt
status: online # 'online' | 'draft'
author: Jane Smith
categories: [News, Updates] # auto-created, comma-separated
tags: [release, beta]
heroImage: ./images/hero.jpg # path relative to .md file
excerpt: Short summary here
---
# My first post
Body content in **Markdown**.
The parser is forgiving — missing fields fall back to sensible defaults.
WordPress XML import
Standard WXR (wp-admin/export.php output) is supported with these mappings:
| WordPress | Flexweg CMS |
|---|---|
<wp:post_type>post</wp:post_type> | Post.type = 'post' |
<wp:post_type>page</wp:post_type> | Post.type = 'page' |
<wp:post_type>attachment</wp:post_type> | imported into media library |
<title> | Post.title |
<wp:post_name> | Post.slug |
<wp:post_date> | Post.createdAt (in WP timezone) |
<wp:status>publish</wp:status> | Post.status = 'online' |
<wp:status>draft|pending|future</wp:status> | Post.status = 'draft' |
<category domain="category"> | Term.type = 'category' (with hierarchy) |
<category domain="post_tag"> | Term.type = 'tag' |
<dc:creator> + <wp:author_email> | matched against users collection |
<content:encoded> | converted from HTML to Markdown via turndown |
Image URLs in <content:encoded> | downloaded + re-uploaded + URLs rewritten |
Custom post types and custom taxonomies are skipped (with a warning in the log) — Flexweg CMS v1 doesn't support them.
Comments are skipped entirely. Re-import them via a third-party comments service if needed (Disqus has a WP comment importer).
How it hooks in
The plugin has no lifecycle hooks. Importing is purely on-demand: the user clicks Confirm in the settings page, the importer runs to completion, then nothing else happens. The publish flow doesn't need to react to imports because the imports themselves call the standard createPost / uploadFile APIs that already trigger every cascade.
When import fails partway through
The importer is resumable: each post imports independently, and a failure on post N doesn't roll back posts 1..N-1. The progress log shows which posts succeeded and which failed. To re-run with only the failed posts: clear the source folder of the successful files and re-import.
Internal details
- Source:
src/mu-plugins/flexweg-import/ - Parsers:
src/mu-plugins/flexweg-import/parsers/ - Examples:
src/mu-plugins/flexweg-import/examples/(markdown),src/mu-plugins/flexweg-import/examples-wordpress/(WP XML) - Hooks used: none
- Translations: 7 locales