Title: Browser tab orchestrates the execution
Published: July 15, 2026
Last modified: July 16, 2026

---

# Browser tab orchestrates the execution

## In this article

 * [Boot sequence](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#boot-sequence)
    - [Data flow](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#data-flow)

[ Back to top](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#wp--skip-link--target)

The main `index.html` ties the entire application together. It starts all the concurrent
processes and displays the PHP responses. The app only lives as long as the main`
index.html`.

Keep this point in mind as you read through the rest of the docs. At this point 
it may seem obvious, by the lines may get blurry later on. This package runs code
outside of the browser tab using Web Workers, Service Workers, and, in the future,
Shared Workers. Some of these workers may keep running even after the browser tab
with `index.html` is closed.

## 󠀁[Boot sequence](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#boot-sequence)󠁿

Here’s what a boot sequence for a minimal app looks like:

![The boot sequence](https://i0.wp.com/raw.githubusercontent.com/WordPress/wordpress-
playground/refs/heads/trunk/packages/docs/site/static/img/boot-sequence.webp?ssl
=1)

The main app initiates the Iframe, the Service Worker, and the Worker Thread. Note
how the main app doesn’t use the PHP stack directly – it’s all handled in the Worker
Thread.

Here’s what that boot sequence looks like in code:

**/index.html**:

    ```javascript
    <script src="/app.ts"></script>
    <iframe id="my-app"></iframe>
    ```

**/app.ts**:

    ```typescript
    const workerUrl = '/worker-thread.js';

    export async function startApp() {
        const phpClient = consumeAPI<PlaygroundWorkerEndpoint>(
            await spawnPHPWorkerThread(
                workerUrl, // Valid Worker script URL
                {
                    wpVersion: 'latest',
                    phpVersion: '8.3', // Startup options
                }
            )
        );

        // Await the two-way communication channel
        await phpClient.isReady();

        // Must point to a valid Service Worker script:
        await registerServiceWorker(
            phpClient,
            'default', // PHP instance scope, keep reading to learn more.
            '/sw.js', // Valid Service Worker script URL.
            '1' // Service worker version, used for reloading the script.
        );

        // Create a few PHP files to browse:
        await workerThread.writeFile('/index.php', '<a href="page.php">Go to page.php</a>');
        await workerThread.writeFile('/page.php', '<?php echo "Hello from PHP!"; ?>');

        // Navigate to index.php:
        document.getElementById('my-app').src = playground.pathToInternalUrl('/index.php');
    }
    startApp();
    ```

Keep reading to learn how all these pieces fit together.

### 󠀁[Data flow](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#data-flow)󠁿

Here’s what happens whenever the iframe issues a same-domain request:

![The data flow](https://i0.wp.com/raw.githubusercontent.com/WordPress/wordpress-
playground/refs/heads/trunk/packages/docs/site/static/img/data-flow.webp?ssl=1)

A step-by-step breakdown:

 1. The request is intercepted by the Service Worker
 2. The Service Worker passes it to the Worker Thread
 3. The Worker Thread calls `PHP.request` to convert that request to a response
 4. The Worker Thread passes the response to the Service Worker
 5. The Service Worker provides the browser with a response

At this point, if the request was triggered by user clicking on a link, the browser
will render PHPRequestHandler’s response inside the iframe.

First published

July 15, 2026

Last updated

July 16, 2026

Edit article

[ Improve it on GitHub: Browser tab orchestrates the execution ](https://raw.githubusercontent.com/WordPress/wordpress-playground/trunk/packages/docs/site/docs/developers/23-architecture/09-browser-tab-orchestrates-execution.md)

Changelog

[ See list of changes: Browser tab orchestrates the execution ](https://developer.wordpress.org/playground/developers/architecture/browser-tab-orchestrates-execution/?output_format=md#)

[  Previous: Running PHP apps in the browser with ServiceWorkers and Worker Threads](https://developer.wordpress.org/playground/developers/architecture/browser-concepts/)

[  Next: Iframe-based rendering](https://developer.wordpress.org/playground/developers/architecture/browser-iframe-rendering/)