<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Adam Zieliński on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Adam Zieliński</name>
  </author>
  <link href="https://web.dev/authors/adamzielinski/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/qNsFHO1nZ3FxmYd3PwWL.webp?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>WordPress core committer at Automattic</subtitle>
  
  
  <entry>
    <title>Build in-browser WordPress experiences with WordPress Playground and WebAssembly</title>
    <link href="https://web.dev/wordpress-playground/"/>
    <updated>2023-04-12T00:00:00Z</updated>
    <id>https://web.dev/wordpress-playground/</id>
    <content type="html" mode="escaped">&lt;p&gt;When you first see &lt;a href=&quot;http://wasm.wordpress.net/&quot; rel=&quot;noopener&quot;&gt;WordPress Playground&lt;/a&gt;, it seems
like an ordinary site–maybe except for the colorful background. It&#39;s anything
but. What you&#39;re actually looking at is an entire WordPress tech stack,
including PHP and a database, running directly in your browser.&lt;/p&gt;
&lt;p&gt;In this post, Adam Zieliński (lead of WordPress Playground) and Thomas Nattestad
(Product Manager for V8) explore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How WordPress Playground can help you as a WordPress developer.&lt;/li&gt;
&lt;li&gt;How it works under the hood.&lt;/li&gt;
&lt;li&gt;What it means for the future of WordPress.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-wordpress-without-installation,-embed-it-in-your-app,-and-even-control-it-with-javascript&quot;&gt;Use WordPress without installation, embed it in your app, and even control it with JavaScript &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#use-wordpress-without-installation,-embed-it-in-your-app,-and-even-control-it-with-javascript&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use and customize the WordPress embedded at
&lt;a href=&quot;http://playground.wordpress.net/&quot; rel=&quot;noopener&quot;&gt;playground.wordpress.net&lt;/a&gt; for free. There&#39;s
no cloud infrastructure and support to pay for, because that site lives entirely
in your browser–no one else can visit it. It&#39;s also temporary. As soon as you
refresh the page, it&#39;s gone. You can get as many of these sites as you want for
prototyping, trying out plugins, and quickly exploring ideas.&lt;/p&gt;
&lt;p&gt;You can even use them to test your code in different environments using the
built-in PHP and WordPress version switcher:&lt;/p&gt;
&lt;img alt=&quot;phpinfo page.&quot; decoding=&quot;async&quot; height=&quot;699&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/tVA8iwBfR187eUUwCLAL.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;WordPress Playground is an entirely new way of using WordPress. Its full power,
however, is only unlocked by including it in your app. The easy way is to embed
WordPress Playground in an &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; and configure it using the
&lt;a href=&quot;https://wordpress.github.io/wordpress-playground/pages/embedding-wordpress-playground-on-other-websites.html&quot; rel=&quot;noopener&quot;&gt;query parameters API&lt;/a&gt;.
That&#39;s what the &lt;a href=&quot;https://developer.wordpress.org/playground&quot; rel=&quot;noopener&quot;&gt;official showcase&lt;/a&gt;
does. When you select, for example, the
&lt;a href=&quot;https://wordpress.org/themes/pendant/&quot; rel=&quot;noopener&quot;&gt;Pendant theme&lt;/a&gt; and the
&lt;a href=&quot;https://wordpress.org/plugins/coblocks/&quot; rel=&quot;noopener&quot;&gt;Coblocks plugin&lt;/a&gt;, the embedded iframe
gets updated to point to
&lt;a href=&quot;https://playground.wordpress.net/?theme=pendant&amp;amp;plugin=coblocks&quot; rel=&quot;noopener&quot;&gt;https://playground.wordpress.net/?theme=pendant&amp;amp;plugin=coblocks&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;WordPress Playground showcase.&quot; decoding=&quot;async&quot; height=&quot;740&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/lPMfWljMKZbMluoN4971.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The iframe is an easy way of getting started, but it&#39;s also limited to just the
basic configuration option. If you need more than that, there is another, more
powerful API.&lt;/p&gt;
&lt;h3 id=&quot;the-wordpress-playground-javascript-client-enables-full-control-over-the-embedded-site&quot;&gt;The WordPress Playground JavaScript client enables full control over the embedded site &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#the-wordpress-playground-javascript-client-enables-full-control-over-the-embedded-site&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can control the entire WordPress site, including the filesystem and PHP,
using the full API available via the
&lt;a href=&quot;https://www.npmjs.com/package/@wp-playground/client&quot; rel=&quot;noopener&quot;&gt;@wp-playground/client&lt;/a&gt; npm
package. The following example shows to use it—check
&lt;a href=&quot;https://adamadam.blog/2023/04/12/interactive-intro-to-wordpress-playground-public-api/&quot; rel=&quot;noopener&quot;&gt;the interactive tutorial&lt;/a&gt;
for even more examples:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  connectPlayground&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  login&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  connectPlayground&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@wp-playground/client&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;connectPlayground&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wp&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// An iframe&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;loadRemote&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://playground.wordpress.net/remote.html&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isReady&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Login the user as admin and go to the post editor:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;admin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;goTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/wp-admin/post-new.php&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Run arbitrary PHP code:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;?php echo &quot;Hi!&quot;; ?&gt;&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Install a plugin:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; plugin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchZipFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;installPlugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; plugin&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;use-webassembly-php-even-without-wordpress&quot;&gt;Use WebAssembly PHP even without WordPress &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#use-webassembly-php-even-without-wordpress&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;WordPress Playground is not a monolith. WebAssembly PHP is released
independently from WordPress and you can use it separately as well. For the web,
you may use the &lt;a href=&quot;https://www.npmjs.com/package/@php-wasm/web&quot; rel=&quot;noopener&quot;&gt;@php-wasm/web&lt;/a&gt; npm
package optimized for a low bundle size, and in Node.js you can lean
on &lt;a href=&quot;https://www.npmjs.com/package/@php-wasm/node&quot; rel=&quot;noopener&quot;&gt;@php-wasm/node&lt;/a&gt; which provides
more PHP extensions. Adam used the former to add interactive PHP snippets
to &lt;a href=&quot;https://adamadam.blog/2023/02/16/how-to-modify-html-in-a-php-wordpress-plugin-using-the-new-tag-processor-api/&quot; rel=&quot;noopener&quot;&gt;this WP_HTML_Tag_Processor tutorial&lt;/a&gt;.
Here&#39;s a sneak peek of how to use it:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@php-wasm/web&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; php &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;8.0&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestHandler&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;documentRoot&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/www&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Create and run a script directly&lt;/span&gt;&lt;br /&gt;php&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mkdirTree&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/www&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;php&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/www/index.php&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;?php echo &quot;Hello &quot; . $_POST[&#39;name&#39;]; ?&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;php&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;scriptPath&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/www/index.php&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Or use the familiar HTTP concepts:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; php&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;relativeUrl&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/index.php&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;John&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Hello John&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;At this point you must be thinking–&lt;em&gt;how does that even work?&lt;/em&gt; Great question!
Let&#39;s dive into the internals and find out. Buckle up!&lt;/p&gt;
&lt;h2 id=&quot;under-the-hood,-theres-webassembly-php,-a-sql-translator,-and-an-in-browser-server&quot;&gt;Under the hood, there&#39;s WebAssembly PHP, a SQL translator, and an in-browser server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#under-the-hood,-theres-webassembly-php,-a-sql-translator,-and-an-in-browser-server&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;php-runs-as-a-webassembly-binary&quot;&gt;PHP runs as a WebAssembly binary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#php-runs-as-a-webassembly-binary&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;PHP doesn&#39;t just work in the browser out of the box. WordPress Playground
developed a
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/blob/0d451c33936a8db5b7a158fa8aad288c19370a7d/packages/php-wasm/compile/Dockerfile&quot; rel=&quot;noopener&quot;&gt;dedicated pipeline&lt;/a&gt;
to build &lt;a href=&quot;https://github.com/php/php-src&quot; rel=&quot;noopener&quot;&gt;the PHP interpreter&lt;/a&gt; to WebAssembly
using &lt;a href=&quot;https://emscripten.org/docs/porting/networking.html&quot; rel=&quot;noopener&quot;&gt;Emscripten&lt;/a&gt;.
Building vanilla PHP isn&#39;t overly complex–it only takes
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/blob/0d451c33936a8db5b7a158fa8aad288c19370a7d/packages/php-wasm/compile/build-assets/php7.1.patch#L8-L9&quot; rel=&quot;noopener&quot;&gt;adjusting a function signature here&lt;/a&gt;,
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/blob/0d451c33936a8db5b7a158fa8aad288c19370a7d/packages/php-wasm/compile/Dockerfile#L495&quot; rel=&quot;noopener&quot;&gt;forcing a config variable there&lt;/a&gt;,
and applying
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/tree/0d451c33936a8db5b7a158fa8aad288c19370a7d/packages/php-wasm/compile/build-assets&quot; rel=&quot;noopener&quot;&gt;a few small patches&lt;/a&gt;.
Here&#39;s how you can build it yourself:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone https://github.com/WordPress/wordpress-playground&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; wordpress-playground &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# Below, you can replace &quot;8.2&quot; with any other valid PHP version number.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; run recompile:php:web:8.2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;However, vanilla PHP builds aren&#39;t very useful in the browser. As a server
software, PHP doesn&#39;t have a JavaScript API to pass the request body, upload
files, or populate the &lt;code&gt;php://stdin&lt;/code&gt; stream. WordPress Playground had to build
one from scratch. The WebAssembly binary comes with a
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/blob/0d451c33936a8db5b7a158fa8aad288c19370a7d/packages/php-wasm/compile/build-assets/php_wasm.c&quot; rel=&quot;noopener&quot;&gt;dedicated PHP API module&lt;/a&gt;
written in C and a
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground/blob/da38192af57a95699d8731c855b82ac0222df61b/packages/php-wasm/common/src/lib/php.ts&quot; rel=&quot;noopener&quot;&gt;JavaScript PHP class&lt;/a&gt; that
exposes methods like &lt;code&gt;writeFile()&lt;/code&gt; or &lt;code&gt;run()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because every PHP version is just a static &lt;code&gt;.wasm&lt;/code&gt; file, the PHP version
switcher is actually pretty boring. It simply tells the browser to download, for
example, &lt;code&gt;php_7_3.wasm&lt;/code&gt; instead of, say, &lt;code&gt;php_8_2.wasm&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;database-is-supported-with-a-sql-translation-layer&quot;&gt;Database is supported with a SQL translation layer &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#database-is-supported-with-a-sql-translation-layer&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;WordPress requires MySQL. However, there isn&#39;t a WebAssembly version of MySQL
you could run in the browser. WordPress Playground therefore ships PHP with the
&lt;a href=&quot;https://www.php.net/manual/en/ref.pdo-sqlite.php&quot; rel=&quot;noopener&quot;&gt;native SQLite driver&lt;/a&gt; and
leans on SQLite.&lt;/p&gt;
&lt;p&gt;But how can WordPress run on a different database?&lt;/p&gt;
&lt;p&gt;Behind the scenes, the official
&lt;a href=&quot;https://github.com/WordPress/sqlite-database-integration&quot; rel=&quot;noopener&quot;&gt;SQLite Database Integration&lt;/a&gt;
plugin intercepts all MySQL queries and rewrites them in SQLite dialect. The 2.0
release ships
&lt;a href=&quot;https://github.com/WordPress/sqlite-database-integration/pull/9&quot; rel=&quot;noopener&quot;&gt;a new WordPress Playground-informed translation layer&lt;/a&gt;
that allows WordPress on SQLite to pass 99% of the WordPress unit test suite.&lt;/p&gt;
&lt;h3 id=&quot;the-web-server-lives-inside-the-browser&quot;&gt;The web server lives inside the browser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#the-web-server-lives-inside-the-browser&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In a regular WordPress, clicking on a link, say &lt;em&gt;Blog,&lt;/em&gt; would initiate an HTTP
request to the remote backend to fetch the &lt;code&gt;blog&lt;/code&gt; page. However, WordPress
Playground has no remote backend. It has a
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Service_Worker_API&quot; rel=&quot;noopener&quot;&gt;Service Worker&lt;/a&gt;
that intercepts all the outgoing requests and passes them to an in-browser PHP
instance running in a separate
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers&quot; rel=&quot;noopener&quot;&gt;Web Worker&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;Flow diagram starting with an iframe pointing at the resource wp-admin, calls to which are intercepted by the service worker, rendered in the worker thread, and ultimately translated to a WordPress response by the in-browser server.&quot; decoding=&quot;async&quot; height=&quot;675&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/8WbTDNrhLsU0El80frMBGE4eMCD3/EAYGDJ5cBGHFnQuFYjEw.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;networking-is-supported-through-websockets&quot;&gt;Networking is supported through WebSockets &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#networking-is-supported-through-websockets&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When it comes to networking, WebAssembly programs are limited to calling
JavaScript APIs. It is a safety feature, but also presents a challenge. How do
you support low-level, synchronous networking code used by PHP with the
high-level asynchronous APIs available in JavaScript?&lt;/p&gt;
&lt;p&gt;For WordPress Playground, the answer involves a WebSocket to TCP socket proxy,
&lt;a href=&quot;https://emscripten.org/docs/porting/asyncify.html&quot; rel=&quot;noopener&quot;&gt;Asyncify&lt;/a&gt;, and patching deep
PHP internals like &lt;code&gt;php_select&lt;/code&gt;. It&#39;s complex, but there&#39;s a reward. The
Node.js-targeted PHP build can request web APIs, install composer packages, and
even connect to a MySQL server.&lt;/p&gt;
&lt;h2 id=&quot;wordpress-can-be-used-in-even-more-places-than-the-browser&quot;&gt;WordPress can be used in even more places than the browser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#wordpress-can-be-used-in-even-more-places-than-the-browser&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since WordPress can now run on WebAssembly, you could also run it in a Node.js
server—it&#39;s the same V8 engine! Of course with StackBlitz you can also run
Node.js directly in the browser, meaning that you could run WordPress and PHP
compiled to WebAssembly, executing in Node.js, which is also compiled to
WebAssembly running
&lt;a href=&quot;https://stackblitz.com/edit/node-zt3hpi?file=todo-list%2Fsrc%2Fedit.js&quot; rel=&quot;noopener&quot;&gt;in the browser&lt;/a&gt;.
WebAssembly is also exploding in popularity in the serverless space, and in the
future this could run on that infrastructure as well.&lt;/p&gt;
&lt;h2 id=&quot;the-future-may-bring-zero-setup,-interactive,-and-collaborative-wordpress-apps&quot;&gt;The future may bring zero-setup, interactive, and collaborative WordPress apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/wordpress-playground/#the-future-may-bring-zero-setup,-interactive,-and-collaborative-wordpress-apps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Imagine jumping straight into a code editor where you&#39;re free to just get
building right away, with all of the setup completed. You could even share a
simple link and start a multiplayer editing session, such as in Google Docs. And
when you&#39;re done, it would only take a single click to seamlessly deploy your
creations to a variety of hosting services–all without ever installing anything
locally!&lt;/p&gt;
&lt;p&gt;And that&#39;s just a glimpse! We may see interactive tutorials, live plugin demos,
staging sites, decentralized WordPress on edge servers, and even building
plugins on your phone.&lt;/p&gt;
&lt;p&gt;The future is exciting and you can be a part of it! Your ideas and contributions
are the oxygen of WordPress Playground. Visit
&lt;a href=&quot;https://github.com/WordPress/wordpress-playground&quot; rel=&quot;noopener&quot;&gt;the GitHub repository&lt;/a&gt;, say
hi in the #meta-playground
&lt;a href=&quot;https://make.wordpress.org/chat/&quot; rel=&quot;noopener&quot;&gt;WordPress.org Slack channel&lt;/a&gt;, and feel free
to contact Adam at &lt;a href=&quot;mailto:adam@adamziel.com&quot; rel=&quot;noopener&quot;&gt;adam@adamziel.com&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Adam Zieliński</name>
    </author><author>
      <name>Thomas Nattestad</name>
    </author>
  </entry>
</feed>
