During a team meetup a few weeks ago in Lisbon, there was a conversation about WordPress Playground and its possibilities. This conversation inspired me to dig deeper into a Headless WordPress stack without a PHP server.
Table of Contents
- The initial idea
- Attempt #1 – Deployment error due to unique port binding on vercel.com ❌
- Attempt #2 – Memory issues on render.com ❌
- A minimal demo without a express server
- Attempt #3 – Deployment error due to large dependencies on vercel.com ❌
- Attempt #4 – Deployment of minimal prototype Fly.io ✅
- Attempt #5 – Deployment of “The initial idea” on Fly.io ✅
- Conclusions
The initial idea
My initial idea was to leverage Playground CLI (and in general the tools Playground provide to run WordPress in Node) to instantiate a Playground instance in Node that can be used as a User Management engine for a Next JS App. My ultimate goal for this project was to deploy it to Vercel to showcase how Playground enable Headless WordPress apps without a PHP Server.
Key ideas of this MVP would be:
- The Next.js app handles the user interface and navigation, while WordPress powers the backend services and serves as the data engine.
- User management and authentication are handled by WordPress, with extended functionality provided through plugins:
- JSON Web Tokens provision for authenticated requests
- Enhance REST API endpoints to provide additional info
- NextJS App will provide the UI and will communicate with the REST API of the WordPress instance
- Final stage is the app being deployed to Vercel, Render or any other NodeJs free hosting plan
That initial exploration I started at Lisbon became the following project: https://github.com/juanma-wp/users-headless-nextjs-playground
This main version of the project works great locally and it uses @wp-playground/cli to launch a WordPress server (internally powered by ExpressJS) that act as the REST API engine of the NextJs App providing endpoints to authenticate users, get tokens and get extended info of users authenticated.

