Skip to content

Add SPA shell with bootstrap data example#28434

Merged
irvinebroque merged 5 commits intoproductionfrom
opencode/issue28433-20260219003659
Feb 19, 2026
Merged

Add SPA shell with bootstrap data example#28434
irvinebroque merged 5 commits intoproductionfrom
opencode/issue28433-20260219003659

Conversation

@ask-bonk
Copy link
Contributor

@ask-bonk ask-bonk bot commented Feb 19, 2026

All done. Here is a summary of what was created:

New file: src/content/docs/workers/examples/spa-shell.mdx

This adds a new Workers example page at /workers/examples/spa-shell/ documenting the SPA Shell Pattern. The page covers:

  1. Configure static assetsWranglerConfig block showing not_found_handling: "single-page-application", run_worker_first, and the ASSETS binding
  2. Inject bootstrap data with HTMLRewriterTypeScriptExample with the full Worker implementation: parallel data fetch, HTMLRewriter streaming the <head> immediately while awaiting API data for <body> injection, graceful fallback on API failure
  3. Consume prefetched data in your SPA — React client-side example reading window.__BOOTSTRAP_DATA__, plus TypeScript global type declaration
  4. Additional injection techniques — Three subsections: meta tags, CSP nonces, and user configuration injection
  5. When to use this pattern — Guidance on good-fit vs not-needed scenarios
  6. Related resources — Links to HTMLRewriter, Workers Static Assets, and routing docs

The page uses TypeScriptExample and WranglerConfig components (following the analytics-engine.mdx pattern), tags TypeScript and SPA, and passes npm run check with 0 errors.

Closes #28433

github run

Co-authored-by: irvinebroque <irvinebroque@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 19, 2026

This pull request requires reviews from CODEOWNERS as it changes files that match the following patterns:

Pattern Owners
/src/content/docs/workers/ @cloudflare/workers-docs, @GregBrimble, @irvinebroque, @mikenomitch, @korinne, @WalshyDev, @cloudflare/deploy-config, @cloudflare/pcx-technical-writing, @cloudflare/wrangler, @mattietk, @cloudflare/dev-plat-leads
/src/content/docs/workers/static-assets @irvinebroque, @GregBrimble, @WalshyDev, @cloudflare/deploy-config, @cloudflare/pcx-technical-writing

Copy link
Contributor

@irvinebroque irvinebroque left a comment

Choose a reason for hiding this comment

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

/bonk please revise - this example needs to ALSO show how you can do this even when the HTML, CSS, and JS are all deployed outside of Cloudflare

@irvinebroque
Copy link
Contributor

/bonk please revise - this example needs to ALSO show how you can do this even when the HTML, CSS, and JS are all deployed outside of Cloudflare

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Feb 19, 2026

Done. Here is a summary of the changes made to address the review feedback:

What changed in src/content/docs/workers/examples/spa-shell.mdx:

The page now presents two parallel variants instead of assuming the SPA is always on Workers Static Assets:

  1. Option 1: SPA on Workers Static Assets — The original example, restructured under a clear heading. Uses the ASSETS binding and run_worker_first config.

  2. Option 2: SPA hosted on an external origin (new) — For when HTML, CSS, and JS are deployed outside Cloudflare (AWS S3, Vercel, Netlify, your own server, etc.). The Worker acts as a reverse proxy:

    • Wrangler config with SPA_ORIGIN env var and no assets block
    • Worker fetches the SPA shell from the external origin via fetch()
    • Passes static asset requests (CSS, JS, images) through to the external origin unmodified
    • Same HTMLRewriter injection pattern for bootstrap data
    • Returns a 502 if the origin is unreachable

The shared sections (client-side consumption, additional injection techniques) remain unchanged since they apply to both variants. The "When to use this pattern" section now has guidance on choosing between the two options. Related resources now link to Custom Domains and Routes docs.

npm run check passes with 0 errors.

github run

- TypeScript
- SPA
pcx_content_type: example
title: SPA shell with bootstrap data
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
title: SPA shell with bootstrap data
title: Single Page App (SPA) shell with bootstrap data


Two variants are shown:

1. **Static Assets** — The SPA is deployed to [Workers Static Assets](/workers/static-assets/) alongside the Worker.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
1. **Static Assets** — The SPA is deployed to [Workers Static Assets](/workers/static-assets/) alongside the Worker.
1. **Static Assets** — The SPA is deployed using [Workers Static Assets](/workers/static-assets/)

Two variants are shown:

1. **Static Assets** — The SPA is deployed to [Workers Static Assets](/workers/static-assets/) alongside the Worker.
2. **External origin** — The SPA is hosted outside Cloudflare (for example, on AWS S3, Vercel, Netlify, or your own server) and the Worker sits in front of it as a reverse proxy.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
2. **External origin** — The SPA is hosted outside Cloudflare (for example, on AWS S3, Vercel, Netlify, or your own server) and the Worker sits in front of it as a reverse proxy.
2. **External origin** — The SPA is hosted outside Cloudflare, and the Worker sits in front of it as a reverse proxy, improving performance


---

## Option 1: SPA on Workers Static Assets
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
## Option 1: SPA on Workers Static Assets
## Option 1: Single Page App (SPA) built entirely on Workers


## Option 1: SPA on Workers Static Assets

Use this variant when your SPA build output is deployed alongside the Worker using [Workers Static Assets](/workers/static-assets/).
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Use this variant when your SPA build output is deployed alongside the Worker using [Workers Static Assets](/workers/static-assets/).
Use this variant when your SPA build output is deployed as part of your Worker using [Static Assets](/workers/static-assets/).


Both variants use the same HTMLRewriter injection technique and the same client-side consumption pattern. Choose the one that matches your deployment.

This pattern works with any SPA framework — React, Vue, Svelte, or others.
Copy link
Contributor

Choose a reason for hiding this comment

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

Include links to the framework docs that are here:

https://developers.cloudflare.com/workers/framework-guides/web-apps


## Option 2: SPA hosted on an external origin

Use this variant when your HTML, CSS, and JavaScript are deployed outside Cloudflare — for example, on AWS S3, Google Cloud Storage, Vercel, Netlify, or your own server. The Worker acts as a reverse proxy: it fetches the SPA shell from the external origin, uses HTMLRewriter to inject bootstrap data, and streams the modified response to the browser.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Use this variant when your HTML, CSS, and JavaScript are deployed outside Cloudflare — for example, on AWS S3, Google Cloud Storage, Vercel, Netlify, or your own server. The Worker acts as a reverse proxy: it fetches the SPA shell from the external origin, uses HTMLRewriter to inject bootstrap data, and streams the modified response to the browser.
Use this variant when your HTML, CSS, and JavaScript are deployed outside Cloudflare. The Worker fetches the SPA shell from the external origin, uses HTMLRewriter to inject bootstrap data, and streams the modified response to the browser.

.transform(shell);
```

## When to use this pattern
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this section

@irvinebroque
Copy link
Contributor

/bonk update these docs based on my review, and based on the Workers best practices: https://developers.cloudflare.com/workers/best-practices/workers-best-practices/

@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Feb 19, 2026

Committed as a9efdc8.

github run

@irvinebroque
Copy link
Contributor

/bonk please update this pull request based on the guidance below. There are additional pages in the developer docs that should reference what we are adding here, and need the additional content below. Please think hard about how to avoid adding extra complexity to existing documentation. While we want the docs to be clear and comprehensive, we do not want them to be littered with callouts and warnings and distractions. Need to strike a good balance.

  1. SPA routing page (/workers/static-assets/routing/single-page-application/)
    This is the highest-value update. Someone configuring an SPA on Workers lands here, learns about not_found_handling and run_worker_first, but currently has no idea what they can do with run_worker_first beyond basic routing.
    Guidance: Add a section or callout after the run_worker_first configuration examples — something like "Use run_worker_first to inject data into your SPA shell before it reaches the browser. See SPA shell with bootstrap data (/workers/examples/spa-shell/) for a full example using HTMLRewriter to prefetch API data and embed it in the HTML stream." Keep it short — one sentence plus the link. Don't duplicate the example code.
  2. Static Assets binding reference (/workers/static-assets/binding/)
    The run_worker_first section documents the config option but doesn't motivate why you'd use it beyond the abstract "run your Worker before serving static assets." The SPA shell example is the concrete answer.
    Guidance: In the run_worker_first section, add the SPA shell example to whatever list of use cases or examples already exists. If there's no use case list, add a brief one: "Common uses for run_worker_first include authentication checks, A/B testing, and injecting bootstrap data into your SPA shell (/workers/examples/spa-shell/)."
  3. HTMLRewriter API reference (/workers/runtime-apis/html-rewriter/)
    The API reference should link to real-world examples that use HTMLRewriter. The SPA shell example is a better showcase than most existing examples because it demonstrates async element handlers, prepend, and setAttribute together.
    Guidance: Add a link to the SPA shell example in whatever "Related resources" or "Examples" section exists at the bottom of the page. If there's already a list of example links, add it there. If not, add one alongside the existing Turnstile and rewrite-links examples.
  4. Static Assets overview (/workers/static-assets/)
    The landing page currently shows a basic API route pattern with run_worker_first. It should mention that you can go further.
    Guidance: This is a lighter touch. Wherever the existing run_worker_first example appears, add a sentence like "For a more advanced pattern, see SPA shell with bootstrap data (/workers/examples/spa-shell/), which uses HTMLRewriter to inject prefetched API data into the HTML stream." Don't add code — just the cross-link.
  5. Security headers example (/workers/examples/security-headers/)
    The existing example sets CSP as a response header. The new SPA shell page shows CSP nonce injection via HTMLRewriter, which is a strictly better pattern for SPAs with inline scripts.
    Guidance: Add a note in the CSP section: "To inject CSP nonces into inline <script> tags using HTMLRewriter, see the CSP nonce example in SPA shell with bootstrap data (/workers/examples/spa-shell/#add-csp-nonces)." One sentence, one link.

Link to the new SPA shell with bootstrap data example from the five
pages where readers are most likely to benefit from discovering it:
SPA routing, Static Assets binding, HTMLRewriter API reference,
Static Assets overview, and security headers example.
@ask-bonk
Copy link
Contributor Author

ask-bonk bot commented Feb 19, 2026

Done. Here's a summary of the 5 cross-link additions:

  1. SPA routing page (single-page-application.mdx:91) — Added a sentence after the run_worker_first code example and before "Local Development", linking to the SPA shell example as a concrete use of run_worker_first for data injection.

  2. Static Assets binding (binding.mdx:123) — Added a one-liner after the route pattern explanation: "Common uses for run_worker_first include authentication checks, A/B testing, and injecting bootstrap data into your SPA shell." with a link.

  3. HTMLRewriter API reference (html-rewriter.mdx:431) — Added the SPA shell example as a new bullet in the existing "Related resources" list, alongside the existing rewrite-links and Turnstile examples.

  4. Static Assets overview (index.mdx:165) — Added a single sentence after the run_worker_first config block and before the "Routing options" LinkCard, pointing to the SPA shell example as a more advanced pattern.

  5. Security headers example (security-headers.mdx:30) — Added a sentence before the code tabs about using HTMLRewriter for CSP nonce injection, linking to the #add-csp-nonces anchor.

Each addition is one sentence plus a link — no callout boxes, no warnings, no code duplication. npm run check passes with 0 errors.

github run

@irvinebroque irvinebroque enabled auto-merge (squash) February 19, 2026 18:05
@irvinebroque irvinebroque merged commit c3399b8 into production Feb 19, 2026
9 checks passed
@irvinebroque irvinebroque deleted the opencode/issue28433-20260219003659 branch February 19, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

product:workers Related to Workers product size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New Example showing SPA Shell Pattern

7 participants

Comments