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.

FrameworkPrimary fingerprints
Next.js<script id="__NEXT_DATA__">, /_next/static/, __next_f runtime, x-powered-by: Next.js
Nuxtwindow.__NUXT__, /_nuxt/, <div id="__nuxt">, <script id="__NUXT_DATA__">
Astroastro-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 7window.__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 metadata export 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/image priority 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:visible instead of client:load.
  • An XML sitemap is @astrojs/sitemap on Astro, next-sitemap on Next.js Pages Router, or sitemap.ts on 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 3useHead() 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.

Remixmeta 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