Attempt #1 – Deployment error due to unique port binding on vercel.com ❌
When I tried to deploy users-headless-nextjs-playground on vercel.com the first time I got some errors that were related to the Vercel limitation that assigns one port (via $PORT) to each runtime instance (see https://vercel.com/docs/builds/configure-a-build). Since Playground CLI and Next.js each start their own server on separate ports, this architecture cannot be deployed to Vercel.
Attempt #2 – Memory issues on render.com ❌
render.com seems to offer more flexibility as background servers are allowed as long as they’re not public. But when deploying users-headless-nextjs-playground (to their free plan) I got this message that made the deploy fail
Ran out of memory (used over 512MB) while running your code.I added some logs to the project to check the amount of memory used. When run the project locally I got the process allocates around 864.63 MB which may probably be the cause of the error above.
⬢ users-headless-nextjs-playground main ⦿ npm run dev
> next-wp-playground@1.0.0 dev
> node server-next.js
...
Starting a PHP server...
Setting up WordPress undefined
Resolved WordPress release URL: https://downloads.w.org/release/wordpress-6.8.1.zip
Booting WordPress...
Booted!
Running the Blueprint...
Downloading Jwt authentication for wp rest api – 0%PHP.request() is deprecated. Please use new PHPRequestHandler() instead.
Logging in – 100%
Finished running the blueprint
WordPress is running on http://127.0.0.1:62142
> NextJS Server listening at http://localhost:3000 as development
...
-----------------------------
Memory usage at 7/1/2025, 9:17:03 AM:
rss: 864.63 MB - Resident Set Size: total memory allocated for the process (includes all C++ and JS objects, stacks, etc.)
heapTotal: 102.56 MB - V8's total heap size
heapUsed: 96.56 MB - V8's used heap size
external: 2469.72 MB - Memory used by C++ objects bound to JS objects managed by V8
arrayBuffers: 445.47 MB - Memory allocated for ArrayBuffers and SharedArrayBuffers
-----------------------------After asking to the Playground team, @berislavgrgicak recommended the following approach
You could boot the Node version of Playground without the express server and than make requests to Playground using the request handler.
Here’s how the CLI does it
The catch with Render.com is that its free plan comes with only 512 MB of RAM, and the next plan that offers more memory costs $25 per month for 2 GB.

As the free plan (Hobby) of vercel.com provides 2GB of memory (see https://vercel.com/docs/functions/configuring-functions/memory) I decided to focus on getting a lighter version of this NextJS app that could connect to a WordPress instance running without a express server so only one process on one port is publicly running (which in theory would solve the limitation I faced on Attempt 1)
A minimal demo without a express server
So I focused my efforts on getting a simple version of a WordPress instance launched with a Node version of Playground without using a express server. The goal with this project was to have a minimal demo that performs with Playground all actions I needed for my initial idea for the NextJs App:
- Instantiate WordPress without a Express server
- Load a custom Blueprint
- Load an external SQLite DB (that is created if it doesn’t exist) – by mounting proper folders
- Perform REST API request to get JWT token
- Use token to authenticate REST API requests
- Mount a local plugin that expands REST API
After struggling with some challenges, I finally was able to implement all these actions with a Node version of Playground without the express server. At demo-playground-cli-mount-db I have two branches that implement all the actions above using two different approaches:
no-express-server-auth– Node version of Playground without the express servermain– Playground CLI with the express server
The no-express-server-auth branch led me to creation and release of the the wordpress-playground-handler NPM package. that encapsulates the WordPress instance creation using the Node version of Playground—without relying on an Express server.
Once I got a working version of Playground WordPress not relying on an express server I created a simple NextJS App nextjs-playground-handler that leveraged wordpress-playground-handler NPM package. as a Headless WordPress to test its deployment
Attempt #3 – Deployment error due to large dependencies on vercel.com ❌
When I tried to deploy nextjs-playground-handler (main branch) to vercel I got the following error: A Serverless Function has exceeded the unzipped maximum size of 250 MB https://vercel.link/serverless-function-size
[15:27:03.926] Running build in Washington, D.C., USA (East) – iad1
[15:27:03.927] Build machine configuration: 2 cores, 8 GB
[15:27:03.939] Retrieving list of deployment files...
[15:27:04.040] Previous build caches not available
[15:27:04.254] Downloading 22 deployment files...
[15:27:04.702] Running "vercel build"
[15:27:05.139] Vercel CLI 44.2.13
[15:27:05.457] Installing dependencies...
[15:27:31.385]
[15:27:31.386] added 541 packages in 26s
[15:27:31.386]
[15:27:31.386] 150 packages are looking for funding
[15:27:31.386] run `npm fund` for details
[15:27:31.437] Detected Next.js version: 15.3.5
[15:27:31.443] Running "npm run build"
[15:27:31.555]
[15:27:31.556] > wordpress-users-app@0.1.0 build
[15:27:31.556] > next build
[15:27:31.556]
[15:27:32.168] Attention: Next.js now collects completely anonymous telemetry regarding usage.
[15:27:32.169] This information is used to shape Next.js' roadmap and prioritize features.
[15:27:32.170] You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
[15:27:32.170] https://nextjs.org/telemetry
[15:27:32.170]
[15:27:32.265] ▲ Next.js 15.3.5
[15:27:32.265]
[15:27:32.289] Creating an optimized production build ...
[15:27:39.119] ✓ Compiled successfully in 6.0s
[15:27:39.123] Linting and checking validity of types ...
[15:27:43.324] Collecting page data ...
[15:27:44.821] Generating static pages (0/6) ...
[15:27:46.023] Generating static pages (1/6)
[15:27:46.024] Generating static pages (2/6)
[15:27:46.024] Generating static pages (4/6)
[15:27:46.117] ✓ Generating static pages (6/6)
[15:27:46.447] Finalizing page optimization ...
[15:27:46.448] Collecting build traces ...
[15:28:03.100]
[15:28:03.103] Route (app) Size First Load JS
[15:28:03.103] ┌ ○ / 611 B 102 kB
[15:28:03.103] ├ ○ /_not-found 977 B 102 kB
[15:28:03.103] └ ƒ /api/users 136 B 101 kB
[15:28:03.103] + First Load JS shared by all 101 kB
[15:28:03.104] ├ chunks/4bd1b696-52a6696c08e3276c.js 53.2 kB
[15:28:03.104] ├ chunks/684-d252a3b20a10e7f9.js 46.1 kB
[15:28:03.104] └ other shared chunks (total) 1.89 kB
[15:28:03.104]
[15:28:03.104]
[15:28:03.104] ○ (Static) prerendered as static content
[15:28:03.104] ƒ (Dynamic) server-rendered on demand
[15:28:03.104]
[15:28:03.283] Traced Next.js server files in: 87.798ms
[15:28:06.341] Warning: Max serverless function size of 250 MB uncompressed reached
[15:28:06.342] Serverless Function's page: api/users.js
[15:28:06.350] Large Dependencies Uncompressed size
[15:28:06.351] node_modules/@php-wasm/node 322.1 MB
[15:28:06.351] node_modules/@php-wasm/web 273.17 MB
[15:28:06.351] node_modules/next/dist 4.23 MB
[15:28:06.351] node_modules/react-dom/cjs 1.74 MB
[15:28:06.352] node_modules/@zip.js/zip.js 791.24 KB
[15:28:06.352] node_modules/@wp-playground/blueprints 740.7 KB
[15:28:06.352]
[15:28:06.352] All dependencies 604.88 MB
[15:28:06.354] Max serverless function size was exceeded for 1 function
[15:28:06.373] Created all serverless functions in: 3.090s
[15:28:06.383] Collected static files (public/, static/, .next/static): 6.079ms
[15:28:06.450] Build Completed in /vercel/output [1m]
[15:28:06.559] Deploying outputs...
[15:28:35.685] Error: A Serverless Function has exceeded the unzipped maximum size of 250 MB. : https://vercel.link/serverless-function-size
[15:28:37.970]
[15:28:40.434] Exiting build containerI asked to Claude about this and this what it told me:
⏺ WordPress Playground Handler Dependencies Size Report
The WordPress Playground Handler has extremely large dependencies that make it unsuitable for Vercel's serverless functions:
Key Dependencies:
- @php-wasm/node: 322MB
- @php-wasm/web: 320MB (with 290MB just for PHP binaries)
- wordpress-playground-handler: 188KB (the handler itself is small)
Critical Issues:
1. 36 WASM files containing PHP binaries for different versions (7.0-8.4)
2. Each PHP WASM file is 11-18MB
3. Total size: ~642MB just for PHP WASM dependencies
4. Vercel limit: 250MB uncompressed for serverless functions
Verdict:
The WordPress Playground Handler cannot be deployed to Vercel in its current form due to the massive PHP WASM binaries required for WordPress execution. You'd need an alternative deployment platform that supports larger function sizes or containerized deployments.Attempt #4 – Deployment of minimal prototype Fly.io ✅
I decided to try to deploy nextjs-playground-handler at Fly.io as it internally uses Dockers containers with less limitations than Vercel’s Serverless Functions and after a few customizations in the project which included the creation of a Dockerfile and a fly.toml files (see fly branch) I was able to succesfully deploy nextjs-playground-handler at https://nextjs-playground-handler.fly.dev/
I asked Claude about the differences between these hostings and this is what I got:
The deployment fails on Vercel but works on Fly.io due to fundamental architectural differences:
Vercel (Serverless Functions)
- Hard limit: 250MB uncompressed per function
- Your app: 604MB (322MB @php-wasm/node + 273MB @php-wasm/web)
- Functions are stateless, isolated Lambda-like environments
- Optimized for lightweight, fast-executing code
Fly.io (Container-based)
- No function size limits - uses Docker containers
- Can handle gigabytes of dependencies
- Persistent VM instances with full filesystem access
- Designed for full applications, not just functionsThe fs-ext package is a dependency of @wp-playground/cli (the only dependency of wordpress-playground-handler NPM package as a way to simplify dependencies) and this package requires Python to build native dependencies. But Python isn’t available in some Linux images (like the Alpine Linux ), so in this exploration I had to install Python in the docker container for fly.io deployments
Attempt #5 – Deployment of “The initial idea” on Fly.io ✅
Given the success of Attempt #4 I decided to try to deploy “The initial idea” (users-headless-nextjs-playground repo) at Fly.io. After some tweaks (see wp-playground-handler-package branch) I was able to succesfully deploy users-headless-nextjs-playground at https://users-headless-nextjs-playground.fly.dev/
Conclusions
In my exploration to deploy a Headless WordPress app—without a traditional PHP server—using WordPress Playground tools for Node.js on platforms like Vercel, I found three major challenges:
- Port Conflicts: Playground CLI spins up its own web server, as does frameworks like Next.js. Vercel, however, only allows one server process to expose a public port.
- High Memory Requirements: Playground in Node depends on WASM packages that require more than 500 MB of RAM, which exceeds the limits of many serverless hosting platforms.
- Large Disk Footprint: These WASM dependencies also consume over 500 MB of disk space, another limiting factor on platforms like Vercel.
The most straightforward workaround is to deploy this stack using hosting providers that support Docker containers. However, once you’re in a containerized environment, it’s just as easy to spin up a standard PHP server and MySQL database—diminishing the advantages of using a Node-based WordPress Playground setup.
The real opportunity lies in reducing Playground’s dependency weight so it can run in environments with more constrained resources—like Vercel Functions.
There are already other approaches that achieve similar goals, so it would be great if having WordPress deployed on Vercel functions could also be achieved by leveraging WordPress Playground.
Thanks to the Playground team (specially to Bero and Adam) for their support on this exploration. After talking to them it seems the challenges I faced can be solved. It’s just a matter of prioritizing them over other features.
I have opened the following issue to keep track of this potential optimization:
https://github.com/WordPress/wordpress-playground/issues/2387
What would you develop if Playground was easy to deploy on Vercel free plan?
Leave a Reply