Skip to content

Add a portability test for published static sites - #807

Open
jamiefolsom wants to merge 1 commit into
developfrom
jf/static-portability
Open

jamiefolsom wants to merge 1 commit into
developfrom
jf/static-portability

Conversation

@jamiefolsom

@jamiefolsom jamiefolsom commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

This adds npm run test-static, a Playwright check for a published static site. It opens the home page, the posts list, the first search page and, when given one, a detail page. It fails when a page requests a host named in the site's configuration, requests a server island, or asks for a same-origin asset that does not exist. The search page may still call the search host until the static search work lands. STATIC_SITE_URL names the site, so the same test runs against a local server or against the published site. This is what pstudio fds check portability --remote will call.

I ran it against marronage, built from these pull requests and served locally. The home page, the posts list and a detail page all passed, making no requests to the site's own backend and no server-island requests. The search page failed on one missing asset, the self-hosted map style, because the maps transform was skipped in that run. The test caught exactly what it should.

Part of #710. This is the third of three pull requests that bring the static-build experiment into develop, and it sits on #805.

@jamiefolsom jamiefolsom added the static-mvp Static build: in the MVP (one site published as plain files from develop) label Sep 18, 2026
@jamiefolsom
jamiefolsom requested a review from blms September 18, 2026 00:46
@jamiefolsom
jamiefolsom added this pull request to stack #806 September 18, 2026 00:46
@netlify

netlify Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for pss-scavenger-hunt ready!

Name Link
🔨 Latest commit bba1c8c
🔍 Latest deploy log https://app.netlify.com/projects/pss-scavenger-hunt/deploys/6ac96ecb592b720008d1e1a7
😎 Deploy Preview https://deploy-preview-807--pss-scavenger-hunt.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for padp-staging ready!

Name Link
🔨 Latest commit bba1c8c
🔍 Latest deploy log https://app.netlify.com/projects/padp-staging/deploys/6ac96ecb10e5ac0008365b35
😎 Deploy Preview https://deploy-preview-807--padp-staging.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for marronage-staging ready!

Name Link
🔨 Latest commit bba1c8c
🔍 Latest deploy log https://app.netlify.com/projects/marronage-staging/deploys/6ac96ecb088aa400085f4277
😎 Deploy Preview https://deploy-preview-807--marronage-staging.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for relnet-staging ready!

Name Link
🔨 Latest commit bba1c8c
🔍 Latest deploy log https://app.netlify.com/projects/relnet-staging/deploys/6ac96ecc53aaaa000849bc1c
😎 Deploy Preview https://deploy-preview-807--relnet-staging.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@blms blms left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking good! A few suggestions around detail pages and images. And one note about testing this against a locally checked out config since it seems the intention is to test published sites.

@@ -0,0 +1,79 @@
import { test, expect } from '@playwright/test';
import config from '../../public/config.json' with { type: 'json' };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is loading the local public/config.json, so it only works if the site is already checked out locally. Could it work to use something lke ${STATIC_SITE_URL}/config.json instead for a published static site? e.g.

const config = BASE ? await (await fetch(new URL('config.json', BASE))).json() : null;

* adapter lands.
*
* STATIC_SITE_URL names the site to check (a local server or the published
* one). Own hosts are every hostname found in config.json; STATIC_OWN_HOSTS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Own hosts are every hostname found in config.json

This catches anything the config points to, but image URLs come from the records, not config.json, so a site could still depend on an outside image server and pass. Since those hosts can be anything, maybe we check images by type instead:

const isImage = (req, url) => req.resourceType() === 'image' || url.pathname.endsWith('/info.json');

and in the request handler, after the same-origin check:

if (isImage(req, url)) ownCalls.push(req.url());

(info.json is there because IIIF viewers fetch it as data before loading any tiles.)

This would fail any site with outside images until images are static, so it may need to wait for that work.

{ name: 'home', path: `/${locale}` },
{ name: 'posts list', path: `/${locale}/posts` },
...(searchName ? [{ name: `search (${searchName})`, path: `/${locale}/search/${searchName}`, searchAllowed: true }] : []),
...(process.env.STATIC_DETAIL_PATH ? [{ name: 'detail', path: process.env.STATIC_DETAIL_PATH }] : [])

@blms blms Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If we wanted, we could actually just grab a detail page directly from the site instead of making the user specify it, using /api/{model}/index.json:

const [model] = Object.keys(config.detail_pages?.models ?? {});
const records = model ? (await (await fetch(new URL(`api/${model}/index.json`, BASE))).json())[model] : [];
const detailPath = records?.[0] && `/${locale}/${model}/${records[0].uuid}`;

That would save the user from having to define STATIC_DETAIL_PATH altogether. (Unless there is a reason we would want to exclude detail pages from testing—in which case I might suggest a boolean like SKIP_DETAIL_PAGES or something)

Comment thread package.json
"vitest": "vitest run",
"playwright": "npx playwright test",
"test-a11y": "npx playwright test test/browser/a11y.test.ts",
"test-static": "npx playwright test test/browser/static.test.ts",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

By default this will use playwright.config.ts, which runs tests under Chromium, Firefox and WebKit. Therefore each page would get checked three times, and wherever pstudio runs it, all three browsers would have to be installed. Adding --project=chromium here should be enough to test fully, since the requests a page makes won't differ between browsers.

Suggested change
"test-static": "npx playwright test test/browser/static.test.ts",
"test-static": "npx playwright test test/browser/static.test.ts --project=chromium",

@ajolipa
ajolipa force-pushed the jf/static-portability branch 2 times, most recently from 1bcd16a to c020e0d Compare October 9, 2026 22:46
Base automatically changed from jf/static-islands to develop October 9, 2026 22:46
The test opens the home page, the posts list, the first search page and, when given, one detail page of a site named by STATIC_SITE_URL. It fails when a page requests any host named in the site's config, makes a server-island request, or asks for a same-origin asset that does not exist. The search page may still call the search host until the static search adapter lands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FbHx5mB9KZKURcTMDh8B9e
@ajolipa
ajolipa force-pushed the jf/static-portability branch from c020e0d to bba1c8c Compare October 9, 2026 22:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

static-mvp Static build: in the MVP (one site published as plain files from develop)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants