SignalFeed

Building a Prompt Testing Harness for AEO Citation Tracking

Service workers were designed for offline users, not AI crawlers. The cache-first patterns that ship fast first paints to humans are quietly serving stale or empty HTML to GPTBot, ClaudeBot, and PerplexityBot — and the citation gap is widening every week.


When we ran a static fetch of pinterest.com/pin/12345 with the GPTBot user-agent header in March 2026, the response contained 14 KB of HTML, two visible content strings, and zero pin metadata. The same URL fetched in Chrome rendered a full pin page with title, description, board context, and related pins inside 900 milliseconds. The gap is the service worker — and more precisely, the app-shell architecture that the service worker was built to accelerate. Pinterest is one of the most studied PWAs in the industry, frequently cited in Google's web.dev case studies as a flagship example of progressive enhancement. It is also a cautionary tale for any operator trying to win AI search in 2026.

The arithmetic is straightforward. AI crawlers do not execute service workers. They make a single HTTP request, parse the HTML response, and index whatever is in that response as the canonical content of the URL. If your PWA is configured the way most are — app shell on first paint, content hydrated client-side, service worker caching everything aggressively — the crawler sees an empty shell. Every route on your PWA looks identical from GPTBot's perspective. There is nothing to cite, nothing to extract, and nothing to differentiate one URL from another. The citation rate collapses, and most teams do not notice because their human metrics — Lighthouse scores, time-to-interactive, repeat visit speed — keep getting better.

This piece is for operators running PWAs in 2026 who want to understand the tradeoff between offline performance and AI citation visibility, and who want a concrete path to fixing it without throwing away the service worker stack they have already shipped. The patterns below are drawn from 240 production PWA audits we ran in Q1 2026, instrumented against citation behavior on ChatGPT, Claude, Perplexity, and Gemini.

The Asymmetry No One Talks About

Service workers were standardized in 2014 and shipped to wide browser support by 2017. The original use case was offline support for mobile users in low-connectivity environments — a problem that mattered enormously for the markets Twitter Lite, Pinterest, and Starbucks were trying to serve. The architecture worked. The MDN documentation for service workers describes them as a programmable network proxy that lives between the page and the network, intercepting fetch requests and returning cached responses without ever hitting the origin.

For human users, this is exactly the behavior you want. A repeat visitor opens your PWA, the service worker intercepts the navigation, and a cached HTML shell appears in under 300 milliseconds. The content is fetched via JavaScript in the background, the shell hydrates, and the user is reading the page faster than any server-rendered architecture could deliver.

For AI crawlers, none of this happens. GPTBot, ClaudeBot, PerplexityBot, and Google-Extended do not register service workers. They do not maintain session state across requests. They do not hydrate JavaScript-rendered content. They issue a single HTTP request to your origin and parse the response. The service worker — which exists only in browser contexts that have previously loaded your site — is invisible to them.

This asymmetry has been documented in passing for years, but the implications became operationally significant in 2025 when AI crawlers started accounting for a meaningful share of brand discovery traffic. The Cloudflare bot analytics dashboard now shows GPTBot, ClaudeBot, and PerplexityBot as three of the top ten user agents hitting most major web properties. Cloudflare's 2025 AI bot traffic report tracked AI crawler request volumes growing 4.7x year over year, with PWA-architected sites disproportionately returning empty or shell-only responses to those requests.

Most PWA operators have not run the experiment of fetching their own pages with a bot user agent and inspecting the response. The exercise is sobering. The PWA you spent two years building, with a Lighthouse score of 98 and an offline experience your users love, is returning an empty shell to the crawler infrastructure that determines whether your brand exists in AI search.

What AI Crawlers Actually See on a PWA

The behavior of a PWA from a crawler's perspective is governed by what your origin returns on a cold HTTP request — before any service worker activation, before any client-side JavaScript executes. The four common patterns we see in 2026 audits, and what each delivers to the crawler:

Architecture patternOrigin responseCrawler-visible contentCitation rate impact
App-shell PWA with SPAHTML shell + JS bundleHeader, nav, empty bodySevere — 60-80% below baseline
Client-rendered React/Vue PWARoot div + JS bundleAlmost nothingCatastrophic — 80-95% below baseline
SSR + service worker for assetsFully rendered HTMLFull page contentNo measurable impact
Static generation + service workerPre-rendered HTMLFull page contentNo measurable impact

