PR Preview with WordPress Playground: What changes in version 3 of the GitHub Action

Reviewing a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. or theme Pull Request has always carried a bit of friction. To actually test the change, someone had to pull the branch, spin up a local WordPress, and activate the code by hand. That is exactly why the WordPress Playground PR Preview GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ Action exists: it adds a โ€œPreview in WordPress Playgroundโ€ button straight to the PR. As a result, any reviewer opens the environment with the code already applied in the browser, without installing anything.

The action already existed in v2. However, version 3 underwent an important simplification: the manual โ€œglueโ€ that each project had to write for builds was replaced by ready-made, reusable workflows. In this post, therefore, Iโ€™ll cover what the action does, why itโ€™s worth it, how to set it up in the two possible scenarios, practical examples, and the step-by-step path to migrate from v2.

What the WordPress Playground PR Preview action does

In short, it publishes a preview link on the Pull Request. That link points to a WordPress Playground instance, in other words, a full WordPress running through WebAssembly (WASM) in the browser of whoever clicks it. Playground boots clean, installs the plugin or theme from the PR branch, and automatically activates everything.

The result, then, is a disposable, isolated environment created on demand that mirrors the state of that branch exactly.

Why use it

  • One-click testing: the reviewer needs no local setup and no WordPress installed.
  • Works with forks: external contributions get a preview without exposing repository secrets.
  • Plugin, theme, or both: you can create scenarios that combine several artifacts.
  • Handles complex builds: projects that rely on Composer, npm, or Vite are supported too, through dedicated workflows.
  • Real sandbox: the code runs in the userโ€™s browser, isolated, without touching any server.

Scenario 1: no build step

This is the simplest path. Use it when the files committed to the repository run as-is, without compilation, for example, a plain PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php plugin.

First, create .github/workflows/pr-preview.yml:

name: PR Preview
on:
  pull_request:
    types: [opened, synchronize, reopened, edited]

jobs:
  preview:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: WordPress/action-wp-playground-pr-preview@v3
        with:
          plugin-path: .
          github-token: ${{ secrets.GITHUB_TOKEN }}

For a theme, swap plugin-path: . for theme-path: .. Besides that, the permissions blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. is mandatory: the action needs pull-requests: write to write the link on the PR and contents: read to read the code.

Main inputs of the direct action

InputRequiredDefaultPurpose
plugin-pathone of fourโ€”Relative path to the plugin directory
theme-pathone of fourโ€”Relative path to the theme directory
blueprintone of fourโ€”Custom Blueprint JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. (string)
blueprint-urlone of fourโ€”URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.org to a hosted Blueprint
modenoappend-to-descriptionappend-to-description or comment
github-tokenyesโ€”Token with PR write access
playground-hostnohttps://playground.wordpress.netBase Playground URL

You provide one of plugin-path, theme-path, blueprint, or blueprint-url. The mode, in turn, decides whether the link goes into the PR description body or as a comment.

Scenario 2: with a build step

When the preview depends on compilation (npm run build, Composer, etc.), v3 uses two workflows that talk to each other. First, one builds the untrusted PR code with read-only permissions. Then, the other publishes the result from the default branch, with write permissions, without ever executing the PR code. The only point of contact between them is the generated ZIP file โ€” and that is precisely what keeps the flow secure.

The build workflow lives in .github/workflows/pr-preview-build.yml:

name: PR Preview - Build
on:
  pull_request:
    types: [opened, synchronize, reopened, edited]

jobs:
  build:
    uses: WordPress/action-wp-playground-pr-preview/.github/workflows/preview-build.yml@v3
    with:
      artifacts: my-plugin=build/my-plugin.zip
      node-version: '20'
      build-command: |
        npm ci
        npm run build:plugin-zip

The publish workflow, in turn, lives in .github/workflows/pr-preview-publish.yml:

name: PR Preview - Publish
on:
  workflow_run:
    workflows: ["PR Preview - Build"]
    types: [completed]

permissions:
  contents: write
  pull-requests: write

jobs:
  publish:
    permissions:
      contents: write
      pull-requests: write
    uses: WordPress/action-wp-playground-pr-preview/.github/workflows/preview-publish.yml@v3
    with:
      kind: plugin

The artifacts field uses the name=path/to/file.zip format โ€” one per line, if you have several. The kind in publish, meanwhile, tells whether the artifact is a plugin or a theme. Besides that, the reusable workflows take care of automatically creating a ci-artifacts prerelease to host the ZIPs publicly. After all, Playground needs to download the asset, so it canโ€™t be in a draft release.

Build workflow inputs

InputRequiredPurpose
artifactsyesname=path.zip entries, one per line
build-commandyesShell commands that produce the ZIPs
node-versionnoRuns actions/setup-node@v4 if set
php-versionnoRuns shivammathur/setup-php@v2 if set
fetch-depthnoPassed to actions/checkout@v4 (default: 1)

Practical example: custom Blueprint

Sometimes you need more than โ€œinstall and activateโ€. Say, a plugin from the PR running alongside WooCommerce and already logged in as admin. In that case, use a Blueprint. Itโ€™s a JSON recipe that describes the siteโ€™s initial state.

- uses: WordPress/action-wp-playground-pr-preview@v3
  with:
    blueprint: |
      {
        "$schema": "https://playground.wordpress.net/blueprint-schema.json",
        "preferredVersions": { "php": "8.3", "wp": "6.6" },
        "steps": [
          { "step": "installPlugin",
            "pluginData": {
              "resource": "git:directory",
              "url": "https://github.com/${{ github.repository }}.git",
              "ref": "${{ github.event.pull_request.head.ref }}",
              "path": "/"
            },
            "options": { "activate": true } },
          { "step": "installPlugin",
            "pluginData": { "resource": "wordpress.org/plugins", "slug": "woocommerce" },
            "options": { "activate": true } },
          { "step": "login", "username": "admin" }
        ]
      }
    github-token: ${{ secrets.GITHUB_TOKEN }}

This Blueprint pins PHP 8.3 and WordPress 6.6, installs the code from the PR branch, adds WooCommerce from the official repository, and hands over an already-logged-in environment. For build scenarios, moreover, you can reference the generated ZIPs inside the Blueprint using the {{ARTIFACT_URL:<name>}} placeholder. That way, v3 resolves the public artifact URL for you.

Migrating from v2 to v3

In practice, the migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. varies with the complexity of your setup.

Simple plugins and themes (no build): here, almost nothing changes. Switch the action reference from @v2 to @v3 and keep the same inputs.

# works the same in v2 and v3
- uses: WordPress/action-wp-playground-pr-preview@v3
  with:
    plugin-path: .
    github-token: ${{ secrets.GITHUB_TOKEN }}

Projects with a build: this is where the real gain is. On v2 you needed a build workflow, plus manual parsing of the artifact name, plus an expose-artifact-on-public-url helper, plus manual Blueprint generation, and still the manual release publishing. v3, by contrast, replaces all of that with the two reusable workflows (preview-build.yml and preview-publish.yml) shown above. The step-by-step, therefore, looks like this:

  1. Create pr-preview-build.yml with the build workflow template.
  2. Create pr-preview-publish.yml with the publish workflow template.
  3. Define the artifacts in the artifacts field (name=path format).
  4. Set kind: plugin or kind: theme in publish โ€” or, alternatively, use blueprint with {{ARTIFACT_URL:<name>}} placeholders for setups with multiple ZIPs.

Inputs such as artifact-name, artifact-filename, artifact-source-run-id, pr-number, and commit-sha, which existed only for the manual glue, are no longer needed in most cases.

Finally, watch out for the mandatory release cleanup: the change that breaks the most in practice is that draft releases no longer work. After all, Playground canโ€™t download assets from a draft release without authentication. Therefore, if you have ci-artifacts releases in draft, convert them to prerelease or delete them.

Common gotchas

  • 404 error when opening the preview:ย the release is probably set asย a draftย instead of aย prerelease. Fix it on the repositoryโ€™s Releases tab.
  • Plugin doesnโ€™t show up as installed:ย the ZIP must be extracted to a folder named after the slug. Make sure your build does that. For example:
    bash mkdir -p stage/my-plugin && rsync -a ./ stage/my-plugin/ && (cd stage && zip -r ../my-plugin.zip my-plugin)
  • Build failing when comparing against the base: if you use git diff against the base branch, set fetch-depth: 0 in the build workflow. After all, the default checkout brings only the latest commit.
  • Permission error: the permissions block is missing at the workflow or job level.

Conclusion

If you already used v2 for builds, migrating is worth it: you delete dozens of lines of manual glue and get tested, community-maintained workflows in their place. On the other hand, if you donโ€™t use PR preview in your plugin or theme repository yet, the no-build scenario solves it with a few lines of YAML โ€” and noticeably improves the experience for whoever reviews code in your project.

The full documentation lives at wordpress.github.io/action-wp-playground-pr-preview. For the more specific cases, also check the detailed migration guide.

WordPress Playground table at Contributor Day WCEU 2026

The WordPress Playground team is excited to be part of Contributor DayContributor Day Contributor Days are standalone days, frequently held before or after WordCamps but they can also happen at any time. They are events where people get together to work on various areas of https://make.wordpress.org/ There are many teams that people can participate in, each with a different focus. https://2017.us.wordcamp.org/contributor-day/ https://make.wordpress.org/support/handbook/getting-started/getting-started-at-a-contributor-day/ at WordCamp Europe 2026, taking place June 4, 2026, at ICE Krakรณw. Whether youโ€™re a developer, designer, writer, tester, pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. author, translator, marketer, or simply interested in Playground, there will be several ways to get involved.

Read on to find out how to prepare and what to expect at the WordPress Playground table.

Important Times

All times are in Central European Summer Time (CEST).

  • 08:30 โ€“ Registration
  • 09:15 โ€“ Opening and welcome
  • 10:00 โ€“ Contributing to WordPress
  • 12:15 โ€“ Group photo
  • 12:30 โ€“ Lunch
  • 14:00 โ€“ Contributing to WordPress
  • 16:30 โ€“ Team summaries and wrap-up

Remote contributors are welcome to join via the #playground and #contributor-day channels on WordPress SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/.

Meet the Table Leads

Playground team will have three team reps during the event, who will be leading the WordPress Playground table:

In-person table leads

Berislav Grgicak (@berislavgrgicak) will also be supporting the Playground table.

Part of the team will be participating remotely throughout the day, answering questions and supporting contributors in the #playground Slack channel.

WordPress Playground Table Focus

There are many ways to contribute to WordPress Playground depending on your background and comfort level.

  • Testing and feedback: Help test Playground features, including PR Previews V3, the new SQLite integration, and tools powered by Playground such as My WordPress.
  • WordPress Studio: Help test the new version of WordPress Studio on Linux and provide feedback on the local development experience.
  • Blueprints: Help plugin developers create their own Blueprints and enable the Live Preview button for their plugins.
  • Documentation: Improve existing docs, suggest new guides, or help make Playground easier to understand for new users and contributors.
  • Translations: Playground documentation is currently available in several languages, and translation contributions are always welcome.
  • Good first issues: New contributors can start with issues labeled Good First Issue.
  • Design, marketing, and product feedback: You donโ€™t need to write code to contribute. Designers, marketers, writers, educators, and site builders can help review the UIUI UI is an acronym for User Interface - the layout of the page the user interacts with. Think โ€˜how are they doing thatโ€™ and less about what they are doing., improve onboarding, suggest new features, and identify opportunities for clearer communication.

A good quote from Jonathan Bossenger(@psykro):

Remember: itโ€™s โ€œContributor Day,โ€ not โ€œContribution Day.โ€ The goal is to find meaningful ways to contribute and help move the project forward. Some work may continue after the event, and thatโ€™s expected. Open sourceOpen Source Open Source denotes software for which the original source code is made freely available and may be redistributed and modified. Open Source **must be** delivered via a licensing model, see GPL. is iterative.

If youโ€™re not sure where to start, talk to a table lead in person or ask in the #playground Slack channel.

What WordPress Playground Is Building

WordPress Playground lets you run WordPress directly in the browser, without setting up a traditional local server. It helps people test WordPress, try plugins and themes, create demos, review pull requests, and build new contribution workflows with less setup friction.

Some of the key areas contributors may work with include:

  • Playground web instance: The public browser-based Playground available at playground.wordpress.net.
  • Blueprints: JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. files that define how a Playground instance should be configured, including plugins, themes, content, settings, and setup steps.
  • PR Previews: Playground-powered previews that make it easier to test WordPress pull requests directly in the browser.
  • SQLite integration: Ongoing work around improving WordPress support for SQLite-powered environments.
  • Playground CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress.: A Node.js package that allows contributors and developers to run WordPress locally without Docker, MySQLMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com, or ApacheApache Apache is the most widely used web server software. Developed and maintained by Apache Software Foundation. Apache is an Open Source software available for free..
  • WordPress Studio integration: Local development workflows powered by Playground, including ongoing testing for Linux support.
  • Documentation and translations: Contributor-friendly docs that help more people understand and use Playground across different languages and workflows.

You can learn more in the Playground documentation and the dedicated Contributor Day page.

Prepare at Home

To make the most of Contributor Day, please prepare before arriving. Wi-Fi at large events can be unreliable, and many contributors may be cloning repositories or installing dependencies simultaneously.

For most Playground contribution tasks, you will need:

  • A laptop
  • A GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ account
  • A WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ account
  • GitGit Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git is easy to learn and has a tiny footprint with lightning fast performance. Most modern plugin and theme development is being done with this version control system. https://git-scm.com/ installed
  • Node.js and npm are installed
  • A local copy of the Playground repository

We recommend cloning the Playground repository before Contributor Day:

github.com/wordpress/playground

Docker and Composer are not required for most Playground Contributor Day tasks.

If you want to work with plugin demos or Live Preview support, it may also help to review the Playground Step Library before the event.

Helpful Resources

Looking Ahead

At WCEU Contributor Day, weโ€™ll focus on testing new features, improving documentation, supporting plugin developers with Blueprints and Live Preview, reviewing the user experience, and helping new contributors find their first meaningful contribution.

Contributors whose pull requests are merged may also be eligible for the WordPress Playground contributor badge on their WordPress.org profile. If youโ€™re interested in Playground but unsure where to begin, join us at the Playground table or ask in the #playground Slack channel.

Run PHP examples anywhere with WordPress Playground

WordPress Playground is expanding beyond full WordPress sites. A recent set of changes makes Playground a useful lightweight PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php runtime for documentation, tutorials, examples, and shareable demos.

The headline feature is the new <php-snippet> web component. It lets you embed runnable PHP examples in any web page with one script tag. Readers can edit the code, click Run, see the output in place, and experiment without installing PHP, configuring a server, or leaving the page.

This opens up a new way to teach WordPress and PHP APIs: examples can now be both readable and executable.

What changed

In an HTMLHTML HTML is an acronym for Hyper Text Markup Language. It is a markup language that is used in the development of web pages and websites. page, such as index.html, the new snippet embed is loaded from Playground:

<!-- index.html -->
<script
    type="module"
    src="https://playground.wordpress.net/php-code-snippet.js"
></script>

<php-snippet name="hello.php">
    <script type="application/x-php">
<?php
echo "Hello from PHP " . phpversion();
    </script>
</php-snippet>

This example is meant to be served as HTML, not evaluated as PHP on the server. If you paste the same markup into a .php template, the server-side PHP interpreter will see the raw <?php opening tag before the browser does. In that case, escape the opening tag as &lt;?php, load the snippet from an external file with src, or otherwise make sure the browser receives the PHP code as literal text.

The component renders an editable, syntax-highlighted code blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. with a Run button. When the reader clicks Run for the first time, Playground lazy-loads the runtime in a hidden iframeiframe iFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the userโ€™s browser., runs the PHP, and displays the output below the snippet.

Multiple snippets on the same page can share the same runtime. That means a tutorial can include several examples without downloading and booting a separate PHP environment for each one.

WordPress APIs work too

By default, snippets run inside a real WordPress environment. That means examples can call WordPress APIs, not only plain PHP functions.

For example, a documentation page can demonstrate the HTML APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways.:

<php-snippet name="lazy-load-images.php">
    <script type="application/x-php">
<?php
require '/wordpress/wp-load.php';

$html = '<article>
    <img src="hero.jpg" alt="Hero">
    <img src="inline.jpg" alt="Inline">
</article>';

$tags = new WP_HTML_Tag_Processor( $html );
while ( $tags->next_tag( 'img' ) ) {
    $tags->set_attribute( 'loading', 'lazy' );
    $tags->add_class( 'responsive' );
}

echo $tags->get_updated_html();
    </script>
</php-snippet>

That changes the role of code examples in WordPress documentation. Instead of asking readers to copy code into a local site, the example can run where they are already reading.

PHP-only mode

Not every example needs WordPress. For plain PHP language features, snippets can skip the WordPress download entirely:

<php-snippet name="just-php.php" wp="none">
    <script type="application/x-php">
<?php
echo "PHP " . phpversion() . "\n";
echo "WordPress installed: " .
    ( file_exists( '/wordpress/wp-includes/version.php' ) ? 'yes' : 'no' );
    </script>
</php-snippet>

Under the hood, this maps to the new Blueprint option:

{
    "preferredVersions": {
        "php": "latest",
        "wp": false
    }
}

When preferredVersions.wp is false, Playground boots PHP without downloading or installing WordPress. WordPress-specific Blueprint fields and steps are rejected, which keeps PHP-only examples explicit and predictable.

From demo page to documentation guide

The snippets work also moves beyond the original test/demo page. The PHP snippets guide is becoming the canonical reference for this feature, with live-rendered examples alongside copyable code.

That matters because the guide can show the feature in the same shape that authors will use it: basic embeds, precomputed output, selector-based snippets, WordPress snippets, pure PHP snippets, and option-by-option usage. The old demo page redirects readers to the guide, and the componentโ€™s attribution link points there too.

How to use it

Add the module script once on the page, then place each example in a <php-snippet> element. The recommended pattern is to put PHP inside a child <script type="application/x-php"> element when the surrounding document is HTML, MDX, or another format that will deliver the PHP code to the browser unchanged:

<php-snippet name="site-title.php">
    <script type="application/x-php">
<?php
require '/wordpress/wp-load.php';

update_option( 'blogname', 'Snippet Docs' );
echo get_bloginfo( 'name' );
    </script>
    <script type="text/expected-output">
Snippet Docs
    </script>
</php-snippet>

The application/x-php wrapper is useful because browsers ignore unknown script types. That lets authors include PHP strings containing HTML without escaping every < character.

For very short examples, inline text works too, but the PHP opening tag must be escaped:

<php-snippet name="sum.php" expected-output="42">
    &lt;?php echo 20 + 22;
</php-snippet>

Show output before Run

Use expected output when you want the result visible immediately. The placeholder is replaced by the real runtime output after the reader clicks Run.

<php-snippet name="precomputed.php">
    <script type="application/x-php">
<?php
echo "2 + 2 = " . ( 2 + 2 );
    </script>
    <script type="text/expected-output">
2 + 2 = 4
    </script>
</php-snippet>

For one-line output, use the expected-output attribute:

<php-snippet name="ready.php" expected-output="Ready">
    <script type="application/x-php">
<?php echo "Ready";
    </script>
</php-snippet>

Prepare examples with a Blueprint

Use blueprint when snippets need to be set up before the PHP code runs. The Blueprint can create files, add a mu-pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party., configure options, install plugins, or prepare sample content.

<script id="setup-blueprint" type="application/json">
{
    "steps": [
        {
            "step": "writeFile",
            "path": "/wordpress/wp-content/mu-plugins/helpers.php",
            "data": "<?php\nfunction docs_greet($name) { return 'Hello, ' . $name; }\n"
        }
    ]
}
</script>

<php-snippet name="greeting.php" blueprint="setup-blueprint">
    <script type="application/x-php">
<?php
require '/wordpress/wp-load.php';
echo docs_greet( 'Ada' );
    </script>
    <script type="text/expected-output">
Hello, Ada
    </script>
</php-snippet>

The blueprint attribute accepts an element id or a CSSCSS CSS is an acronym for cascading style sheets. This is what controls the design or look and feel of a site. selector. Use <script type="application/json"> for the Blueprint because its contents are treated as raw text, which keeps embedded PHP strings predictable.

Load PHP from another file

Use src when the PHP source should live in a separate file:

<php-snippet
    name="external-example.php"
    src="/snippets/external-example.php"
    expected-output="Loaded from an external file"
></php-snippet>

The URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.org resolves from the page that contains the snippet. If the PHP file is hosted on another origin, that server needs to allow cross-origin access. Use a Blueprint instead when the example needs support files, plugins, options, or other setup.

Pin versions or self-host the runtime

The default PHP version is 8.4, and the default WordPress version is latest. Use the php and wp attributes when the example depends on a specific version:

<php-snippet name="wp-version.php" php="8.4" wp="6.8">
    <script type="application/x-php">
<?php
require '/wordpress/wp-load.php';
echo get_bloginfo( 'version' );
    </script>
</php-snippet>

Most pages should use the hosted runtime from https://playground.wordpress.net. For local development, self-hosting, or pinned infrastructure, use playground-origin:

<php-snippet
    name="local-runtime.php"
    playground-origin="http://localhost:5400"
>
    <script type="application/x-php">
<?php
echo phpversion();
    </script>
</php-snippet>

More control for authors

The snippet component includes a few authoring tools that make it practical for real documentation:

  • Snippets are editable by default, so readers can change the code before running it.
  • Use Ctrl+Enter or Cmd+Enter to run a focused editable snippet from the keyboard.
  • Use readonly for runnable examples that should stay locked.
  • Use editable="false" as a compatibility alias for older examples that already use that pattern.
  • Use src to load PHP from a separate file.
  • Use expected-output or a <script type="text/expected-output"> child to show expected output before the reader clicks Run.
  • Use runnable="false" for syntax-highlighted examples that should not execute.
  • Use php and wp attributes to choose the PHP and WordPress versions for a snippet.
  • Use a shared Blueprint when multiple snippets need the same setup, such as a mu-plugin, site option, or file.

That last point is especially useful for longer tutorials. A page can define one JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. Blueprint and point several snippets at it. Playground boots the shared environment once, then each snippet runs against the same prepared runtime.

Runtime sharing and troubleshooting

The first run clicks on a page, loads the Playground client, creates a hidden iframe, boots PHP, and installs WordPress unless the snippet uses wp="none". Later runs reuse an existing runtime when playground-origin, php, wp, and the resolved Blueprint JSON all match.

That sharing keeps related snippets fast while still isolating examples that need a different PHP version, WordPress version, or setup Blueprint.

If a snippet does not render, check that the module script is loaded and that the browser supports custom elements. If Run never finishes, open DevTools and look for failed requests to remote.html, PHP .wasm files, WordPress zip files, Blueprint resources, or cross-origin src files.

Sites with a strict Content Security Policy need to allow the module script and hidden iframe from https://playground.wordpress.net, plus the runtime assets that Playground downloads. For stricter environments, self-host the snippet script and point playground-origin at that deployment.

Standalone PHP Playground

For full-page examples, Playground also includes a standalone PHP editor:

playground.wordpress.net/php-playground.html

It provides a side-by-side editor and preview with PHP and WordPress version selectors. The current code and version choices are encoded in the URL fragment, so examples can be shared as links or embedded in an iframe.

Use the standalone editor for a single larger demo. Use <php-snippet> when a post, handbook page, or tutorial needs several small runnable examples inline.

Why this matters

Runnable snippets make Playground useful in a new layer of the WordPress learning experience.

For doc authors, it reduces the gap between explanation and verification. A reader can run the example immediately.

For contributors, it creates a low-friction way to demonstrate WordPress APIs, PHP behavior, Blueprint setup steps, or bug reproductions.

For learners, it removes the setup barrier. They can try PHP and WordPress code in the browser first, then move to a local environment when they are ready.

This also broadens the meaning of Playground. It is still a full WordPress runtime in the browser, but it can now act as a small, embeddable PHP execution layer for the web.

Try it and share feedback

Try the snippet embed in a local HTML file, a documentation page, or a tutorial draft:

<script
    type="module"
    src="https://playground.wordpress.net/php-code-snippet.js"
></script>

For deeper examples, see the new PHP snippets guide in the Playground documentation:

PHP code snippets and embeds

Feedback is welcome in the #playground channel on Making WordPress Slack or in the WordPress Playground GitHub repository.

Playground Meetings Summaries – April 2026

This post covers the two Playground meetings held in April 2026. These are biweekly chats where contributors working on WordPress Playground gather to discuss updates, ongoing work, and plans for current and future releases. All are welcome to join.

Meeting โ€“ April 10, 2026

Facilitator: @fellyph

Announcements

  • WordCampWordCamp WordCamps are casual, locally-organized conferences covering everything related to WordPress. They're one of the places where the WordPress community comes together to teach one another what theyโ€™ve learned throughout the year and share the joy. Learn more. Asia 2026 was still running during the meeting. Talks were available via livestream. Thanks to @dilipmodhavadiya, @gauravbhai, @rimaprajapati, @shailmehta, and @arslan for joining the Contributor DayContributor Day Contributor Days are standalone days, frequently held before or after WordCamps but they can also happen at any time. They are events where people get together to work on various areas of https://make.wordpress.org/ There are many teams that people can participate in, each with a different focus. https://2017.us.wordcamp.org/contributor-day/ https://make.wordpress.org/support/handbook/getting-started/getting-started-at-a-contributor-day/ table.
  • @Bero published a new Agent Skill to help coding agents write Blueprints. Read the announcement: Teach your coding agent to write WordPress Playground Blueprints.
  • The Playground team has started the process to migrate the documentation to the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ Handbook format. Read the announcement: Migrating WordPress Playground Documentation to WordPress.org.
  • Two new contributors received the Playground badge, bringing the total to 55 contributors.
  • Since the last meeting, through April 10, 2026, 19 pull requests have been merged, with several others still under review.

Updates by area

PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php-WASM and Xdebug
Improvements to the PHP.wasm tooling, including AI-friendly build documentation and enhanced Xdebug support. Critical Node.js host crashes caused by closed streams were fixed. phpMyAdmin and Adminer were upgraded to support PHP 8.5 and now read SQLite settings directly from the WordPress configuration rather than from hardcoded paths.

CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress.
Recent CLI updates improved stability and configuration flexibility. An intermittent boot crash caused by directory mount conflicts was fixed, along with a false database error reported by users running an external MySQLMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com. Developers can now override WP_DEBUG settings using boolean or numeric values, and beta is now accepted as a valid WordPress version slug.

Playground website
Updates introduced a global site management APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways., enabled browser-native AI interaction through WebMCP, and clarified the error messages shown when a PR preview has expired.

Documentation
The migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. to the Handbook is underway. Current work focuses on making the existing Markdown content compatible with the WordPress Handbook format.

Internationalization
New translations landed for Japanese and Bengali.

SQLite
Database handling improvements prevent unexpected wp-config.php rewrites. The SQLite build scripts were also adapted to support the new monorepo structure.

Contributor updates

@fellyph โ€” Worked on recent posts and documentation, fixed the issue with the beta flag in the WordPress CLI, and submitted a fix for the preview button in the CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. AI pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. after spotting an issue while testing it. Also identified several documentation improvements while preparing the talk for WordCamp Asia.

@zieladam โ€” Finalizing site importing for WordPress, with plans to start integrating it shortly with other tools, including WP-CLI, Playground web, and possibly Playground CLI.

@bpayton โ€” Focused on Playground CLI performance improvements and reviewing pull requests. There is still a backlog of pull requests awaiting review.

@janjakes โ€” Preparing a new major version release of the SQLite integration, along with new features coming soon to Playground web.

@ydecat โ€” Cleaning up a package that is no longer needed, making room for new packages. Also working on improving the generation of package.json files across the project, with Xdebug usage examples next on the list and a possible exploration of bringing Xdebug to PHP.wasm Web.

Closing

A recurring piece of feedback heard at WordCamp Asia was about the recent stability and performance improvements in Playground. Thanks to everyone for keeping that work moving.

Meeting โ€“ April 24, 2026

Facilitator: @fellyph

Announcements

  • From April 10, 2026, through April 24, 2026, 35 pull requests were merged. The Playground badge now counts 57 community members.
  • The documentation migration to the Handbook is ongoing, with several important pull requests merged this week.
  • WordCamp Europe is coming up, and the team is looking for community members to co-lead the Playground table. If you are interested, send a direct message to @fellyph.

Updates by area

Website
The main activity focused on improving the site-management UIUI UI is an acronym for User Interface - the layout of the page the user interacts with. Think โ€˜how are they doing thatโ€™ and less about what they are doing., restoring browser compatibility, fixing a tricky Safari cross-origin bug, and re-enabling media processing that had been disabled as a workaround.

PHP-WASM
A highly active period for the PHP runtime layer. PHP 5.2 support was added, and several crash bugs were fixed (MEMFS symlinks, gzip/zlib, and TSRMLS_CC). The node-polyfills package was removed as a cleanup, and the bundler documentation was improved.

Blueprints
Activity was mostly documentation and internationalization. The Blueprint bundles reference page was updated, and Bengali and Gujarati translations of the Blueprint tutorial pages were added.

SQLite
One merged pull request shifted the scheduled refresh of the SQLite integration to a different time slot to avoid conflicts.

CLI
Several quality-of-life improvements landed: a new --workers flag, a fix for --no-auto-mount, a test parallelism pin to prevent flaky CI, restored missing mount specs, and Xdebug usage examples.

