Nuxt and SvelteKit both render on the server by default, both let you switch that off per route or per site, and both inline a serialised copy of the page's data into the HTML so the browser can hydrate without a second request. Those three facts decide how the two frameworks score on A7 and B5: which rendering mode gives which ratio, why the inlined payload does not count against you since rubric v1.0.1, and where each framework expects robots and sitemap generation to happen.
Framework claims below are limited to documented behaviour at nuxt.com/docs and svelte.dev/docs/kit as of this writing; defaults change between major versions.
The two checks
A7, server-rendered content parity, fetches the homepage once as a plain request and once in a headless browser, extracts the visible text from each with script, style and SVG contents removed, and divides raw by rendered. At or above 0.8 it scores five points; from 0.5 it scores three; below that, zero. It carries a High effort rating because the usual fix is a change of rendering architecture.
B5, clean text ratio, divides the visible text on each crawled page by the bytes of markup that delivered it, after removing the contents of script and style elements. At or above 0.10 it scores three; from 0.05 it scores two; below that, one. It is rated Medium, and the fix is usually template weight rather than architecture. The report shows averageRatio across the crawl and a perPage list.
The two are related. Server rendering makes A7 pass by putting the text in the HTML, and the same architecture inlines a payload that used to make B5 fail. The changelog records why that was corrected.
Rendering modes through A7
Both frameworks have three modes worth distinguishing, under different names.
Server rendering on request. Nuxt calls this universal rendering; SvelteKit calls it SSR; both have it on by default. The server runs the page's load functions, renders components to HTML, and sends a complete document; the browser then hydrates it. For A7 this is the target state: every route arrives with its text in the raw response, and the ratio lands near 1. Content a component fetches after mount, rather than in a load function, is the only thing missing from the raw fetch and the only thing that lowers the ratio.
SPA mode. Nuxt exposes a site-wide ssr: false option; SvelteKit exposes ssr = false as a page option that can be set at the layout level to cover the whole app. In either case the server sends a shell and the browser assembles the page. This is the single-page app problem reproduced inside a framework that could have avoided it, and A7 reads near zero. The mode exists for good reasons, an app behind a login that touches browser-only APIs on first render, for instance, but it belongs on those routes, not on the homepage.
Prerendering. Nuxt prerenders routes at build time through its route rules or its static generation command; SvelteKit does it through a prerender page option and, for a fully static site, its static adapter. The result is an HTML file per route, produced by the same server-rendering code, written once. A7 sees it exactly as it sees a server-rendered page. The trade is that content is as fresh as the last build, and routes that cannot be enumerated at build time cannot be prerendered.
Both frameworks let you mix modes per route: Nuxt through route rules, SvelteKit through page options per route. The scanner measures A7 on the homepage, and an agent starts there too, so whatever you decide for the application, make the homepage and the commercial routes render on the server or at build time.
| Mode | A7 ratio, typically | When it drops |
|---|---|---|
| Server rendering on request | near 1 | text fetched after mount rather than in a load function |
| Prerendering | near 1 | same, plus anything that changed since the build |
| SPA mode | near 0 | always, by construction |
The ratios are what the mechanism implies, not a measurement of any set of sites; run the parity script on your own routes for real numbers.
The inlined payload and B5
Server rendering leaves a second copy of the page in the document. Nuxt serialises the data its load functions returned into a script element in the HTML so that hydration can reuse it; SvelteKit does the same with the data returned from load. For a page whose text comes from a CMS, that payload holds every paragraph a second time, as JSON inside a script tag.
Rubric v1.0.0 measured B5 against total bytes, and that payload was in the denominator. On our own homepage it was most of the document, so the check was penalising the architecture A7 rewards and measuring framework choice rather than markup quality. Version 1.0.1 removed the contents of script and style elements from the denominator; scores issued under 1.0.0 were not restated. The scanner strips every script element regardless of its type attribute, so a JSON payload in a script tag is excluded exactly as a JavaScript bundle is.
So on a Nuxt or SvelteKit site the hydration payload is not your problem on B5, and neither is the bundle. What remains in the denominator is wrapper elements, attribute weight and inline SVG.
Component wrappers. A component that renders a div around a div around the text costs bytes per character of content. Vue 3 and Svelte both allow a component to render multiple root elements, so the wrapper is a habit rather than a requirement.
Class attributes. Utility-class styling puts the styling in the markup, so a long class attribute on every element is counted where a stylesheet rule would not be. That is an observation about where the bytes land, not an argument against it.
Inline SVG. The scanner removes SVG from the text but not from the markup, because an icon is not content but its bytes are still delivered. A navigation bar of inline icons can outweigh the copy on a short page.
Clean text ratio has the terminal command for computing B5 per page so you can see which of the three is yours.
Where robots and sitemaps come from
Neither framework core writes a robots.txt or a sitemap for you, as of this writing. Both serve a static directory verbatim, public/ in Nuxt and static/ in SvelteKit, so the simplest correct approach is a hand-written robots.txt there that names the six AI crawlers and references the sitemap. Both also support server routes that return arbitrary responses, Nuxt through its server directory and SvelteKit through a +server file, so a sitemap can be generated from the same data as the pages rather than maintained by hand; the SvelteKit documentation describes building one this way. The Nuxt ecosystem carries community modules that generate both files from the route table, and route rules can prerender the output so it is served as a static file.
Whichever route you take, A3 wants the sitemap referenced from robots.txt, and D4 wants a lastmod on the entries with at least a fifth of them inside 90 days. A generated sitemap that omits lastmod passes A3 and fails D4; XML sitemaps for agents covers the rest.
The fixes, in order of effort
Low. The static directory: robots.txt, llms.txt, llms-full.txt, security.txt under .well-known. None of these depend on the rendering mode.
Medium. Move page text from post-mount fetches into load functions so it is in the raw response; move JSON-LD into a layout so B1 covers every page; trim wrapper elements and inline SVG for B5.
High. If the site runs in SPA mode, switching it back is the architectural change. In both frameworks that is a configuration change followed by a debugging session, because components written for SPA mode will assume window exists on first render. Agent readiness on Next.js goes through the equivalent decisions in the React framework this site runs on.
Check your own site
Run the free scan and read the A7 and B5 evidence together: the raw and rendered text lengths tell you the rendering mode, the per-page ratios tell you the template weight. A7 is defined under discovery and access and B5 under understanding, and our own report shows what the two look like on a server-rendered site.