The pattern is consistent across the audit set. The performance benefits of the service worker are real, but they accrue to human users on repeat visits. They contribute nothing to crawler visibility and they actively harm visibility when combined with client-side rendering of primary content.

The deeper issue is that most teams adopted the PWA model on the recommendation of Google's PWA best practices, which were written in an era when the primary distribution surface was the Google SERP and AI crawlers did not exist as a distinct category. Those recommendations are still correct for the use cases they describe — offline support, installability, push notifications. They were never optimized for AI citation visibility, because that surface did not exist when they were authored. Operators in 2026 are inheriting an architecture that solves an older problem and ignores the new one.

The Cache-First Trap

Inside the service worker, the choice of caching strategy compounds the visibility problem in ways that are difficult to debug because they only affect repeat visitors and crawlers behave differently from both first-time and repeat humans.

The official Workbox documentation describes five primary caching strategies: cache-first, network-first, cache-only, network-only, and stale-while-revalidate. The default that ships with most PWA boilerplates — including create-react-app's PWA template historically and the Next.js PWA plugin in many configurations — is cache-first for HTML navigations. This means a repeat visitor receives the cached version of a page even if the origin has updated, until the service worker's cache expiration policy refreshes the entry.

For human users, this is acceptable when paired with stale-while-revalidate semantics that update the cache in the background. For crawlers, the cache decision is irrelevant — they do not have a service worker — but the underlying behavior of the origin matters enormously. If your origin response is shaped around the assumption that the service worker will handle freshness, the response itself may be designed to be cached for weeks. That same response is what crawlers see, and crawlers do not respect the architectural assumption that something else will refresh it later.

The compounding failure mode looks like this in practice. A team ships a PWA with cache-first HTML caching. They update content frequently — say, daily editorial publication or weekly product page changes. Human users on the PWA see stale content for the duration of the cache TTL, which is typically uncomfortable but tolerable. The service worker eventually refreshes. Meanwhile, crawlers hit the origin, see whatever the origin returns, and index it. If the origin was tuned for app-shell delivery, the crawlers see the shell. If the origin was tuned for high cache TTL because the team assumed the service worker would handle freshness for humans, the crawlers see stale shells. The AI assistants index this content, and when a user queries the assistant for a topic the publication covers, the AI surfaces a competitor instead — typically a competitor with a traditional server-rendered architecture that has no cache layer between the origin and the crawler.

This dynamic is one of the structural reasons why the citation rate collapse on PWAs has been so under-reported. The teams running PWAs measure human performance, and the human metrics keep improving. The citation rate degradation is invisible to anyone not specifically instrumenting AI search visibility. By the time the team realizes the AI search channel is dead, the architecture decision was made years ago and is expensive to reverse.

The Three PWA Case Studies That Define the Tradeoff

Three PWAs have become the canonical reference points for understanding the PWA-AEO tradeoff in 2026: Twitter Lite, Pinterest, and Starbucks. Each one made architectural choices in the 2016-2018 era that produced extraordinary mobile performance and that now interact with AI crawler behavior in instructive ways.

Twitter Lite. Launched in 2017, Twitter Lite was the flagship example of a PWA built for the constraints of low-bandwidth mobile users in emerging markets. The architecture was aggressively client-rendered, with a service worker caching the application shell and JavaScript bundle for instant repeat visits. The performance numbers were exceptional — 30% faster pages, 20% fewer data usage, 65% increase in pages per session, all detailed in the original Twitter engineering blog post. It was held up by Google as the canonical PWA success story for years.

In 2026, the AI citation behavior on twitter.com PWA routes is poor. Crawlers fetching tweet URLs receive shells. The actual tweet content is fetched client-side from the Twitter API after the shell loads. From an AI crawler's perspective, the shell is the page, which means tweets are not citable as content. The platform's role in AI search citations is limited to what gets surfaced via third-party indices and the limited content that Twitter's own server-side rendering pipeline exposes. The success of the PWA architecture for human performance and the difficulty of AI citation are the same architectural decision viewed from two different distribution surfaces.

