Skip to content

A working site with no production database

planned

Not verified end to end yet

Every command on this page exists and does what it says. Nobody has yet confirmed the whole path in one run against a real project: clone, build, render. Until then, treat this as the intended route rather than a promise, and see what is still open below.

The scrubber and the mail guard exist because a copied production database is dangerous. This is the path on which that question does not arise.

The idea

A cwp tree already holds almost everything a site is: content, menus, terms, settings, roles, widget areas, the inventory and the design system. With media in the tree, it holds the images an attachment points at too. What stays in the database that the tree does not describe is users, orders, sessions and comments. Nobody needs that part in order to build a page. That part is what makes a copy a data-protection question.

Turning it on

media:
  tracked: referenced
  max_files: 200
  max_megabytes: 50

referenced carries the files your pulled content points at: the featured image, the picture in a page. That is what a page needs to render. library carries every attachment the site holds, linked or not, and is the answer for a small site whose pictures are the site. none is the default, and it is what this guide turns off.

The limits come with the switch rather than separately. git cannot delta-compress binaries: it stores every version of every file whole and forever, and nobody can repair a history afterwards. You would discover a budget that started generous at the point it is too late to change.

Then capture what the tree points at:

cwp adopt prod
cwp pull prod

The pull reads the content, then fetches the originals that content names. It never captures derived sizes: thumbnails, -300x200 variants, WebP copies. They are build output, they depend on the theme’s configuration, and thirty uploads become two hundred files with them.

If the budget stops it, the run says so and names what it left behind. Raise the limit, or leave those files on the site. That is a decision, not a failure.

Building the site

From a clean checkout, with no database import of any kind:

git clone <your project>
cd <your project>
ddev start
ddev wp core download
ddev wp core install --url=... --title=... --admin_user=... --admin_email=...

That is an empty WordPress: your admin user, nothing else.

cwp push
cwp wp -- media regenerate --yes

The push writes the tree into it: content, terms, menus, settings, roles, widget areas, the design system. The regenerate is WP-CLI’s own: cwp wp forwards everything after -- verbatim. cwp has no regenerate verb of its own. It carried the originals, and WordPress already knows how to rebuild the derived sizes. The tree leaves them out for that reason.

What this buys, said carefully

No customer data, no user accounts, no orders and no email addresses reach the machine you work on. For an agency that is not convenience. It is the answer to a question a client’s data-protection officer asks.

The honest framing, and the one that survives contact with a lawyer: cwp does not make anyone compliant. It removes the step that creates the exposure. The scrubber and the mail guard stay for the projects that still need the real database, and there are plenty of them: anything where the work is the orders, the members or the comments.

What is still open

  • Nobody has run the whole path end to end on a real project. Each command works; the sequence has not yet run in one go.
  • The byte budget counts as files land, not before the fetch. No provider reports a remote file’s size, so a pre-flight check would have to invent the numbers. The limit holds; it spends the bandwidth first.
  • Git LFS is an escape the manual documents, never a requirement. A project whose imagery exceeds a sensible budget should reach for it, or leave the media on the site and accept that a local build shows gaps.