PageFerry exports a single Gutenberg page, post, or custom post type to a ZIP file on staging, then imports it on production with correct block-level attachment remapping. No full-DB overwrite. No broken images.
The native WordPress exporter leaves image files behind. Full-site migrators overwrite live orders, customers, and fresh content. Manual copy/paste means re-uploading media and fixing references by hand.
The #1 complaint about WXR export: references come over, files don't. PageFerry bundles every used file into the ZIP.
One page moves. Nothing else is touched — no database overwrite, no lost orders or comments.
SHA-256 content-hash dedup reuses byte-identical files instead of stacking another copy on every re-import.
ZIP-first workflow. Works across hosts, firewalls, and client handoffs — no site-to-site pairing needed.
Open the page → PageFerry Export → Ferry this page → download the ZIP (content + pageferry-manifest.json + media files).
Tools → PageFerry Import → upload the ZIP → preview what will change → choose create-new or update-selected.
PageFerry dedupes media, remaps attachment IDs + URLs, preserves slug and taxonomies, snapshots the overwritten page, and writes a log row.
One perfect flow: a Gutenberg page + its media, moved correctly. Free scope is deliberately Gutenberg-only.
Conservative scan of block attributes (any depth) + saved HTML. IDs and URLs rewritten at exact recorded slots — never raw number replacement.
SHA-256 index, always hash-verified on read. Identical bytes reuse the existing attachment; same name with different bytes uploads separately.
Categories, tags, and custom taxonomies travel with hierarchy. Existing terms are reused; only new terms are created.
Staging URLs in content, excerpts, and custom fields are rewritten to production — URL-shaped occurrences only, prose untouched.
Create-new lands as draft with a unique slug, or update a selected page of the same post type. Re-pushes don't duplicate.
Every update snapshots prior content + meta (last 20 under Backups). Every import writes a plain-language log row (last 200).
v1.1: block-editor CPTs and custom taxonomies ferry. ACF blocks storing fields in post meta (usePostMeta) ferry values with media-ID remap.
Elementor / Divi / Beaver / Bricks / WPBakery bundles are refused with a message naming the builder — never silently corrupted.
No outbound requests, no CDN, no accounts or keys. All JS vendored locally. Nonce + capability checks on every handler.
pageferry-export.zip
├── pageferry-manifest.json manifest v1: post, tax_terms, media[], acf_post_meta[]
└── media/
├── 182-hero.jpg original basenames preserved
└── 431-diagram.png
PageFerry wins on correctness, simplicity, and trust — not feature count.
| Approach | What happens |
|---|---|
| Native Tools → Export/Import (WXR) | Exports references, leaves image files behind. Broken images. |
| Full-site migrators / host Push-to-Live | Overwrite the whole database. Live orders, users, and comments at risk. |
| Manual copy/paste | Re-upload media, re-enter meta/SEO/taxonomies by hand. Tedious, error-prone. |
| PageFerry | One page + its media, block-level remap, hash dedup, update-in-place. Nothing else touched. |
From the plugin readme.
PageFerry v1 imports Gutenberg pages only. The exporter detects page-builder meta and the importer refuses the bundle with a message naming the builder instead of silently corrupting the layout. Export as Gutenberg blocks (or rebuild in the block editor) and ferry again.
Every file is hashed (SHA-256) at export. On import, PageFerry looks the hash up in its reuse index and verifies by re-hashing the existing attachment — a stale index row never reuses a deleted file. Identical bytes reuse the attachment; same filename with different bytes uploads separately.
You choose on the import screen. Create-new inserts as a draft with a unique slug. Update-selected overwrites content, excerpt, terms, and featured image after snapshotting the prior version into Backups. Terms match by name; existing terms keep their current parents.
Tools → PageFerry Import → Backups. Each update stores the target's prior content and meta before writing anything (kept: last 20). The Logs tab links each update row to its backup key.
Your host caps each upload. Bundles over the cap import file-by-file automatically — but one single asset over the cap cannot. Raise the PHP upload limit, or drop that asset and re-export. The error names the file.
Blocks keeping field data in the block comment ferry like any other blocks. Blocks storing fields in post meta (usePostMeta, ACF PRO 6.3+) ferry values too: image/file/gallery IDs remap, URLs rewrite, the rest restores verbatim via the ACF API. Reference-type IDs (post/relationship/taxonomy/user) ferry verbatim — the export warns when they hold values.
Requirements: WordPress 6.5+, PHP 8.1+, PHP zip extension (export side).
pageferry to /wp-content/plugins/, activate.Download v1.1.0 Free · GPL-2.0-or-later · by vadim.xyz
usePostMeta blocks: field values stored in post meta now ferry in the bundle and restore with media-ID remap and URL rewrite. Skipped values reported in the log row.