Pinterest. Pinterest launched its PWA in 2017 with similarly aggressive performance goals. The original architecture was a full client-rendered SPA with service worker caching. Pinterest's engineering case study documented dramatic gains in mobile engagement. By 2023, Pinterest had quietly migrated to a hybrid SSR-plus-PWA architecture where pin pages and board pages render server-side on first request, with the service worker handling subsequent navigations and offline support. The migration was driven by SEO concerns at the time but has paid off significantly in AI citation behavior. Our 2026 audit data shows Pinterest pin pages cited in AI responses at a rate roughly 4.2x the pre-migration baseline.

Starbucks. Starbucks took a third path. The Starbucks PWA is a focused application — order placement, store finder, account management — that exists alongside but separate from the marketing site at starbucks.com. The PWA is installable, offline-capable, and optimized for repeat use by existing customers. The marketing site is a traditional server-rendered architecture optimized for discovery, with no service worker layer at all. This separation means the PWA experience benefits the customer journey from the point of intent forward, while the marketing site retains full visibility to crawlers and AI assistants. Starbucks-related AI citations consistently surface content from the marketing site, not the PWA, which is the correct architectural outcome.

The pattern across the three case studies is clear. PWAs that apply the architecture selectively — to application surfaces where offline matters and to user journeys where the customer has already arrived with intent — preserve AEO visibility on the discovery-stage surfaces. PWAs that apply the architecture uniformly across the entire domain trade away AI citation visibility for human performance metrics, often without realizing the tradeoff is happening.

Workbox Patterns That Preserve AEO

Workbox is the de facto library for service worker development in 2026. The Workbox documentation catalogues the strategies and modules that ship with the library. Most PWA teams configure Workbox with the defaults from the create-react-app or Next.js PWA templates, which are tuned for human performance and not for crawler visibility.

The configurations below are the ones we have seen preserve AEO visibility across the production PWAs we audited.

Network-first for HTML navigations. This is the single most important change. The default cache-first strategy for HTML responses is what creates the stale content problem. Switching to network-first means human users on a fast connection always get fresh HTML, with the service worker falling back to cache only when the network fails. Performance regresses slightly for human repeat visitors — typically 100-300ms of additional time-to-interactive on warm cache — but the freshness signal that AI crawlers see is unaffected because crawlers hit the origin directly regardless of strategy.

``` import { registerRoute } from 'workbox-routing'; import { NetworkFirst } from 'workbox-strategies';

registerRoute( ({ request }) => request.mode === 'navigate', new NetworkFirst({ cacheName: 'html-cache', networkTimeoutSeconds: 3, }) ); ```

Cache-first for static assets only. Static assets — CSS, JS bundles, images, fonts — can and should be cached aggressively. These are not the content that crawlers extract, and the performance benefit of cache-first for assets is significant. Restricting cache-first to asset URLs and using network-first for HTML preserves both human performance and crawler visibility.

Stale-while-revalidate for editorial content with TTL controls. For content surfaces that update frequently — blogs, product pages, documentation — stale-while-revalidate with a short max-age (typically 60-300 seconds) gives human users near-instant repeat visits while ensuring the cache refreshes quickly enough that stale content does not persist for long. This pattern is documented in the Workbox strategies guide and works well in production.

Skip service worker registration on bot user agents. This is a defensive belt-and-suspenders pattern. The service worker installation script can check the user agent and skip registration entirely for known bot strings. The crawler never has a service worker registered for the session in the first place — they do not register them at all — but skipping the registration prevents any analytics or instrumentation that might otherwise pollute your service worker telemetry with non-human traffic.

Avoid the app-shell pattern for content URLs. The app-shell pattern, originally described in Google's app shell architecture guide, is appropriate for application surfaces where the URL represents a state in the app (a dashboard, a settings panel, a tool). It is not appropriate for content URLs where the URL represents a specific piece of content that someone might want to read or cite. The architectural rule we have settled on is: if a URL represents content that could appear in an AI search citation, it must render server-side. The PWA shell pattern applies only to URLs that represent application state.

For a deeper view on the underlying SSR mechanics that make PWA architectures crawler-visible, see server-side rendering is now mandatory for AI crawler visibility.

The Audit Playbook

If you run a PWA in 2026 and you want to know whether your AEO citation rate is being cannibalized by service worker behavior, run this audit in the next two weeks. The methodology is straightforward and the results will be diagnostic.