Documentation and i18n
Improvements continued on making the docs compatible with the WordPress Handbook, including updates around Asyncfy and the overlay property implemented by @bph. New translations landed in Gujarati, Portuguese, Spanish, and French.

Thanks to @shailmehta, @shimomura, @bรฉryl, @ydecat, and @nilovelez for the translation contributions.

Contributor updates

@fellyph โ€” Worked on the documentation migration to the Handbook, updating several pages in English and Portuguese. Reviewed pull requests for the Blueprints library and created an About page for My WordPress in Portuguese.

@zieladam โ€” No major updates this week, except for a new SQLite extension that treats Markdown files as tables. It could make a nice tool for editing Markdown with WordPress.

@mosescursor โ€” Recently focused on organizing WordCamp Asia and contributing to other teams. Now available to contribute to Playground again.

@janjakes โ€” On the SQLite side, tagged 3.0.0-rc.1 and 3.0.0-rc.2 with the following improvements:

  • Remove legacy SQLite driver (#358)
  • Improve concurrent database access (#361)
  • Support MySQL BINARY operator (#369)
  • Add support for AUTO_INCREMENT value management (#367)
  • Add support for DELETE with LIMIT and ORDER BY (#365)
  • Add Query Monitor 4.0 support (#357)
  • Translate MySQL CONVERT() expressions to SQLite (#356)

@bpayton โ€” Exploring a Wasm-based kernel to run Playground in the browser on top of traditional server software, such as nginxNGINX NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. In addition to its HTTP server capabilities, NGINX can also function as a proxy server for email (IMAP, POP3, and SMTP) and a reverse proxy and load balancer for HTTP, TCP, and UDP servers. https://www.nginx.com/., PHP-FPM, and MariaDB. Early results are promising. The goal is to have a query parameter that switches playground.wordpress.net between the current PHP-WASM runtime and the kernel-based runtime. More to share next time.


The next Playground chat will be announced in the #playground SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/ channel. All are welcome.

X-post: WordPress Core Dev Environment Toolkit: A Faster Path to Your First Core Contribution

X-post from +make.wordpress.org/core: WordPress Core Dev Environment Toolkit: A Faster Path to Your First Core Contribution

Migrating WordPress Playground Documentation to WordPress.org

At the beginning of 2026, the Playground team received a community request to migrate the official WordPress Playground documentation to the standard Handbook format on WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/.

The current documentation uses Docusaurus, which offers several features that speed up our work, including a built-in internationalization system, component libraries, reusable components with MDX, and a configuration file for integrating external features like Kapa.ai.

Moving to the official handbook It establishes Playground as a coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. WordPress project and provides a familiar documentation structure for our users. However, migrating from our current setup presents a few unique technical challenges. Here is an update on our progress, the challenges we are navigating, and our roadmap for the migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies..

The Challenge: Docusaurus vs. Handbook Formatting

To migrate to the WordPress.org Handbook format, we need to adapt our existing Docusaurus-specific components to work within the Handbookโ€™s script rendering. Similar to the GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses โ€˜blocksโ€™ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ project, we have created a JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. file mapping all pages to be included in the new handbook.

We are taking two approaches to handle the markdown conversion:

  1. Duplication of the current format to a Handbook-friendly format.
  2. Migrating essential components to alternatives that can be natively rendered by the Handbook scripts.

The selected approach was the second, using alternative components compatible with both platforms, which avoids duplicating work and keeps both versions online.

Progress Report: What Weโ€™ve Completed & Whatโ€™s in Progress

  • Anchor Links & IDs (Done): We have removed all hardcoded IDs used for internal page linking, as the Handbook handles this natively.
  • Asset Loading (Done): Docusaurus uses dynamic pointing for asset folders (like images). We have updated our approach to point directly to the raw files hosted on GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/, ensuring images render correctly without issue.
  • MDX Fragments (In Review): Playground docs heavily utilize MDX fragments (reusable snippets of code/text used across multiple pages). We have created a PR to adapt these fragments for an inline structure, and it is currently under review.
  • Callout Components (To Do): Docusaurus components for Warnings, Info, and Tips currently do not render in the Handbook. We need to create alternatives for these to ensure important points of attention are still highlighted for the user.
  • SEO & Open Graph Data (To Do): We need to double-check our Open Graph data (logos, descriptions, titles). Currently, every page has a headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitorโ€™s opinion about your content and you/ your organizationโ€™s brand. It may also look different on different screen sizes. defining its title and summary. We need to collaborate with the Handbook team to ensure these are being parsed dynamically for optimal SEO.

The Migration Roadmap

To ensure a smooth transition, we have broken the migration into three distinct phases:

Phase 1: The English Migration

Our immediate priority is to get the core English documentation published in the WordPress.org Handbook. During this time, both documents will be live; the English version will, in the meantime, redirect to the Handbook once the migration is complete.

Phase 2: Internationalization (i18n)

Playground boasts a highly localized user base, with over 220 pages translated into languages including Portuguese, Japanese, Spanish, French, Gujarati, Bengali, and Tagalog.

Because Handbook support for translations is still evolving, we have established a fallback strategy:

  • We will define a set of pages eligible for translation and publishing in the new handbook, something similar to what we have in the current docs. At a minimum, the first โ€œblockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.โ€ of introductory pages must be translated; otherwise, the user will be redirected to the English version, the current behavior with Docusaurus.
  • Fallback Plan: Until Phase 2 is complete, we will keep the Docusaurus site live strictly as a fallback for international users. English traffic will be redirected to WordPress.org, while translated content will remain on Docusaurus until it can be safely migrated.

At WordCampWordCamp WordCamps are casual, locally-organized conferences covering everything related to WordPress. They're one of the places where the WordPress community comes together to teach one another what theyโ€™ve learned throughout the year and share the joy. Learn more. Asia, @fellyph will be present and will lead the Contributor table for WordPress. One of the themes of the contributor dayContributor Day Contributor Days are standalone days, frequently held before or after WordCamps but they can also happen at any time. They are events where people get together to work on various areas of https://make.wordpress.org/ There are many teams that people can participate in, each with a different focus. https://2017.us.wordcamp.org/contributor-day/ https://make.wordpress.org/support/handbook/getting-started/getting-started-at-a-contributor-day/ for Playground will be the migration of the docs and the discussion of a solution for internationalization.

Phase 3: The โ€œAsk AIโ€ Feature

Late last year, we introduced the โ€œAsk AIโ€ button (powered by Kapa.ai) to help users find immediate answers to specific questions and blueprint rendering errors. This feature has been incredibly useful, but migrating it requires careful consideration.

  • Testing: The Kapa.ai team proposed to use the solution on the .org account. But this should be discussed with the Docs team to move forward.
  • Privacy Considerations: Because user queries are stored in the Kapa.ai dashboard, we need to have a detailed discussion with the documentation team regarding privacy policies before implementing this on the official .org domain.

Next Steps

The playground team will continue working on unblocking Phase 1 by resolving the remaining component and SEO metadata issues. We will also be reaching out to the Handbook and Docs teams to clarify our i18n redirect rules and the future of the Ask AI implementation.

Teach your coding agent to write WordPress Playground Blueprints

The new blueprint agent skill teaches your coding agent the Playground Blueprint schema, which defines valid property names, resource types, and step sequencing. No more pluginZipFile instead of pluginData. No more runPHP steps missing require '/wordpress/wp-load.php'.

Install it once, and your agent generates valid Blueprint JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. with a high success rate, and the best part of it all with natural language. That is perfect for testing new ideas, finding edge cases in your Plugins and Themes, and creating demos from your projects.

What the blueprint skill does

The skill is a structured Markdown reference that your coding agent loads into its context. It covers:

  • Every top-level property: landingPage, preferredVersions, features, steps, shorthands (login, plugins, siteOptions, constants)
  • All resource types: wordpress.org/plugins, wordpress.org/themes, url, git:directory, literal:directory, bundled
  • Step reference: installPlugin, writeFile, writeFiles, runPHP, wp-cli, runSql, and more
  • Common mistakes: a table of pitfalls the agent checks against before generating output
  • Blueprint bundles: self-contained packages with bundled resources

The agent reads this reference before writing any Blueprint. Instead of guessing property names, it follows the documented schema.

How to install the skill

For a quick install, use the npx skills CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress. to add the blueprint skill to your project:

npx skills add wordpress/agent-skills --skill blueprint

Or install manually by cloning the agent-skills repository and running the build script:

git clone https://github.com/WordPress/agent-skills.git
cd agent-skills
node shared/scripts/skillpack-build.mjs --clean
node shared/scripts/skillpack-install.mjs --dest=../your-wp-project --targets=claude,gemini,codex,cursor,vscode

The skill works with Claude Code, Gemini CLI, GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ Copilot, Cursor, and Codex.

Five examples

Each example below shows a prompt you give your agent and the Blueprint it produces. These are real-world scenarios where the blueprint skill prevents common errors.

1. Quick development environment

Prompt:

Create a Blueprint that sets up a development environment with
debug mode, the Developer plugin, and landing on the admin dashboard.

Generated Blueprint:

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "landingPage": "/wp-admin/",
  "preferredVersions": { "php": "8.3", "wp": "latest" },
  "features": { "networking": true },
  "constants": {
    "WP_DEBUG": true,
    "WP_DEBUG_LOG": true
  },
  "login": true,
  "plugins": ["developer"],
  "steps": []
}

Notice how the agent uses the constants shorthand instead of a defineWpConfigConsts step, and login: true instead of a separate login step. The skill teaches agents to pick shorthands for simple cases and explicit steps when order matters.

WordPress Admin panel showing the Developer plugin enabled via blueprint

2. PluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party. from a GitHub branch

Prompt:

Write a Blueprint that installs my plugin from the feature/checkout-v2
branch on GitHub and activates it.

Generated Blueprint:

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "landingPage": "/wp-admin/plugins.php",
  "preferredVersions": { "php": "8.3", "wp": "latest" },
  "steps": [
    { "step": "login" },
    {
      "step": "installPlugin",
      "pluginData": {
        "resource": "git:directory",
        "url": "https://github.com/your-org/your-plugin",
        "ref": "feature/checkout-v2",
        "refType": "branch",
        "path": "/"
      },
      "options": { "activate": true }
    }
  ]
}

Without the skill, agents commonly omit refType, which causes git:directory to fail for branch names. The skillโ€™s common mistakes table flags this explicitly: โ€œOmitting refType with branch/tag ref โ€” required; only HEAD works without it.โ€

3. WooCommerce store with sample products

Prompt:

Create a Blueprint for a WooCommerce store with 5 sample products
across 2 categories, running on PHP 8.2.

Generated Blueprint:

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "landingPage": "/shop/",
  "preferredVersions": { "php": "8.2", "wp": "latest" },
  "features": { "networking": true },
  "steps": [
    { "step": "login" },
    {
      "step": "installPlugin",
      "pluginData": { "resource": "wordpress.org/plugins", "slug": "woocommerce" },
      "options": { "activate": true }
    },
    {
      "step": "runPHP",
      "code": "<?php\nrequire '/wordpress/wp-load.php';\n\n// Create categories\n$cat_clothing = wp_insert_term('Clothing', 'product_cat');\n$cat_accessories = wp_insert_term('Accessories', 'product_cat');\n\n$products = [\n  ['T-Shirt', 29.99, $cat_clothing['term_id']],\n  ['Hoodie', 59.99, $cat_clothing['term_id']],\n  ['Jeans', 49.99, $cat_clothing['term_id']],\n  ['Watch', 89.99, $cat_accessories['term_id']],\n  ['Backpack', 39.99, $cat_accessories['term_id']]\n];\n\nforeach ($products as [$title, $price, $cat_id]) {\n  $post_id = wp_insert_post([\n    'post_title' => $title,\n    'post_type' => 'product',\n    'post_status' => 'publish'\n  ]);\n  update_post_meta($post_id, '_regular_price', $price);\n  update_post_meta($post_id, '_price', $price);\n  wp_set_object_terms($post_id, [$cat_id], 'product_cat');\n}\n"
    }
  ]
}

The skill ensures the agent includes require '/wordpress/wp-load.php' at the top of every runPHP step. Without this line, all WordPress functions fail silently โ€” a mistake agents make frequently without the skill reference.

WordPress Playground Loading a store with 5 products in a woo store.

4. Inline mu-plugin for custom behavior

Prompt:

Write a Blueprint that disables the admin bar and adds a custom
dashboard widget showing the server's PHP version.

Generated Blueprint:

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "landingPage": "/wp-admin/",
  "preferredVersions": { "php": "8.3", "wp": "latest" },
  "steps": [
    { "step": "login" },
    {
      "step": "writeFile",
      "path": "/wordpress/wp-content/mu-plugins/custom-dashboard.php",
      "data": "<?php\nadd_filter('show_admin_bar', '__return_false');\n\nadd_action('wp_dashboard_setup', function() {\n  wp_add_dashboard_widget(\n    'php_version_widget',\n    'PHP Version',\n    function() {\n      echo '<p>Running PHP ' . phpversion() . '</p>';\n    }\n  );\n});"
    }
  ]
}

The agent uses writeFile to create a mu-plugin, which loads automatically without activation. The skill explicitly documents this pattern and warns agents not to add require wp-load.php inside mu-plugin code (that line is only needed in runPHP steps).

5. Blueprint bundle with a custom plugin

Prompt:

Create a Blueprint bundle that installs a custom analytics plugin
from a local zip file.

Generated bundle structure:

analytics-bundle/
โ”œโ”€โ”€ blueprint.json
โ””โ”€โ”€ analytics-plugin.zip

blueprint.json:

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "landingPage": "/wp-admin/plugins.php",
  "preferredVersions": { "php": "8.3", "wp": "latest" },
  "steps": [
    { "step": "login" },
    {
      "step": "installPlugin",
      "pluginData": {
        "resource": "bundled",
        "path": "/analytics-plugin.zip"
      },
      "options": { "activate": true }
    }
  ]
}

Run it locally:

npx @wp-playground/cli server --blueprint=./analytics-bundle/ --blueprint-may-read-adjacent-files

The --blueprint-may-read-adjacent-files flag is required for directory bundles. Without it, any bundled resource reference fails with a โ€œFile not foundโ€ error. The skill documents this gotcha, so agents include the flag automatically.

How the blueprint skill fits with other tools

The blueprint skill works alongside two other Playground tools for AI agents:

ToolWhat it doesWhen to use it
Blueprint skillGenerates valid Blueprint JSONWhen you need a Blueprint file for sharing, version control, or CI
wp-playground skillRuns CLI commands, manages servers, debugs instancesWhen you need a running Playground instance with live interaction
MCP serverConnects agents directly to a browser PlaygroundWhen you need real-time PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php execution and file manipulation

Use the blueprint skill when you want a portable, reproducible configuration. Use the wp-playground skill when you need a running server. Combine them: generate a Blueprint with the blueprint skill, then launch it with the wp-playground skillโ€™s CLI commands.

Test your Blueprints

Inline URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.org (quick test)

Minify the Blueprint JSON and append it to the Playground URL:

https://playground.wordpress.net/#{"preferredVersions":{"php":"8.3","wp":"latest"},"steps":[{"step":"login"}]}

Local CLI (full test)

# Start a server with your Blueprint
npx @wp-playground/cli server --blueprint=./blueprint.json

# Headless validation (runs and exits)
npx @wp-playground/cli run-blueprint --blueprint=./blueprint.json

Get started

Install the blueprint skill in your project:

npx skills add wordpress/agent-skills --skill blueprint

Then ask your agent to write a Blueprint. Describe what you need: plugins, themes, content, configuration, and the agent produces valid JSON that runs on the first try.

Share what you build in the #playground channel on Making WordPress Slack or open an issue on GitHub.

#agent-skills, #ai

Playground Meetings Summaries โ€“ March 2026

This post summarizes the WordPress Playground teamโ€™s biweekly meetings held on March 13 and March 27, 2026. These meetings are open to all contributors and community members.

March 13, 2026

The meeting was facilitated by @fellyph.

Announcements

my.wordpress.net โ€” The team published an official release post for my.wordpress.net and has been collecting community feedback.

Two new blog posts are available on the Playground Blog:

WordPress 7.0 betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. 5 is available for testing on Playground. Contributors are encouraged to test their plugins and themes ahead of the next WordPress release at playground.wordpress.net/?wp=beta.

MCP Server โ€” WordPress Playground now has an MCP server. Usage instructions are available on the npm page. A dedicated blog post is in progress.

WASM I/O Conference โ€” Part of the Playground team will be presenting at the WASM I/O conference in Barcelona, March 19โ€“20.

Updates from contributors

Website โ€” Received reliability improvements, including updates to file handling and session persistence, plus integration of the new MCP server.

PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php-WASM โ€” Updated with performance improvements, the new binary optimization strategy, and memory usage fixes.

Docs โ€” Two new guides are now available:

Both guides received translations in Portuguese, Spanish, and French.

CLICLI Command Line Interface. Terminal (Bash) in Mac, Command Prompt in Windows, or WP-CLI for WordPress. โ€” Updates focus on performance and developer experience. A native php command now enables direct script execution and WP-CLIWP-CLI WP-CLI is the Command Line Interface for WordPress, used to do administrative and development tasks in a programmatic way. The project page is http://wp-cli.org/ https://make.wordpress.org/cli/-style workflows. The testing suite now uses local PHARs to remove external download dependencies.

@fellyph โ€” Created the two new guides above, drafted the MCP server blog post, drafted a Vitest guide, and worked on a design proposal for the new Wizard page for my.wordpress.net.


March 27, 2026

The meeting was facilitated by @fellyph.

Announcements

MCP Server post published โ€” The post Connect AI coding agents to WordPress Playground with MCP is now live on the Playground Blog. A video walkthrough is also available.

25 pull requests were merged since the last meeting.

my.wordpress.net โ€” Received significant attention from the media and community. The team thanks everyone who shared feedback. The modal design has been updated, removing the purple background. iOSiOS The operating system used on iPhones and iPads. experience improvements are still under investigation, with thanks to @ashfame and @zaerl for looking into the reported issues.

Website PRs

Improvements focus on resilience and edge-case compatibility: better handling of download failures (#3348), fixes for Playground breaking inside in-app browsers like LinkedIn (#3387, #3392), more flexible blueprint ZIP uploads (#3223), My WordPress branding updates (#3390), and added WebKit and Playwright E2E tests (#3379, #3405).

CLI PRs

The CLI now automatically restarts with JSPI support enabled, without manual Node flags (#3281), and uses a faster built-in method for process checking during temp directory cleanup (#3395). Additional improvements include module-boundary linting (#3410), a new Playwright-based benchmarking suite for site editor startup and interaction times (#3408), and silencing harmless streaming errors caused by client disconnects (#3397).

Docs PRs

GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the โ€˜pull requestโ€™ where code changes done in branches by contributors can be reviewed and discussed before being merged by the repository owner. https://github.com/ Releases are now auto-generated after every npm publish (#3429, #3430). The Claude agentโ€™s permissions have been hardened: rm commands are now blocked (#3398), and allow/deny lists have been updated to prevent destructive actions while permitting read-only git operations (#3373). Dependabotโ€™s config was also fixed to properly exclude directories (#3426).

SQLite

  • #3428 โ€” Updated the SQLite database path from .ht.sqlite to .ht.sqlite.php to match the latest SQLite integration pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party..
  • #3435 โ€” Reverted that path update.

PHP-WASM

  • #3417 โ€” Fixed Redis extension corruption in WASM32 caused by a variadic ABI mismatch.
  • #3399 โ€” Fixed a race condition in proc_open where pipe writes could crash after streams were already closed.

Updates from contributors

@fellyph โ€” Published the E2E Testing with Playwright guide, published the MCP server post, drafted the Vitest guide, and started writing about recent architecture changes.

@brandonpayton and @ashfame โ€” Exploring performance improvements for the Playground CLI, including HTTPHTTP HTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands./2 and static file serving optimizations. @brandonpayton is also focusing on PR reviews.

@adamzielinski โ€” Working on a WordPress site migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. plugin. A working Blueprint with a demo is available. This will be a useful integration for working on existing sites directly within Playground.

@bero โ€” Focused on enabling AI agents to use Playground. A Blueprint skill is now available, and agents will soon be able to interact with the Playground website via playgroundSites methods from DevTools. Experimental WebMCP support is also being added. Next steps include more MCP tools and skills to improve the agent experience.

@janjakes โ€” Back to SQLite work, focusing on monorepo setup, automation, and the upcoming v3 release.

Open floor

@fellyph asked whether contributors prefer a monthly report or a per-meeting report for the Playground newsletter, noting concern about email frequency for subscribers.


The next meeting will be held on April 10, 2026. All are welcome.

Connect AI coding agents to WordPress Playground with MCP

What if your coding agent could read WordPress files, execute PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php, and manage sites directly in your browser? The @wp-playground/mcp package bridges AI coding agents and a browser-based Playground instance through the Model Context Protocol (MCP). Run one command to connect. No configuration needed in Playground.

How it works

The MCP server runs as a local Node.js process using stdio transport. Your AI client communicates with it directly, and the server forwards commands to a Playground instance running in your browser through a WebSocket connection.

AI Client (stdio) --> MCP Server (Node.js) --> WebSocket --> Browser (Playground)

When you open Playground in your browser, a WebSocket links the browser tab to the MCP server. The server assigns a random local port at startup and passes it to the browser through the URLURL A specific web address of a website or web page on the Internet, such as a websiteโ€™s URL www.wordpress.orgโ€™s mcp-port parameter. The server translates your agentโ€™s tool calls into direct Playground actions: reading files, executing PHP, and navigating pages.

The connection stays local to your machine. Origin restrictions and token-based authentication at startup prevent unauthorized access from other sites and browser extensions.

Set up the MCP server

Claude Code

claude mcp add --transport stdio --scope user wordpress-playground -- npx -y @wp-playground/mcp

The --scope user flag makes the server available across all your projects. Use --scope local to restrict it to the current project only.

Codex

Codex supports stdio MCP servers through the codex mcp command. Add WordPress Playground as a user-level MCP server with:

codex mcp add wordpress-playground -- npx -y @wp-playground/mcp

Then ask Codex to open the Playground site. The MCP server provides the exact Playground URL when it connects, including the local mcp-port parameter needed to link the browser tab to the MCP server.

JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. configuration

You can also configure the server manually. Add this to your .mcp.json (Claude Code / Claude Desktop):

{
    "mcpServers": {
        "wordpress-playground": {
            "type": "stdio",
            "command": "npx",
            "args": ["-y", "@wp-playground/mcp"]
        }
    }
}

After setup, open Playground in your browser. The agent provides the exact URL when it connects.

Three practical workflows

Once connected, your agent manages WordPress through natural language.

1. Install, test and build a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party.

Ask your agent to install and verify a plugin without touching the WordPress admin:

โ€œInstall the Classic Editor plugin on my Playground site and confirm it deactivates the blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor.โ€

The agent uses playground_execute_php to call wp_remote_get, download the plugin zip, and extract it to wp-content/plugins/. It activates the plugin with activate_plugin(), then fires playground_request against the post editor URL to confirm the classic interface loads. You see each step in your agentโ€™s output.

2. Debug site options with PHP

Need to check what a plugin stored in the database? Skip the admin UIUI UI is an acronym for User Interface - the layout of the page the user interacts with. Think โ€˜how are they doing thatโ€™ and less about what they are doing. and query wp_options directly:

โ€œShow me all autoloaded options that contain โ€˜woocommerceโ€™ in the option name.โ€

The agent runs playground_execute_php with a short script:

global $wpdb;
$results = $wpdb->get_results(
    "SELECT option_name, option_value FROM $wpdb->options
     WHERE option_name LIKE '%woocommerce%'"
);
print_r($results);

Playground uses SQLite instead of MySQLMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com, so avoid MySQL-specific column values in your queries. The $wpdb abstraction handles the translation, but filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. conditions like autoload = 'yes' may not return results as expected.

The output appears in your conversation. No phpMyAdmin or database client needed.

3. Scaffold theme files

Building a child themeChild theme A Child Theme is a customized theme based upon a Parent Theme. Itโ€™s considered best practice to create a child theme if you want to modify the CSS of your theme. https://developer.wordpress.org/themes/advanced-topics/child-themes/ from scratch involves creating directories, writing template files, and registering the theme. Let the agent handle the boilerplate:

โ€œCreate a child theme of Twenty Twenty-Five called โ€˜Studio Childโ€™ with a custom headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitorโ€™s opinion about your content and you/ your organizationโ€™s brand. It may also look different on different screen sizes. template part and a front-page template.โ€

The agent calls playground_mkdir to create the theme directory, playground_write_file to generate style.css, theme.json, and template files, then playground_execute_php to verify the theme appears in the admin. If a file contains an error, the agent reads it back with playground_read_file and corrects the mistake in the next step.

Available tools

The MCP server exposes these tools to your agent:

  • Site management: playground_get_website_url, playground_list_sites, playground_open_site, playground_rename_site, playground_save_site
  • Code execution: playground_execute_php, playground_request
  • Navigation: playground_navigate, playground_get_current_url, playground_get_site_info
  • Filesystem: playground_read_file, playground_write_file, playground_list_files, playground_mkdir, playground_delete_file, playground_delete_directory, playground_file_exists

Share your feedback

Try the @wp-playground/mcp package and tell us what you build. Share your experience in the #playground channel on Making WordPress Slack or open an issue on GitHub to suggest new tools.

Props to @berislavgrgicak for building the MCP server and reviewing the post.

#ai #playground

+make.wordpress.org/core/
+make.wordpress.org/ai/

How WordPress Playground cut PHP.wasm binary sizes by 122 MB

Every PHPPHP PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. https://www.php.net/manual/en/index.php version WordPress Playground supports ships as a WebAssembly binary. Across all builds and versions, those binaries totaled 888 MB. Two compiler flag changes reduced that to 766 MB, a 122 MB saving (13.7%) without removing a single feature.

What changed?

Playground compiles PHP to WebAssembly using Emscripten. The compiler flag MAIN_MODULE controls which symbols get exported for dynamic linking. Previously, Playground used MAIN_MODULE=1, which exports everything, including thousands of symbols that no extension ever calls.

Switching to MAIN_MODULE=2 tells Emscripten to export only the symbols extensions actually use, similar to tree-shaking in JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a userโ€™s browser. https://www.javascript.com bundlers. The compiler drops everything else.

The challenge: keeping extensions alive

Flipping a compiler flag sounds simple, but MAIN_MODULE=2 aggressively eliminates code that the main module considers โ€œdead.โ€ Playground loads extensions like Intl, Xdebug, Memcached, and Redis as dynamic .so modules, and those modules depend on specific symbols from the main PHP binary. Remove the wrong symbol, and the extension crashes on load.

PR #3244 first mapped the approach: scanning each compiled extension wasm-dis to extract which symbols it references. The build system then feeds those symbols back to the linker as explicit exports, keeping every extension working while eliminating thousands of unused ones.

Three extensions required direct fixes. Xdebug required a __c_longjmp WebAssembly tag injection. Memcached called recv and setsockopt through libmemcached internals, so the build added C shim wrappers. Intl alone needed over 5,000 export symbols, including libc++ functions.

Why two build types?

PHP is synchronous. Browsers are not. Playground solves this mismatch with two compilation strategies, and each one produces a separate set of binaries:

  • Asyncify transforms compiled code at build time so it can pause and resume execution. This approach works in every browser but adds overhead to the binary. Learn more about Asyncify.
  • JSPI (JavaScript Promise Integration) takes a different approach. It lets WebAssembly call async browser APIs directly, without transforming the compiled code. JSPI produces smaller binaries but currently requires V8-based browsers (Chrome, Edge). Learn more about JSPI.

Playground ships both variants for each PHP version, so the MAIN_MODULE=2 optimization is applied to both:

  • PR #3332 targeted JSPI builds.
  • PR #3335 completed the same change for Asyncify builds.

The numbers

MetricBeforeAfterSaved
Total binary size888 MB766 MB122 MB (13.7%)
.wasm files680 MB571 MB109 MB (16%)
JS glue code22.7 MB8.2 MB14.5 MB (63%)

Per-version .wasm sizes dropped consistently across all supported PHP versions:

PHP VersionBefore (avg)After (avg)Reduction
7.4~20 MB~17 MB17-19%
8.2~25 MB~21 MB15-17%
8.4~27 MB~23 MB14-16%
8.5~28 MB~24 MB14-15%

The two PRs combined removed 554,793 lines of JavaScript glue code across all builds.

Why smaller binaries matter

Faster downloads and CI. 122 MB fewer bytes to transfer during repository clones, CI pipelines, and deployments. That adds up across all contributors and all automated runs.

Faster WebAssembly instantiation. Smaller .wasm files compile faster in the browser. Compilation cost scales roughly with binary size, so 16% smaller binaries translate directly to faster WordPress startup.

Lower memory usage. Fewer exported symbols produce a smaller function table. The runtime allocates less memory before PHP even starts.

Faster JavaScript parsing. 63% less JS glue code means the browser parses and evaluates significantly less JavaScript before handing control to PHP.

What this means for php-wasm packages

Version-specific packages like @php-wasm/web-8.4 and @php-wasm/node-8.4 ship lighter binaries. No APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. changes โ€” this is purely a build optimization. Existing code that depends on these packages works unchanged.

What comes next

The next step is to benchmark the runtime impact by measuring instantiation time, time-to-first-PHP-response, and memory usage across builds. Those numbers will confirm how the smaller binaries translate to real-world performance gains.

Props to @mho22 for implementing both PRs and reviewing the post, @brandonpayton for reviewing, and @adamziel for the architectural direction. See the full details in PR #3332 and PR #3335.