tech stack
Web framework detected
MetricSpot fingerprints the JavaScript framework rendering the page (Next.js, Astro, Nuxt, SvelteKit, Remix, React, Vue). Informational — it tailors the rest of the audit's recipes.
What this check does
Identifies the JavaScript framework rendering the page from a layered set of fingerprints. The first reliable signal wins, and the result is purely informational — this rule never fails an audit.
| Framework | Primary fingerprints |
|---|---|
| Next.js | <script id="__NEXT_DATA__">, /_next/static/, __next_f runtime, x-powered-by: Next.js |
| Nuxt | window.__NUXT__, /_nuxt/, <div id="__nuxt">, <script id="__NUXT_DATA__"> |
| Astro | astro-island custom element, data-astro-cid-* attributes, <!-- generated by Astro --> comment, View-Transitions style tags |
| SvelteKit | <script data-sveltekit-hydrate>, /_app/immutable/, __sveltekit_* globals |
| Remix / React Router 7 | window.__remixContext, /build/_assets/, <link rel="modulepreload" href="/build/, Remix-style _data URLs |
| Gatsby | /page-data/, window.___gatsby, <div id="___gatsby"> |
| Create React App | /static/js/main.*.js, /static/css/main.*.css, <div id="root"> with no SSR markup |
| Vite + React/Vue | /assets/index-*.js, <script type="module"> with hashed entry, no framework-specific globals |
| Vue (standalone) | <div id="app">, window.Vue, data-v-* scoped attributes |
| Angular | <app-root>, ng-version attribute on the root element |
When MetricSpot can’t classify the page with confidence (heavily customised builds, server-rendered HTML with all framework signatures stripped), it reports “no framework detected” and treats the audit as a server-rendered HTML site.
Why it matters
Same as the CMS check — this is context that lets the rest of the audit choose the right recipe.
- A missing canonical tag on Next.js is fixed via the
metadataexport in App Router; on Astro it goes in your<Layout>; on CRA there’s no real fix without a server. - A failing Largest Contentful Paint on Gatsby usually means image plugin misconfiguration; on Next.js it points to
next/imagepriority hints or the streaming boundary; on a Vite SPA it usually means client-side rendering of above-the-fold content (the real fix is SSR). - A failing Interaction to Next Paint on Remix or Next.js App Router points to oversized client components; on Astro it points to islands that should be
client:visibleinstead ofclient:load. - An XML sitemap is
@astrojs/sitemapon Astro,next-sitemapon Next.js Pages Router, orsitemap.tson the App Router — the fix label is different every time.
Framework also predicts ceilings. Statically generated Astro or Next.js sites routinely score 95+ on Lighthouse performance; client-rendered CRA or vanilla Vue SPAs rarely break 70 without aggressive code-splitting. Knowing where you are tells you what’s worth optimising and what’s worth migrating.
How to fix it
There’s nothing to fix — this rule is informational. The action is reading the rest of your audit through the lens of your framework’s conventions.
Next.js (App Router) — almost every metadata fix is the metadata export in layout.tsx or page.tsx. Security headers go in next.config.js under async headers(). Images use next/image with priority for LCP.
Next.js (Pages Router) — <Head> in pages/_app.tsx for site-wide tags, per-page <Head> for overrides. next-sitemap for sitemaps. Headers still in next.config.js.
Astro — everything page-level goes in your <Layout> component or a per-page frontmatter block. @astrojs/sitemap for sitemaps, native import.meta.env for build-time data. Astro’s “zero JS by default” model means most performance audits pass without intervention.
Nuxt 3 — useHead() composable or definePageMeta() for metadata. nuxt.config.ts for site-wide settings. @nuxtjs/sitemap for sitemaps.
SvelteKit — <svelte:head> in +layout.svelte for site-wide tags; per-route <svelte:head> for overrides. Headers via handle hook in src/hooks.server.ts.
Remix — meta and headers exports per route. links export for preloads and stylesheets.
Create React App / Vite SPA — most server-rendered audit findings (security headers, canonical URLs, OG tags) cannot be fully fixed without server-side rendering or a meta-injecting build step. Consider migrating to Vite + SSR (with a framework like Astro or Remix) before fighting individual rules.
Vue (standalone) — use vue-meta (Vue 2) or @unhead/vue (Vue 3) for dynamic head tags. For SSR-grade SEO, use Nuxt.
No framework detected — you’re on plain HTML or a server-side template (PHP, Rails, Django, Go templates). Every fix is a direct edit to the source template; you have the most control and the least magic.
Hide framework fingerprints if you must. You can remove x-powered-by headers and strip <!-- generated by … --> comments, but the runtime signatures (mount node IDs, hashed asset paths, hydration globals) are baked into the framework and stripping them breaks the framework. It’s not worth the effort.
Frequently asked questions
MetricSpot detected my framework wrong. Why?
The most common case is detecting a wrapper framework instead of the meta-framework. A Next.js site is also a React site — MetricSpot reports Next.js because it’s more specific. A Nuxt site is also a Vue site; we report Nuxt. If you see “React” but you’re on Next.js, your build is probably stripping the __NEXT_DATA__ script — unusual but possible in custom output modes.
Does the framework affect my audit score?
No, this rule is informational only. It does change which recipes you see — failures elsewhere in the audit will recommend a fix appropriate to your detected stack.
What if I’m using multiple frameworks (micro-frontends)?
MetricSpot reports the framework rendering the page shell. If your shell is Next.js but one section is a Vue micro-frontend, we’ll report Next.js. Single-page micro-frontend setups are rare on marketing surfaces — if you have one, you probably already know which framework owns which route and can interpret the audit accordingly.
Sources
Last updated 2026-05-11