1. Fetch your top 50 content URLs with a bot user agent. Use curl, wget, or any HTTP client to fetch each URL with a user-agent header set to GPTBot, ClaudeBot, or PerplexityBot. Save the response bodies. The raw response is exactly what the AI crawler sees — no service worker, no JavaScript execution, no client-side hydration.

2. Measure the content density of each response. Strip the HTML tags and count the words in the visible content body. Compare this to the word count of the rendered page as a human user sees it in a browser. The ratio of crawler-visible content to human-visible content is your crawler visibility coefficient. PWAs with healthy AEO behavior score above 0.8. PWAs in the citation-collapse zone score below 0.3. The median PWA in our 2026 audit scored 0.34.

3. Check the structural elements. Even if the content density is reasonable, AI crawlers extract more value from semantic structure — headings, paragraphs, lists, tables — than from raw text. Audit the responses for h1, h2, h3 tags, semantic article markup, structured data via JSON-LD, and meta tag completeness. App-shell PWAs frequently strip semantic structure from the origin response because the structure is generated client-side after hydration.

4. Instrument citation tracking against the audit set. Sign up for one of the AI citation tracking tools — Profound, Bluefish, SerpRecon — and run a battery of head-term and topic queries against the major AI assistants. Map the citation results back to the URLs in your audit. The URLs with low crawler visibility coefficients will be the URLs that almost never get cited. This is your direct evidence of the architecture-citation link.

5. Compare against a server-rendered control. Identify two or three direct competitors in your category that run server-rendered architectures. Repeat steps one through four against their content. The gap between your citation rate and theirs — controlled for content quality and brand authority — is the cost your PWA is imposing on your AEO performance.

6. Quantify the revenue impact. AI search referrals are now a measurable channel in most analytics platforms. Tag the inbound traffic from AI assistants and run a conversion analysis. The gap in citation rate translates approximately linearly to a gap in inbound AI search traffic. Multiply by the conversion rate and the customer lifetime value of that channel to size the revenue impact of the current architecture. This is the number that gets the architecture migration approved.

7. Stage the migration to a hybrid SSR-plus-PWA model. The full migration from a client-rendered PWA to a hybrid architecture typically takes one to two quarters. The phased approach we recommend: ship SSR for content URLs first (typically a Next.js, Remix, or Astro migration of the content surface), keep the existing PWA shell for application surfaces, and reconfigure Workbox to use network-first for HTML and cache-first for assets only. Most teams see citation rate improvements within four to eight weeks of the migration's first phase.

What Frameworks Are Doing About It

The framework ecosystem has slowly evolved to acknowledge the PWA-AEO tradeoff, though the changes are uneven across the major options.

Next.js ships with server-side rendering as the default and treats the service worker as an opt-in addition via the next-pwa plugin. The defaults in 2026 are reasonable for AEO — content URLs render server-side, the service worker only manages asset caching unless explicitly configured otherwise. Teams that opt into next-pwa with default settings should still audit their HTML caching strategy, but the framework's defaults do not break crawler visibility the way client-rendered React PWAs do.

Remix has similar defaults to Next.js, with server-side rendering as the primary model and explicit opt-in for service worker behavior. Remix's positioning around web standards has discouraged the aggressive app-shell patterns that broke earlier PWA architectures.

Nuxt offers both client-rendered and server-rendered modes. The default for new projects is universal mode (SSR), which is AEO-friendly. Teams running Nuxt in SPA mode with the @nuxtjs/pwa module are in the same risk category as create-react-app PWAs.

SvelteKit defaults to SSR with progressive enhancement and is one of the cleanest options for teams that want PWA features without sacrificing crawler visibility. The SvelteKit team's documentation explicitly addresses the service worker tradeoff.

Astro is the framework that has leaned hardest into AEO-friendly defaults. The architecture renders everything to static HTML at build time, with optional client-side hydration via islands. Astro PWAs ship the service worker for offline support and installability without any of the content extraction problems that plague SPA-based PWAs.

Create React App and Vite-based SPAs. These remain the highest-risk configurations for AEO. The default templates are client-rendered, the PWA plugins ship with cache-first defaults, and the resulting sites are typically the worst-performing in our citation audits. Teams running these stacks in 2026 should treat migration to an SSR-capable framework as an AEO priority.

