Skip to content

Configure saved-site export API deployment - #4220

Merged
ashfame merged 16 commits into
trunkfrom
agent/hosted-playground-api-deployment
Aug 4, 2026
Merged

Configure saved-site export API deployment#4220
ashfame merged 16 commits into
trunkfrom
agent/hosted-playground-api-deployment

Conversation

@ashfame

@ashfame ashfame commented Jul 30, 2026

Copy link
Copy Markdown
Member

What

Configures /api.html as a network-first, no-store entry document and excludes the API HTML and hashed entry chunk from the website eager offline manifest. It covers both legacy .htaccess hosting and the WP Cloud redirect layer.

Why

A cached API entry can reference assets removed by a later deployment, while eagerly caching this external-only endpoint would add unnecessary website offline payload. The entry needs the same freshness rules as other deployment-sensitive documents.

Stack

Checks

  • npm exec nx test playground-remote
  • npm exec nx lint playground-remote
  • npm exec nx typecheck playground-remote
  • npm exec nx build playground-website
  • PHP deployment harness executed with repository PHP.wasm: all tests passed
  • Built offline manifest checked to exclude /api.html and /assets/api-*.js

@ashfame
ashfame force-pushed the agent/hosted-playground-api branch from 4b0b60f to 652e0af Compare July 30, 2026 16:50
@ashfame
ashfame force-pushed the agent/hosted-playground-api-deployment branch from 5f5b923 to ce71607 Compare July 30, 2026 16:50
@ashfame
ashfame force-pushed the agent/hosted-playground-api-deployment branch from ce71607 to 3079ac7 Compare July 30, 2026 19:31
@ashfame
ashfame force-pushed the agent/hosted-playground-api branch from 652e0af to 7cbfcdf Compare July 30, 2026 19:31
@ashfame
ashfame force-pushed the agent/hosted-playground-api-deployment branch from 3079ac7 to e06b651 Compare July 30, 2026 20:03
@ashfame
ashfame force-pushed the agent/hosted-playground-api branch from 7cbfcdf to 314fd8f Compare July 30, 2026 20:03
@ashfame
ashfame force-pushed the agent/hosted-playground-api-deployment branch from e06b651 to a9045ec Compare July 31, 2026 07:30
@ashfame
ashfame marked this pull request as ready for review July 31, 2026 07:54
@ashfame
ashfame requested a review from brandonpayton July 31, 2026 07:54
AddEncoding x-gzip .gz

<FilesMatch "index\.html">
<FilesMatch "index\.html|api\.html">

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it, remote.html can be added here for completeness. But it's not needed, since service worker has explicit behavior around not caching it. This is only relevant for a self-hoster wanting to use apache, but even then won't make a difference. So, I would rather not touch it for now.

Co-authored-by: Brandon Payton <brandon@happycode.net>
ashfame and others added 8 commits August 3, 2026 15:30
## What

Adds a short explanation to `api.html` for people who open the endpoint
directly. The paragraph starts with the HTML `hidden` attribute and a
small synchronous script reveals it only when `window.self ===
window.top`. The existing module import remains in `api.html`, but
`bootPlaygroundAPI()` is called only when the page is embedded, so
direct navigation does not initialize the export API and iframe
consumers never receive a visible artifact.

## Direct navigation

Opening `api.html` as the top-level page shows the intended explanation.

![Direct navigation to
api.html](https://gist.githubusercontent.com/ashfame/f597ab984bdb9c762ab39c6a477f818e/raw/53ecaf2cdcc7b8cd6a81c126dd1a3ab0ba781f5f/direct-navigation.png)

## Embedded export

For verification, the API iframe was deliberately made visible and given
a border. It remained blank before and after exporting a real saved
site.

![Visible API iframe remains blank during
export](https://gist.githubusercontent.com/ashfame/f597ab984bdb9c762ab39c6a477f818e/raw/53ecaf2cdcc7b8cd6a81c126dd1a3ab0ba781f5f/embedded-export.png)

## `startPlaygroundWeb()` handling

Passing `api.html` as the `remoteUrl` to `startPlaygroundWeb()` does not
load this page. The client validates the URL before assigning
`iframe.src` and throws an `Invalid remote URL` error because
`startPlaygroundWeb()` requires the pathname to be `/remote.html`. The
new direct-navigation explanation therefore covers someone opening
`api.html` in a browser, while the existing client error covers this API
misuse.

## Tested

- Navigated directly to `api.html` and confirmed the explanation is
visible, `window.playgroundAPI` is not initialized, and no page errors
occur.
- Loaded `api.html` in an iframe and confirmed its body remains visually
empty, its paragraph retains `hidden` with zero client rects,
`window.playgroundAPI` is initialized, and no page errors occur.
- Called `startPlaygroundAPI()` with a deliberately visible iframe,
seeded a real OPFS saved site, and ran `exportSavedSiteAsZip()`.
- Confirmed the export returned `application/zip`, 647 bytes, with the
ZIP `PK\x03\x04` signature.
- Confirmed the iframe body remained empty and the paragraph had zero
visible client rects both before and after export.
- Confirmed `npm exec nx lint playground-website` and `npm exec nx
typecheck playground-website` pass.
… agent/pr4219-test-quality

# Conflicts:
#	packages/playground/website/src/lib/state/opfs/opfs-site-storage.spec.ts
ashfame added a commit that referenced this pull request Aug 4, 2026
## What

Adds `startPlaygroundAPI()`, the public saved-site export types, a
lightweight `/api.html` runtime, API forwarding coverage, and Vite
chunking that keeps the OPFS export path separate from the optional
Blueprint editor.

## Why

Consumers need to export an existing OPFS Playground without booting
WordPress, PHP, workers, or a service worker. The endpoint must share
the origin and browser storage partition where the site was saved;
WebKit additionally requires the same top-level origin.

## Stack

- 2 of 3
- Base: #4217
- Previous: #4217
- Next: #4220

## Checks

- `npm exec nx test playground-client`
- `npm exec nx test playground-website`
- `npm exec nx lint playground-client`
- `npm exec nx lint playground-website`
- `npm exec nx typecheck playground-client`
- `npm exec nx typecheck playground-website`
- `npm exec nx build playground-client`
- `npm exec nx build playground-website`

---------

Co-authored-by: Brandon Payton <brandon@happycode.net>
Base automatically changed from agent/hosted-playground-api to trunk August 4, 2026 06:57
@ashfame
ashfame merged commit dd7333b into trunk Aug 4, 2026
54 checks passed
@ashfame
ashfame deleted the agent/hosted-playground-api-deployment branch August 4, 2026 06:58
ashfame added a commit that referenced this pull request Aug 4, 2026
## Summary

- Add a Chromium E2E test that loads the public client, starts a
sandboxed `/api.html`, exports a saved OPFS site, and verifies the
returned ZIP contains unique site content.
- Make the development `client/index.js` shim respect Vite's configured
base path.

## Why

This is stacked on #4220 and verifies the saved-site export API through
the same public entry points consumers use.

The test directly seeds a minimal valid OPFS site so it isolates the API
contract without coupling the coverage to WordPress startup or unrelated
site-manager UI behavior. Its output assertion verifies the complete
browser-to-iframe-to-OPFS-to-ZIP path.

Exercising the real development deployment exposed that the public
client shim emitted a root-relative `/@fs/` import even when the website
was served below `/website-server/`. Using Vite's configured base fixes
that path.

## Validation

- `npm exec nx -- run playground-website:e2e:playwright
--args='packages/playground/website/playwright/e2e/api.spec.ts
--project=chromium'`
- The same E2E against the production static bundle
- `npm exec nx -- run playground-website:lint`
- `npm exec nx -- run playground-website:typecheck`
- `npm exec nx -- run playground-website:build`
- `git diff --check`

---------

Co-authored-by: Brandon Payton <brandon@happycode.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants