Title: Pinery Static
Author: amgoodman
Published: <strong>October 30, 2026</strong>
Last modified: October 30, 2026

---

Search plugins

![](https://ps.w.org/pinery-static/assets/banner-772x250.png?rev=3775360)

![](https://ps.w.org/pinery-static/assets/icon-256x256.png?rev=3775215)

# Pinery Static

 By [amgoodman](https://profiles.wordpress.org/amgoodman/)

[Download](https://downloads.wordpress.org/plugin/pinery-static.2.5.1.zip)

 * [Details](https://wordpress.org/plugins/pinery-static/#description)
 * [Reviews](https://wordpress.org/plugins/pinery-static/#reviews)
 *  [Installation](https://wordpress.org/plugins/pinery-static/#installation)
 * [Development](https://wordpress.org/plugins/pinery-static/#developers)

 [Support](https://wordpress.org/support/plugin/pinery-static/)

## Description

Pinery Static turns your WordPress site into a fast, secure static site hosted on
Cloudflare Pages. You keep editing in WordPress as usual; visitors get plain HTML
from Cloudflare’s network. No Node.js, no wrangler, no build server — the export
and the Direct Upload to Cloudflare run in pure PHP, so it works on ordinary shared
hosting.

**Free — the full static pipeline, no limits on size**

 * One-click export of the whole site and deploy to Cloudflare Pages (pure-PHP Direct
   Upload, unlimited pages)
 * Incremental exports — only changed pages and the archives they appear on are 
   re-crawled
 * Batched and resumable, so large sites survive shared-hosting timeouts
 * Choose which content types to export and exclude paths (WooCommerce cart / checkout/
   account are excluded by default)
 * SEO intact: absolute canonical / og:url, sitemap.xml with lastmod, your own robots.
   txt rules, 404 page, _redirects
 * Theme, Yoast and Rank Math meta and structured data carry over in the static 
   HTML
 * Paginated listings (/page/2/ …) are exported too
 * Cloudflare connection test, deployment history, bilingual admin (English / 中文)

**Plus (optional upgrade)** — for running the static site as your production site:

 * Auto-deploy on publish: edit in WordPress, the static site updates itself
 * Comments, live search and a contact form keep working on the static site (handled
   by WordPress through its REST API)
 * WebP images: uploaded JPEG / PNG files are converted on export (cached) and served
   as WebP, usually 30–70% smaller
 * One-click domain switch: serve the static site on your existing domain through
   a Cloudflare Worker, while /wp-admin keeps working on the same domain — with 
   one-click roll back
 * Roll production back to any earlier deployment

**Pro** — everything in Plus, for stores:

 * WooCommerce live prices, stock and add-to-cart on static product pages
 * Priority support
    Plus and Pro are a separate download you get after upgrading;
   the version on WordPress.org contains no locked code.

**How it works**

 1. The plugin crawls your published pages (through your own site) and writes a static
    build: HTML plus the CSS, JS, images and fonts they use.
 2. It hashes the files (BLAKE3, as Cloudflare’s own tools do) and uploads only what
    changed to your Cloudflare Pages project.
 3. Your site is live on `<project>.pages.dev`; add your own domain in Cloudflare whenever
    you are ready.

_Not affiliated with, or endorsed by, Cloudflare or WordPress._

### External services

This plugin connects to the following services:

**Cloudflare API** (api.cloudflare.com) — to publish your static site, which is 
the purpose of the plugin. When you click Test connection, Export & Deploy or Refresh(
deployments), it sends your Cloudflare Account ID and API token (for authentication),
your Pages project name and branch, and the files of the generated static site (
HTML pages and the assets they use) to Cloudflare. Nothing is sent until you enter
credentials and start one of these actions. Pro additionally uses the Cloudflare
API to deploy a Worker and add its routes when you click the domain switch buttons.

Cloudflare terms: https://www.cloudflare.com/website-terms/ — privacy policy: https://
www.cloudflare.com/privacypolicy/

The plugin also requests pages from your own site to build the static copy; those
requests stay between your server and your site.

## Screenshots

[⌊Pinery Static Deploy screen — Cloudflare credentials, content selection, and one-
click deployment.⌉⌊Pinery Static Deploy screen — Cloudflare credentials, content
selection, and one-click deployment.⌉[

Pinery Static Deploy screen — Cloudflare credentials, content selection, and one-
click deployment.

[⌊Pinery Static Migration Wizard — zero-downtime domain switch and custom routing.⌉⌊
Pinery Static Migration Wizard — zero-downtime domain switch and custom routing.⌉[

Pinery Static Migration Wizard — zero-downtime domain switch and custom routing.

## Installation

 1. Install and activate the plugin.
 2. Go to **Pinery Static  Deploy** in the admin menu.
 3. Enter your Cloudflare **Account ID** and an **API Token** with the permission `
    Account › Cloudflare Pages › Edit`. The **Project** name is filled in from your
    domain.
 4. Click **Export & Deploy to Pages**.

For maximum security, keep the token out of the database by defining it in `wp-config.
php`: define( ‘WP2CF_API_TOKEN’, ‘your-token’ );

## FAQ

### Does it need Node.js or wrangler?

No. Export and the Cloudflare Direct Upload are implemented in pure PHP.

### Does WordPress have to stay online?

For editing and deploying, yes. Visitors are served by Cloudflare, so the static
site stays up even when WordPress is slow or down.

### Do comments, search and forms work on the static site?

A static site cannot run PHP, so anything dynamic stops working in the free version.
Plus and Pro keep comments, search and a contact form working by sending them to
your WordPress through its REST API.

### Can I use it with WooCommerce?

Yes. Product and shop pages can be exported statically for SEO; add-to-cart buttons
send shoppers to the normal WooCommerce cart on WordPress, and cart, checkout and
account always stay dynamic. The Pro plan adds live prices and stock on the static
pages.

### Is my API token stored safely?

It is encrypted at rest with your site’s keys, or you can keep it out of the database
entirely with the `WP2CF_API_TOKEN` constant.

### How do I update or switch to Pro without losing my settings?

Update in place: use the normal Update button, or Plugins  Add New  Upload Plugin
and choose “Replace current with uploaded”. Don’t delete the plugin first — deleting
runs the uninstall cleanup, which removes its settings and the export folder. When
you install Pro next to the free version, Pro takes over with the same settings 
and the free copy steps aside; you can then delete the free copy.

### How do I get Pro?

Buy a license at https://www.pinery.pro/en/static/#pricing, download Pinery Static
Pro from the link in your purchase email (or your account), then upload and activate
it under Plugins  Add New  Upload Plugin. Your settings carry over, and Pro updates
itself from then on.

### Where can I ask questions or report a bug?

In the Pinery community on Reddit: https://www.reddit.com/r/pinery/ — questions,
ideas and bug reports are all welcome there.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Pinery Static” is open source software. The following people have contributed to
this plugin.

Contributors

 *   [ amgoodman ](https://profiles.wordpress.org/amgoodman/)

[Translate “Pinery Static” into your language.](https://translate.wordpress.org/projects/wp-plugins/pinery-static)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/pinery-static/), check
out the [SVN repository](https://plugins.svn.wordpress.org/pinery-static/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/pinery-static/) 
by [RSS](https://plugins.trac.wordpress.org/log/pinery-static/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 2.5.1

 * New plugin icon
 * Community link (r/pinery) on the Plugins screen and at the bottom of the Deploy
   screen

#### 2.5.0

 * Three plans: Free, Plus and Pro. Plus includes every paid feature except WooCommerce
   live prices / stock, which is in the Pro plan
 * On a Plus license the WooCommerce option is shown locked with an upgrade link;
   a stored setting is kept, so moving to Pro turns it back on

#### 2.4.2

 * The WordPress.org version no longer bundles the Freemius SDK: it is smaller, 
   has no opt-in screen and contacts no service besides Cloudflare. Upgrade links
   go to the pricing page; Pro (with its own licensing and updates) is a separate
   download
 * When Pinery Static Pro is active, a free copy that is still installed steps aside
   with a notice instead of competing with it
 * Uninstall cleanup is shared by both versions and still keeps the settings while
   another copy of the plugin is installed

#### 2.4.1

 * Plugin header: Plugin URI now points to the plugin’s own page (it was the same
   as the Author URI)

#### 2.4.0

 * Pro: new “Images” option — serve uploaded JPEG / PNG images as WebP on the static
   site. Converted on your server while exporting through the WordPress image editor(
   GD or Imagick), cached so each image is converted once, used only when smaller;
   originals stay in the build and social-preview images (og:image) keep the original.
   Off by default; the setting explains when the server can’t write WebP

#### 2.3.9

 * Settings, free plan on WooCommerce sites: a note under Content Types explains
   that exported product pages show price and stock as of export time (checkout 
   always uses the live price) and that Pro keeps them live

#### 2.3.8

 * Fix: the Cloudflare API token entered on a fresh install (before any settings
   were saved) didn’t work until it was saved a second time — WordPress sanitizes
   a brand-new option twice and the token got encrypted twice
 * FAQ: how to update or switch to Pro without losing settings

#### 2.3.7

 * Faster repeat visits: the build now includes a Cloudflare Pages _headers file
   so browsers keep images (30 days) and theme, plugin and core assets (7 days) 
   instead of re-checking every file on every page view. Adjustable with the wp2cf_cache_headers
   filter
 * Fix: the _redirects rules from the settings (and the new _headers) are sent to
   Cloudflare as deployment configuration, the way Cloudflare’s own tools do, instead
   of as a plain file in the build
 * The site-wide comments feed (/comments/feed/, linked from most themes’ page head)
   is exported too
 * If a very early copy of the plugin (folder “wp2cf-pages”) is still active, this
   version now pauses with a notice asking you to deactivate the old one, instead
   of a fatal error on activation

#### 2.3.6

 * Security: the stored Cloudflare API token is now encrypted with the site’s WordPress
   salts even when wp-config.php doesn’t define them (they live in the database 
   then). Tokens saved by earlier versions keep working and are re-encrypted the
   next time you enter a token
 * Pro, Migration: the “proxied by Cloudflare” check also asks Cloudflare from the
   server, so it turns green right after you switch the DNS record to orange even
   if your own browser still reaches the old IP

#### 2.3.5

 * Settings, free plan: locked Pro options (comments, search, contact form, auto-
   deploy, WooCommerce) now show unchecked, and saving the settings no longer switches
   them off — they keep their Pro defaults for when you upgrade

#### 2.3.4

 * Settings: Cloudflare dashboard links and help text reworded; uninstall cleanup
   uses WordPress functions instead of a direct database query (Plugin Check clean-
   up)

#### 2.3.3

 * Pro, comments: a visitor’s comment that is waiting for moderation stays visible
   to them (marked “awaiting moderation”) after reloading the page, like on a normal
   WordPress site, until it is approved

#### 2.3.2

 * Pro, WooCommerce: product pages now show the live “N in stock” text from the 
   store, not the number frozen at export time

#### 2.3.1

 * Deploy screen: the crawl progress no longer goes past 100% when new pages are
   discovered while crawling

#### 2.3.0

 * Free and Pro are now separate builds: the free version contains only free features(
   ready for WordPress.org), Pro features ship in the Pro build you get with a license.
   Licensed sites receive the Pro build through the normal update
 * Admin: the Deploy screen’s script is now a proper enqueued file; output escaping
   and input sanitizing tightened throughout; the language switch link is protected
   with a nonce
 * Requests the plugin sends to its own site (crawl, background deploy) follow WordPress’
   https_local_ssl_verify setting, like core’s own loopback requests
 * Build files are deleted through WordPress’ file APIs
 * Uninstall also removes the domain-switch setting and recognises the Pro folder
   name

#### 2.2.2

 * Domain switch: when the API token cannot read the Worker routes yet, the state
   shows “Unknown” instead of “Not switched” (a domain switched by hand was reported
   as not switched). Clearer message when the token cannot see the domain’s zone

#### 2.2.1

 * Domain switch: sites on a subdomain (e.g. blog.example.com) get only their own
   route. The www / non-www twin route and redirect are now limited to the zone 
   apex and its www, so a wildcard DNS record no longer adds a route for www.blog.
   example.com

#### 2.2.0

 * New (Pro): one-click domain switch. The Migration screen checks readiness (domain
   proxied by Cloudflare, static site deployed, API token permissions), then deploys
   the routing Worker and adds its routes with one click; Roll back removes the 
   routes again. Needs three extra token permissions: Zone > Zone > Read, Zone >
   Workers Routes > Edit, Account > Workers Scripts > Edit
 * Changed: the routing Worker now reaches WordPress through your own domain by 
   default, so no separate origin hostname (wp.yourdomain), certificate or redirect-
   loop setup is needed. Hosts with bot challenges (e.g. SiteGround) keep seeing
   the real visitor IP. A separate origin hostname is still available under Advanced
 * The Worker also 301-redirects the www / non-www twin of your domain to the canonical
   host
 * Migration screen redesigned: server details, manual Worker setup and the separate-
   origin steps moved into an Advanced section

#### 2.1.7

 * Fix: anonymous AJAX forms on static pages (e.g. Beaver Builder / UABB subscribe
   forms, contact plugins) stopped working about a day after each build, because
   the nonce baked into the page expired. Nonces for logged-out visitors now last
   two years; logged-in users keep the normal 24-hour nonces. Run a full rebuild
   after updating so every page gets a long-lived nonce

#### 2.1.6

 * SEO: the static robots.txt is now the one WordPress serves (core, your SEO / 
   robots plugin or a physical file), so crawl rules such as Disallow: /tag/ carry
   over. Previously every build wrote a permissive “Allow: /” robots.txt. Falls 
   back to the old default only if WordPress’s robots.txt can’t be fetched

#### 2.1.5

 * Domain migration: “Verify origin” bypasses the host’s page cache (random query
   string), shows cache status per check and lists which X- headers reach PHP, so
   a stale cached answer can’t pass or fail the check

#### 2.1.4

 * Domain migration: works on hosts that strip X-Forwarded-Host before PHP (e.g.
   SiteGround). The routing Worker now also sends X-Pinery-Host, which the plugin’s
   redirect-loop guard reads first. Re-copy the Worker script if you deployed it
   with an earlier version

#### 2.1.3

 * Domain migration: “Verify origin” shows who issued a redirect (X-Redirect-By,
   cache, server) and which host headers actually reached PHP, to pinpoint redirect
   loops caused by the hosting stack

#### 2.1.2

 * Domain migration: the redirect-loop guard is now built into the plugin. Requests
   the routing Worker forwards to the origin host are served as your public domain(
   only your own domain is accepted), so nothing has to be added to wp-config.php
   any more
 * Domain migration: “Verify origin” now explains an expired page (“reload and verify
   again”) instead of just printing “failed”

#### 2.1.1

 * Licensing: Pro features now depend only on the Freemius license check; if the
   licensing component cannot load, the plugin runs as Free
 * Domain migration: when the site is already proxied by Cloudflare but this server’s
   DNS cache still lists the old nameservers, the page now says so instead of showing“
   nameservers point to Cloudflare” next to the old nameservers
 * Domain migration: link to the optional done-for-you setup service

#### 2.1.0

 * First stable release (new version numbering). Includes everything from 0.2.2–
   0.2.9 below.
 * Freemius WordPress SDK updated from 2.13.1 to 2.13.4 (as recommended by Freemius)

#### 0.2.9

 * Fix: paginated listings are now exported. /page/2/, /page/3/… of the home page,
   the blog page, category / tag archives and pages with a paginated posts module(
   e.g. Beaver Builder) were never crawled, so “next page” links 404’d on the static
   site. The crawler now follows each listing’s pagination links, and re-crawls 
   them whenever that listing is refreshed.

#### 0.2.8

 * Admin menu: Pinery Static is now its own top-level menu with Deploy, Migration
   and Account together (previously split across Tools)
 * Origin verifier also checks a front-end page: the REST API never canonical-redirects,
   so a missing wp-config X-Forwarded-Host snippet used to pass the check and only
   loop after cutover. It now also refuses the public domain itself as the origin,
   detects an origin that serves the static copy, and flags a blocked wp-login.php
 * Router Worker: redirects pointing at the *.pages.dev or origin hostname are rewritten
   to the public domain, so visitors never land on a backend host. Re-copy the Worker
   script from the migration page.
 * Migration page: “Copy Worker script” refuses until the origin host is entered(
   an unfilled WP_ORIGIN crashes the Worker); SiteGround Site Tools is detected 
   with its own steps (Parked Domains + SSL Manager); cutover steps now cover www
   routes, Proxied records, SSL mode Full (strict) and checking email DNS records

#### 0.2.7

 * WooCommerce: add-to-cart on static pages now goes straight to WordPress (cart
   forms and ?add-to-cart links point at WP, WooCommerce’s AJAX hook removed), so
   items land in the normal cart that /cart/ and /checkout/ show. Previously the
   static page used a separate Store API cart (Cart-Token) the WordPress cart page
   never saw. Live price / stock hydration is unchanged.
 * Router Worker: ?add-to-cart and ?wc-ajax go to WordPress, and any URL the static
   build doesn’t have (cart / checkout / my-account, excluded paths, posts published
   since the last deploy) falls back to WordPress instead of 404ing. Re-copy the
   Worker script from the migration page.
 * Migration page fills the Worker’s WP_ORIGIN from the origin host you enter

#### 0.2.6

 * Fix: a static front page (Settings  Reading  “A static page”) is now refreshed
   on every incremental / auto deploy like the home page it is — previously it was
   only re-exported when that page itself was edited

#### 0.2.5

 * Smart incremental: a change re-crawls only the edited pages, home / feed / sitemap,
   and the category / tag archives those pages are (or were) listed on — not every
   archive on the site. (The first run after updating still refreshes all archives
   once.)
 * Auto-deploy now runs in short background slices (WP-Cron + self-chained loopback,
   with a cron safety net), so hosts that kill long requests can’t stop it; transient
   Cloudflare errors are retried; edits made during a deploy trigger a follow-up
   deploy
 * Manual Export / Deploy waits for a running background slice instead of colliding
   with it

#### 0.2.4

 * Fix: uploaded asset hashes are registered with Cloudflare (upsert-hashes, as 
   wrangler does), so later deploys only upload changed files instead of the whole
   build
 * Export / Deploy refuse to run while the settings form has unsaved changes (previously
   they silently used the last saved settings)

#### 0.2.3

 * Fix: “Activate License” now appears under the plugin on the Plugins screen — 
   license keys can be entered directly in this build (Freemius has_premium_version
   = false)
 * Fix: deploy progress no longer shows “hash: 0/N” when switching from hashing 
   to upload

#### 0.2.2

 * Crawl origin is auto-probed (loopback https/http, then the public site); export
   aborts up front if none reaches WordPress
 * Never deploys an empty build when no pages could be crawled
 * Exported pages carry a marker so the crawler refuses to re-export its own static
   copy; the router Worker sends crawler requests (X-WP2CF-Crawl) to WordPress
 * Deploy: large files are stream-hashed across requests (no more gateway 503/504),
   hashes are cached between deploys, interrupted deploys resume where they stopped
 * Uploads are size-bounded per request; files over the Cloudflare Pages 25 MiB 
   limit are skipped and listed

#### 0.2.1

 * Freemius licensing integrated (in-dashboard checkout, license activation, opt-
   in analytics — skippable); activating a Pro license instantly unlocks premium
   features

#### 0.2.0

 * Freemium: the full unlimited static export + deploy pipeline is now the Free 
   plan; Pro ($299 one-time per site) unlocks auto-deploy on publish, comments/search/
   contact proxies, WooCommerce live hydration, seamless-domain migration and one-
   click rollback
 * Settings preserved across plans — activating a license instantly unlocks Pro 
   features

#### 0.1.0

 * Initial release: crawl, pure-PHP Direct Upload to Cloudflare Pages, incremental
   + batched deploy, auto-deploy, comments/search/contact proxy, content scope, 
   SEO (sitemap/robots/canonical), migration wizard, bilingual admin.

## Meta

 *  Version **2.5.1**
 *  Last updated **1 day ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 5.6 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [cloudflare-pages](https://wordpress.org/plugins/tags/cloudflare-pages/)[performance](https://wordpress.org/plugins/tags/performance/)
   [security](https://wordpress.org/plugins/tags/security/)[static export](https://wordpress.org/plugins/tags/static-export/)
   [static site](https://wordpress.org/plugins/tags/static-site/)
 *  [Advanced View](https://wordpress.org/plugins/pinery-static/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/pinery-static/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/pinery-static/reviews/)

## Contributors

 *   [ amgoodman ](https://profiles.wordpress.org/amgoodman/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/pinery-static/)