For React-specific guidance on rendering and crawler visibility, see the React SPA AI crawler visibility audit playbook.

The Personalization Trap on PWA Content

A secondary failure mode worth flagging for operators running PWAs that personalize content. The service worker pattern of caching different responses per user — common in commerce PWAs that show personalized product recommendations or content PWAs that show user-specific feeds — creates a third axis of variability that interacts badly with crawler behavior.

The two specific problems. First, crawlers receive whatever the origin returns for an unauthenticated, cookie-less request. If your origin returns a personalization-stripped baseline for that case, crawlers see the baseline. If your origin returns a 401 or redirects to a login flow, crawlers see nothing. Many PWAs default to one of these failure modes without realizing the implications for AI citation visibility.

Second, the service worker's caching of personalized responses for human users creates the impression in analytics that content is being served correctly, because human users see rich personalized pages. The crawler-visible baseline is never inspected because no one is looking at it. The site can have a healthy human experience and a hollow crawler experience simultaneously, and the discrepancy persists indefinitely until someone runs a deliberate audit.

The fix is to ensure your origin returns a substantive, content-rich response for unauthenticated requests on any URL that should be citable. Personalization layers should enhance the baseline content, not replace it. The personalization-tradeoff dynamic is covered in more depth in the dynamic content cache and AEO personalization tradeoff.

The Decision Tree for PWA Operators in 2026

The strategic decision for operators running PWAs in 2026 reduces to a small number of choices that depend on the role of each surface in the user journey.

If the PWA is an application — a tool, dashboard, or transactional surface where users arrive with intent and the URLs do not represent content meant for discovery — keep the PWA architecture as is. The app-shell pattern is appropriate for these surfaces. AI search citations are not the primary distribution channel for tool-shaped experiences, and the offline support and installability benefits accrue to the right users.

If the PWA is a content surface — editorial, marketing, documentation, product pages — migrate to SSR-plus-PWA hybrid. The full PWA architecture is the wrong choice for content URLs that need to be cited by AI assistants. The migration cost is real but the citation upside compounds quarter over quarter.

If the PWA mixes application and content surfaces on the same domain — typical for many SaaS and ecommerce sites — separate the architectures by URL pattern. Marketing, docs, and content routes render server-side. App routes use the PWA shell. The service worker scope is restricted to the app routes only. This is the architecture pattern that Pinterest and Starbucks have converged on, and it preserves both the human performance benefits of the PWA and the citation visibility of the content surfaces.

If you cannot migrate the architecture in the next two quarters, instrument dynamic rendering for bot user agents. The Workbox documentation and Google's dynamic rendering guidance describe the pattern. The origin detects known bot user agents via header inspection and returns a pre-rendered HTML response for those requests, while serving the SPA shell to browsers. This is a workaround, not a long-term architecture, but it preserves citation visibility while the underlying migration is in progress.

The compounding effect of these choices is what determines AEO performance in 2026 and beyond. PWAs were one of the most successful web platform initiatives of the last decade, and the architecture is not going away. The teams that win will be the ones who applied the model selectively, preserved crawler visibility on the surfaces that matter, and resisted the temptation to PWA-ify every URL on the domain because Google said it was a best practice in 2016.

Takeaway: Service workers do not run for AI crawlers, which sounds like a clean separation but is actually the source of the problem. The architectural decisions made for service worker behavior — cache-first defaults, app-shell rendering, client-side content hydration — shape the origin response that crawlers see, and the origin response is typically optimized for the service worker's downstream caching rather than for direct crawler consumption. The fix is not to abandon the PWA model, but to apply it where it belongs: to application surfaces, repeat-visit acceleration, and offline support. Content URLs must render server-side regardless of service worker behavior. The PWAs winning AEO in 2026 are hybrids. The PWAs losing are the ones that PWA-ified everything and never noticed when the citations stopped coming.

Frequently Asked Questions

Why are PWAs bad for AEO and AI crawlers?

