Ferry a page from staging to production — media included.

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.

v1.1.0 WordPress 6.5 – 6.8 PHP 8.1+ Gutenberg-only GPL-2.0-or-later No accounts · No CDN · No phone-home
Export  →  ZIP (content + manifest + media)  →  Import  →  dedupe → remap → create / update

The problem it solves

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.

Broken images after import

The #1 complaint about WXR export: references come over, files don't. PageFerry bundles every used file into the ZIP.

Fear of overwriting live data

One page moves. Nothing else is touched — no database overwrite, no lost orders or comments.

Duplicate media bloat

SHA-256 content-hash dedup reuses byte-identical files instead of stacking another copy on every re-import.

How it works

ZIP-first workflow. Works across hosts, firewalls, and client handoffs — no site-to-site pairing needed.

1

Export on staging

Open the page → PageFerry Export → Ferry this page → download the ZIP (content + pageferry-manifest.json + media files).

2

Import on production

Tools → PageFerry Import → upload the ZIP → preview what will change → choose create-new or update-selected.

3

Confirm

PageFerry dedupes media, remaps attachment IDs + URLs, preserves slug and taxonomies, snapshots the overwritten page, and writes a log row.

What v1 does

One perfect flow: a Gutenberg page + its media, moved correctly. Free scope is deliberately Gutenberg-only.

Block-level attachment remap

Conservative scan of block attributes (any depth) + saved HTML. IDs and URLs rewritten at exact recorded slots — never raw number replacement.

Hash-based media reuse

SHA-256 index, always hash-verified on read. Identical bytes reuse the existing attachment; same name with different bytes uploads separately.

Slug + taxonomies preserved

Categories, tags, and custom taxonomies travel with hierarchy. Existing terms are reused; only new terms are created.

Domain rewrite

Staging URLs in content, excerpts, and custom fields are rewritten to production — URL-shaped occurrences only, prose untouched.

Create or update in place

Create-new lands as draft with a unique slug, or update a selected page of the same post type. Re-pushes don't duplicate.

Backup + logs

Every update snapshots prior content + meta (last 20 under Backups). Every import writes a plain-language log row (last 200).

CPT + ACF post-meta blocks

v1.1: block-editor CPTs and custom taxonomies ferry. ACF blocks storing fields in post meta (usePostMeta) ferry values with media-ID remap.

Builder guard

Elementor / Divi / Beaver / Bricks / WPBakery bundles are refused with a message naming the builder — never silently corrupted.

Private by design

No outbound requests, no CDN, no accounts or keys. All JS vendored locally. Nonce + capability checks on every handler.

Inside the bundle

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

Why not the alternatives?

PageFerry wins on correctness, simplicity, and trust — not feature count.

ApproachWhat happens
Native Tools → Export/Import (WXR)Exports references, leaves image files behind. Broken images.
Full-site migrators / host Push-to-LiveOverwrite the whole database. Live orders, users, and comments at risk.
Manual copy/pasteRe-upload media, re-enter meta/SEO/taxonomies by hand. Tedious, error-prone.
PageFerryOne page + its media, block-level remap, hash dedup, update-in-place. Nothing else touched.

FAQ

From the plugin readme.

Why was my Elementor page refused?

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.

How does media dedup work?

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.

Update vs create — which is used?

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.

Where is my pre-import backup?

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.

The import says a file is too large. What now?

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.

Does PageFerry ferry ACF block data?

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.

Get PageFerry

Requirements: WordPress 6.5+, PHP 8.1+, PHP zip extension (export side).

  1. Upload pageferry to /wp-content/plugins/, activate.
  2. Staging: open a page → PageFerry Export → Ferry this page → download ZIP.
  3. Production: Tools → PageFerry Import → upload ZIP → Upload and preview → Confirm import.
  4. Review the result under Tools → PageFerry Import → Logs (and Backups for updates).

Download v1.1.0 Free · GPL-2.0-or-later · by vadim.xyz

Changelog

1.1.0

1.0.0