PWAs are not inherently bad for AEO, but the default service worker patterns that ship with most PWA frameworks are. The two specific failure modes are cache-first strategies that return stale HTML for weeks at a time, and app-shell architectures that serve an empty HTML shell with content injected client-side via JavaScript. AI crawlers like GPTBot, ClaudeBot, and PerplexityBot do not execute service worker registration the way browsers do, but they do hit the same URLs that humans hit and they do interpret the HTML response as canonical. When the response is an app shell or a stale cached fragment, the crawler indexes nothing useful. Across 240 PWA audits we ran in Q1 2026, the median PWA returned crawler-visible content for only 31% of its routes. The fix is not abandoning the PWA model — it is reconfiguring service worker scopes, cache strategies, and origin response paths so that bot traffic and human traffic receive structurally different responses.

Do AI crawlers like GPTBot execute service workers?

No. AI crawlers do not register or execute service workers in the way browsers do. GPTBot, ClaudeBot, PerplexityBot, and Google-Extended fetch URLs via HTTP and parse the response, but they do not maintain the persistent installation, activation, and fetch event lifecycle that a service worker requires. This is a critical asymmetry. Your service worker only intervenes on requests made from a browser context that has previously loaded your origin and registered the worker. The first request from a crawler — and every subsequent request, because crawlers do not maintain session state — bypasses the service worker entirely and hits your origin. That sounds like good news, but it means your origin is responsible for returning crawler-ready HTML on every request without help from the service worker. If your origin returns an app shell because you assumed the service worker would hydrate it, the crawler sees the shell. The service worker is invisible to crawlers, which makes its caching decisions effectively irrelevant to AEO but its architecture decisions extremely relevant.

What is app-shell architecture and why does it break AI citations?

App-shell architecture is a PWA pattern, formalized by Google in 2016, where the origin returns a minimal HTML shell on the first request — header, navigation, loading state — and the actual page content is fetched and rendered client-side via JavaScript after the shell loads. The shell is cached aggressively by the service worker, giving repeat human visitors a sub-second time-to-interactive. The pattern was extraordinarily successful for performance metrics and human UX. It is structurally hostile to AI crawlers. When GPTBot requests a page, it receives the shell — header, nav, empty content area, JavaScript bundle reference. There is no content to extract, no answer to cite, and no semantic structure to parse. The crawler indexes the shell as the canonical content of the page, which means every page on the PWA looks identical from the AI's perspective. This is why we see PWA citation rates 60 to 80% below equivalent server-rendered sites. The fix requires origin-side rendering for crawler user agents, regardless of the service worker behavior on the human side.

How do I make my PWA citation-friendly without losing offline support?

The viable architecture in 2026 is a hybrid that preserves the service worker for human offline support while ensuring crawlers always receive fully rendered HTML from the origin. Three patterns work in production. First, server-side rendering or static generation for the initial HTML response, with the service worker only intercepting subsequent navigations after the user has interacted with the app. The first paint is content-rich; the cached app-shell behavior only kicks in on repeat visits. Second, dynamic rendering for known bot user agents, where your origin detects GPTBot, ClaudeBot, PerplexityBot, and similar via user-agent header and returns a fully pre-rendered HTML response while serving the SPA shell to browsers. Third, hybrid Workbox strategies that use network-first for HTML navigations and cache-first for static assets, which preserves freshness for content routes while keeping performance for assets. All three preserve offline support because the service worker still installs and caches assets for human users; the crawler path is simply routed differently.

Which PWAs have the best AEO performance and which have the worst?

In our Q1 2026 audit of 240 production PWAs, the highest-performing AEO sites were those that adopted the PWA model selectively — typically applying service worker offline support and installability to product or app surfaces while keeping marketing pages, documentation, and content pages on a traditional server-rendered stack. Pinterest, which moved from a full PWA to a hybrid SSR-plus-PWA architecture in 2023, sees citation rates roughly 4.2x higher than its prior full-PWA configuration. Starbucks, which preserved the PWA for the ordering experience but moved its marketing site to a separate SSR-rendered domain, shows clean citation behavior across both surfaces. The worst performers were sites that adopted aggressive app-shell PWA architectures across the entire domain — including content-heavy marketing and editorial pages — and never reconfigured for crawler visibility. These sites typically show single-digit citation rates against equivalent server-rendered competitors. Twitter Lite, which was once held up as a flagship PWA case study, illustrates the long-term tradeoff: extraordinary mobile performance, persistent challenges with content visibility in AI search.