SolidJS SEO
How to make SolidJS sites crawlable, indexable, and fast — why bare SolidJS is CSR-only, how SolidStart's SSR/SSG fixes it, managing head tags with @solidjs/meta, and why SolidJS hydrates (it is not resumable like Qwik).
SolidJS is a fast, React-like library with fine-grained reactivity and no virtual DOM — but on its own it's client-side rendered, so it ships an empty HTML shell with the same indexing problems as bare React. The fix is SolidStart, the official meta-framework: SSR or SSG put real content and metadata in the first response. Manage head tags with @solidjs/meta (<Title>, <Meta>, <Link>), return real 404s with <HttpStatusCode>, and fetch data on the server with createAsync. One thing not to mix up: SolidJS hydrates — it is not resumable. Resumability is Qwik's trick. SolidJS's win is a Core Web Vitals edge on top of standard SSR.
Evidence for this claim The article's described solidjs-seo capabilities must be evaluated against the platform's current documentation rather than assumed to be search-engine behavior. Scope: Platform-specific capability documentation. Confidence: high · Verified: SolidStart documentation Evidence for this claim Regardless of platform, Google needs crawlable URLs, accessible rendered content, descriptive metadata, and valid search directives. Scope: Google requirements independent of platform. Confidence: high · Verified: Google Search Central: SEO Starter GuideTL;DR — SolidJS is a fast, React-like library, but on its own it builds the page in your browser — so search engines first see an empty shell. The fix is SolidStart, its official full-stack tool, which sends finished HTML to both users and crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index.. RenderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. mode is a per-route setting, not a whole-site switch — use server renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. (SSR or SSG) on the routes that need to rank, set your title and meta tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. with @solidjs/meta, and verify each route’s actual HTML output rather than assuming the whole site is covered.
What SolidJS is
SolidJS is a JavaScript library for building user interfaces. If you’ve seen React, it’ll look familiar — it uses the same JSX syntax and a similar component style. The big difference under the hood is that SolidJS has no virtual DOM: it updates the exact pieces of the page that change, which makes it very fast.
The catch for SEO: by default, SolidJS is client-side rendered (CSR). The server sends an almost-empty HTML file, then your browser downloads the JavaScript and builds the page. That’s a problem because the first thing a search engine sees is the empty version — no text, no title, no meta descriptionThe meta description is an HTML head tag — `<meta name=\"description\" content=\"…\">` — that suggests a short summary of the page for the search snippet. It's not a Google ranking factor, and Google rewrites it the majority of the time, but a good one can still lift click-through..
Why CSR is an SEO problem
When Google crawls a CSR page, it sees the empty shell first. It can come back later, run the JavaScript, and read the real content — but that second pass can take anywhere from hours to weeks. Worse, Bing and social-media crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. (Facebook, LinkedIn, X) often don’t run JavaScript at all, so they may never see your content or your share previews.
This is the same issue bare React, Vue, and Angular have. It’s not unique to SolidJS — it’s a property of client-side rendering. (See JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. for the full picture.)
The fix: SolidStart
SolidStart is the official meta-framework for SolidJS — think of it as SolidJS’s version of Next.js (for React) or Nuxt (for Vue). It lets the server send finished HTML, so search engines and social crawlers get your content on the very first request. Two main modes:
- SSR (server-side rendering) — the page is built on the server each time it’s requested. Good for content that changes often.
- SSG (static site generation) — pages are built once at deploy time and served as plain files. Fastest option; ideal for blogs, docs, and marketing pages.
Setting your title and meta tags
To control your <title>, meta descriptionThe meta description is an HTML head tag — `<meta name=\"description\" content=\"…\">` — that suggests a short summary of the page for the search snippet. It's not a Google ranking factor, and Google rewrites it the majority of the time, but a good one can still lift click-through., and social share tags, use the
@solidjs/meta package. It gives you <Title>, <Meta>, and <Link>
components you drop into your pages — SolidJS’s equivalent of React Helmet. With
SolidStart’s SSR turned on, those tags show up in the HTML that crawlers read.
The one thing not to mix up
You may hear SolidJS lumped in with Qwik as “the resumable frameworks.” That’s wrong. Resumability is Qwik’s idea. SolidJS uses ordinary hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. — it just does it more cheaply than React. For SEO that distinction barely matters (both put content in the HTML), but it’s a common mistake.
Want the real mechanics — SSR vs. SSG vs. streaming, the @solidjs/meta API, real 404s, server-side data fetching, and the Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. story? Switch to the Advanced tab.
Evidence for this claim The article's described solidjs-seo capabilities must be evaluated against the platform's current documentation rather than assumed to be search-engine behavior. Scope: Platform-specific capability documentation. Confidence: high · Verified: SolidStart documentation Evidence for this claim Regardless of platform, Google needs crawlable URLs, accessible rendered content, descriptive metadata, and valid search directives. Scope: Google requirements independent of platform. Confidence: high · Verified: Google Search Central: SEO Starter GuideTL;DR — SolidJS is fine-grained reactive (signals, no virtual DOM) and ships as a CSR library by default — an empty shell with the same Wave-1 indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. problem as bare React. SolidStart is the fix: SSR, SSG (route prerenderingTurning HTML, CSS, and JavaScript into the final visual page and DOM.), and streaming SSR put content and metadata in the first response. Manage head tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. with @solidjs/meta (
<Title>,<Meta>,<Link>under a<MetaProvider>), return real status codes with<HttpStatusCode>, and load data on the server withcreateAsyncso it lands in the SSR HTML. The accuracy spine: SolidJS hydrates — it is NOT resumable (that’s Qwik). Its fine-grained reactivity is a client update optimization, not a server-to-client startup one — so the SEO upside is mostly a Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. (INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good./TBTTotal Blocking Time — the sum of the blocking portion (time above 50 ms) of every long task between First Contentful Paint and Time to Interactive. It's a lab-recommended metric and the lab proxy for INP, not a Core Web Vital.) edge layered on top of normal SSR.
SolidJS architecture: what’s actually different
SolidJS uses JSX that looks identical to React’s, plus hooks-like primitives
(createSignal, createEffect, createMemo). But the execution model is
fundamentally different:
- React re-runs the whole component function when state changes and diffs a virtual DOM to decide what to update.
- SolidJS compiles JSX to real DOM operations at build time. Components run once; reactive signals wire values directly to the specific DOM nodes that depend on them. When a signal changes, Solid updates only that node — no reconciliation, no virtual DOM overhead.
This is why SolidJS consistently sits near the top of the js-framework-benchmark suite, and why its runtime is dramatically leaner than React’s re-render model. The library itself is roughly 7KB gzipped. Smaller, surgical updates plus a tiny runtime is the performance story — but none of that changes the renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. mode, which is what decides your SEO fate.
CSR by default: the SEO problem
Build with SolidJS alone (no SolidStart) and you get a client-side-rendered app:
- The server sends
index.htmlwith a near-empty body — typically a<div id="root"></div>and a script tag. - The browser downloads the JS bundle, runs Solid’s reactive code, and populates the DOM.
- GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer.’s first wave sees the empty shell — no content, no metadata.
- GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer.’s second wave (the rendering queue) eventually runs the JS and sees content — but the timing is unpredictable, from hours to weeks.
- Bing, social crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index., and non-JS bots may never see the content at all.
This is the two-wave rendering process, and it’s the same trap any CSR SPA falls into. The practical impacts: slow initial indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. of new content; titles and meta descriptionsThe meta description is an HTML head tag — `<meta name=\"description\" content=\"…\">` — that suggests a short summary of the page for the search snippet. It's not a Google ranking factor, and Google rewrites it the majority of the time, but a good one can still lift click-through. missing from the raw HTML (so wrong/blank snippets in SERPs); and soft 404sA soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing., because a CSR app can’t return a true HTTP 404 — the server always answers 200 with the app shell.
SolidStart: the fix
SolidStart (1.0, stable) is the official SolidJS meta-framework, built on Vinxi (Vite + Nitro). It provides:
- Isomorphic, file-based routing — files under
src/routes/map to URLs (src/routes/blog/[slug].tsx→/blog/:slug). One correction worth being precise about: SolidStart itself does not ship a router or metadata library bundled in — per its own docs, “SolidStart itself does not ship with a Router or Metadata library. Rather, it leaves that open for you to use any library you want.” The routing and@solidjs/metabehavior described here come from adding@solidjs/routerand@solidjs/metaexplicitly (the official templates add both for you, which is why it can feel automatic — check yourpackage.jsonrather than assuming they came free with the framework). - Multiple rendering modes, chosen per route: CSR, SSR (synchronous, asynchronous, or streaming), and SSG / route prerendering. A SolidStart project isn’t “SSR” or “CSR” as a whole — each route picks its own mode, so verify the rendering config (and the resulting HTML) for the specific route you care about rather than assuming the whole site inherited one setting.
- Server functions — a
"use server"directive for RPC-style server code (data fetching, database access). - Adapters for Cloudflare, Vercel, Netlify, Deno, Node, and static hosting.
Version note: this reflects SolidStart 1.0’s current documentation, which labels itself beta and was last updated 2026-04-28 — confirm details against the docs for the version you’re actually running before treating any of this as permanent API surface.
SSR vs. SSG vs. streaming — the SEO read
- SSR (synchronous, asynchronous, or streaming — SolidStart names these as distinct sub-modes) delivers full content on the first request and is fully indexable on Wave 1. Best for frequently changing pages.
- SSG (route prerendering) builds HTML at deploy time — the fastest TTFBTime to First Byte — the time from the start of a request to when the first byte of the response arrives. It's a diagnostic metric (not a Core Web Vital) and a major input to FCP and LCP; ≤0.8 s is good. and
LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good., CDN-cacheable, no per-request server work. Best for blogs, docs, and
marketing pages. Configure prerendered routes in
app.config.ts:
// app.config.ts
import { defineConfig } from "@solidjs/start/config";
export default defineConfig({
server: {
prerender: {
routes: ["/", "/about", "/blog"],
},
},
});- Streaming SSR sends HTML progressively to improve TTFB on data-heavy pages; Google renders the full streamed output.
- CSR is fine for authenticated dashboards and tools that don’t need to rank — not for public content.
Managing head tags with @solidjs/meta
The @solidjs/meta package is the SolidJS equivalent of React Helmet or
Next.js’s <Head>. It’s SSR-ready and asynchronous. Wrap your app in
<MetaProvider> so tags are collected during SSR, then set per-page tags inside
your route components:
// src/routes/about.tsx
import { Title, Meta, Link } from "@solidjs/meta";
export default function AboutPage() {
return (
<>
<Title>About Us — My Site</Title>
<Meta name="description" content="Learn more about us." />
<Link rel="canonical" href="https://example.com/about" />
<Meta property="og:title" content="About Us" />
<Meta property="og:description" content="Learn more about us." />
<Meta property="og:image" content="https://example.com/og-about.jpg" />
<main>...</main>
</>
);
}The components available are <Title>, <Meta>, <Link>, <Style>,
<Base>, and the <MetaProvider> wrapper. Deduplication is built in:
<Meta> tags with matching name attributes override parent definitions — the
deepest (most specific) one wins, and this works correctly during SSR. So a root
default title and per-page overrides behave as you’d expect.
One warning straight from the docs: don’t add raw <title> tags in your
server files — they override @solidjs/meta’s functionality. Always use the
<Title> component, never a hand-written HTML title in your server template.
Structured data (JSON-LD)
Google supports JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. whether it’s in the raw HTML or injected by JavaScript, but SSR-rendered JSON-LD is the reliable choice. In SolidStart, render it in the route component:
export default function ArticlePage() {
const schema = {
"@context": "https://schema.org",
"@type": "Article",
"headline": "My Article",
"author": { "@type": "Person", "name": "Author Name" },
};
return (
<>
<script
type="application/ld+json"
innerHTML={JSON.stringify(schema)}
/>
<article>...</article>
</>
);
}With SSR enabled, the JSON-LD appears in the server-rendered HTML — the preferred approach for reliability across every crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index.. Validate with the Rich ResultsRich results (formerly 'rich snippets') are enhanced search listings — stars, images, prices, breadcrumbs, video thumbnails, and more — that Google and Bing build from structured data. They're a display feature, not a ranking factor, and eligibility never guarantees they'll show. Test or URL Inspection ToolA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version..
Hydration, not resumability — the accuracy spine
HydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. is the process where, after SSR delivers rendered HTML, the
framework attaches to the existing DOM to make it interactive: download the JS
bundle, execute the framework code, reconcile state with the existing nodes,
attach event listeners. SolidJS uses hydration — the same fundamental mechanism
as React’s hydrate, Vue’s createSSRApp, or Angular SSR.
Resumability (Qwik’s architecture) is different: the server serializes the framework’s execution state into the HTML, and the client resumes from there without re-executing components — interactive before any JS runs.
The myth to debunk: SolidJS’s fine-grained reactivity is sometimes confused with resumability because both avoid “re-running” components in the traditional sense. They are not the same thing. Fine-grained reactivity is a client-side update optimization; resumability is a server-to-client startup mechanism. SolidJS still downloads and runs its runtime before the page is interactive.
The SEO implication: both SSR+hydration (SolidJS) and resumability (Qwik) put rendered HTML in the server response, so both are good for indexing. The difference is Time to Interactive and INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good. on slow devices, where Qwik’s near-zero startup JS has the edge. For crawl and index, SolidStart SSR is already enough.
Core Web Vitals
SolidJS’s runtime advantages can translate into better Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. scores on routes that use SSR — but this isn’t automatic or universal. No primary source establishes guaranteed cheap hydration or better outcomes for every Solid/SolidStart route: bundle size, data fetching, third-party scripts, device, and the route’s actual rendering mode all determine the real cost. Treat the following as the mechanism by which SolidJS can help, and measure your own routes to confirm it does:
- LCP improves because the largest content element is in the server-rendered HTML — no waiting on JS.
- INP improves because Solid’s fine-grained runtime handles interactions efficiently (no virtual DOM diffing).
- CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. drops because SSR’d content doesn’t shift as late-loading JS fills in.
A caution worth keeping honest: figures like “SolidJS is ~70% faster than React’s virtual DOM” come from synthetic benchmarks (js-framework-benchmark), not real-world field dataPerformance metrics captured from real users, not lab tests.. Real CWV depends far more on implementation quality, data fetching, and hosting than on framework choice. Treat the benchmark numbers as directional, and measure your own field data in CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. / Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance..
Routing, data fetching, and real 404s
Routing. SolidStart uses the History API by default — never use
hash-based (#/page) routing, which prevents reliable URL discoveryURL discovery is how search engines find URLs to crawl — by pull (following links and reading sitemaps) and by push (you notify them via IndexNow, the Indexing API, or WebSub). It's the find step that comes before a page is ever fetched.. Keep
trailing-slash behavior consistent and enforce it with server redirectsA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't., not
just canonicals.
Data fetching for SEO. Content that needs to rank must be loaded on the
server so it’s in the SSR HTML. Use createAsync and server functions — not
onMount or client-side effects, which run after the HTML is sent:
// Server-side data fetch — content lands in the initial HTML ✓
import { createAsync } from "@solidjs/router";
import { getPost } from "~/lib/api";
export const route = {
load: ({ params }) => getPost(params.slug),
};
export default function BlogPost(props) {
const post = createAsync(() => getPost(props.params.slug));
return <article>{post()?.content}</article>;
}Real 404s. A catch-all route plus <HttpStatusCode> from @solidjs/start
sets the actual HTTP response code on the server — a true 404 instead of a soft
404:
// src/routes/[...404].tsx
import { HttpStatusCode } from "@solidjs/start";
export default function NotFound() {
return (
<>
<HttpStatusCode code={404} />
<h1>Page Not Found</h1>
</>
);
}Sitemaps, robots.txt, and international SEO
- robots.txtA plain-text file at the root of a host that tells crawlers which URLs they may and may not request. It controls crawling, not indexing — a blocked URL can still be indexed if it's linked from elsewhere. — add
public/robots.txtat the project root and point it at your sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing.. Don’t block the/api/routes used for XHR data fetching. - Sitemap — the third-party
solid-start-sitemapplugin (by madaxen86) generatessitemap.xmlat build time and supports dynamic routes via parameter mapping or a runtime API route. - International SEOInternational SEO is the practice of optimizing a site so search engines understand which countries and/or languages it targets, and serve the right version to each user. It spans URL structure, hreflang, and on-page localization. — emit hreflangHreflang is an annotation (in HTML, HTTP headers, or XML sitemaps) that tells search engines which language and optional region a page targets, and which alternate versions exist. It only works when every page in the cluster references all the others. with
<Link rel="alternate" hreflang="…">from @solidjs/meta, and use a subdirectory structure (/en/,/fr/) over subdomains or query parameters.
Common SolidJS SEO pitfalls
- Running SolidJS CSR without SolidStart SSR/SSG.
- Fetching rankable content in
onMount/ client-side effects. - Forgetting the
<MetaProvider>wrapper (tags won’t render in SSR). - Adding raw
<title>HTML tags in server templates (overrides @solidjs/meta). - Using hash-based routing.
- Serving soft 404s without
<HttpStatusCode>. - Blocking API routes in robots.txt.
- Not fingerprinting JS assets (Google caches scripts aggressively).
- Content behind a click/accordion/tab that never auto-loads into the DOM.
- Assuming SSR works without verifying via View Source / URL Inspection.
- Assuming
@solidjs/routerand@solidjs/metacome bundled with SolidStart — they don’t; SolidStart’s own docs say it “does not ship with a Router or Metadata library.” Official templates add both for you, but a from-scratch or customized setup needs them installed explicitly. - Treating a project as uniformly “SSR” or “CSR” — rendering mode is set per route in SolidStart, so a route you assume is server-rendered may not be.
Where this sits
SolidJS lives in the JavaScript frameworksJavaScript frameworks — React, Vue, Angular, Next.js, Nuxt, Svelte, Astro — are libraries or meta-frameworks for building web UIs. Their SEO impact depends on rendering mode: SSR and SSG deliver pre-rendered HTML; CSR-only apps require Googlebot to execute JavaScript before it can index content. subcluster alongside Qwik, under the broader JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript. cluster. For the closest parallel, see React SEOReact SEO is the practice of making React apps crawlable and indexable. React renders client-side by default, so the raw HTML is near-empty until JavaScript runs — SSR or SSG puts the content back in the initial response where crawlers (and AI bots) can reliably see it. — SolidJS shares React’s JSX and CSR-by-default problem, but fixes it with SolidStart instead of Next.js, and runs faster thanks to no virtual DOM. For how Google sees rendered content, see renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. and crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor..
AI summary
A condensed take on the Advanced version:
- SolidJS = fine-grained reactivity, no virtual DOM. Components run once; signals update only the exact DOM nodes that change. Tiny runtime (~7KB), consistently near the top of js-framework-benchmark, faster than React’s re-render model.
- Bare SolidJS is CSR by default — an empty HTML shell. Same Wave-1 indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. problem as bare React/Vue/Angular: GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer.’s first wave sees no content, renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. is queued (hours to weeks), and Bing/social crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. may never see it. Soft-404 risk too (CSR can’t return a real 404).
- SolidStart is the fix, per route — the official meta-framework offers CSR, SSR (sync, async, or streaming), and SSG per route; it doesn’t default the whole project to SSR. SSR/SSG routes put content + metadata in the first response, fully indexable on Wave 1 — verify the specific route rather than assuming site-wide coverage.
- Router and metadata aren’t auto-bundled. SolidStart’s own docs say it
ships without a router or metadata library —
@solidjs/routerand@solidjs/metaare explicit additions the official templates happen to include. - Head tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. via @solidjs/meta:
<Title>,<Meta>,<Link>under<MetaProvider>; deduplication works in SSR; never use raw<title>in server files. - Real 404s with
<HttpStatusCode>; server-side data withcreateAsync(notonMount); History API routing (no hash routes); JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. rendered in the route component. - Accuracy spine: SolidJS hydrates — it is NOT resumable. Resumability is Qwik’s. Fine-grained reactivity is a client-update optimization, not a startup one. Both SSR+hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. and resumability are good for indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed.; Qwik only wins on Time to InteractiveTime to Interactive — a retired Lighthouse lab metric marking the point a page's main sub-resources have loaded and it can reliably respond to input. It was removed from the Lighthouse Performance score in Lighthouse 10 (2023) for being too volatile, was never a Core Web Vital, and still defines the end of the Total Blocking Time measurement window..
- CWVGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. upside is possible, not guaranteed (on SSR’d routes): better LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good., INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good., and CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. are plausible outcomes — but benchmark gaps are synthetic, and real field dataPerformance metrics captured from real users, not lab tests. depends on implementation, data, and hosting, not framework choice alone.
Official documentation
Primary-source documentation from Google and the SolidJS team.
Google — JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript.
- Understand JavaScript SEO Basics — the crawl → render → indexStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. pipeline and the two-wave process.
- Dynamic Rendering as a Workaround — why Google deprecated dynamic renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. in favor of SSR, static renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., and hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers..
- SEO Guide for Web Developers — the developer-facing fundamentals.
SolidJS / SolidStart
- SolidJS documentation — the official docs home.
- Fine-Grained Reactivity — the signals model and how updates target individual DOM nodes.
- SolidStart — the meta-framework: SSR, streaming, routing, server functions.
- SolidStart — Head and Metadata — managing title/meta/link tags for SEO.
- SolidStart — Route Pre-rendering — configuring SSG.
@solidjs/meta
- solid-meta GitHub repository — source and API reference.
- @solidjs/meta on npm — the package.
- Title component docs and Meta component docs.
Quotes from the source
On-the-record statements from Google on JavaScript SEOMaking sure search engines can crawl, render, and index content that depends on JavaScript., plus the SolidJS team’s own framing.
Google — how JavaScript apps are processed
- “Google processes JavaScript web apps in three main phases: 1. CrawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. 2. RenderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. 3. IndexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed..” — Google Search Central. Understand JavaScript SEO Basics
- “It’s fine to use JavaScript to inject links into the DOM, as long as such links follow the best practices for crawlable links.”
— Google Search Central (use
<a href>, notonclickorjavascript:void(0)). Understand JavaScript SEO Basics - “You shouldn’t use JavaScript to change the canonical URLHow search engines pick one canonical URL among duplicates and consolidate signals onto it. to something else than the URL you specified as the canonical URL in the original HTML.” — Google Search Central. Understand JavaScript SEO Basics
- “Use the History API to implement routing between different views of your web app.” — Google Search Central (i.e. no fragment/hash routing). Understand JavaScript SEO Basics
SolidJS team — fine-grained reactivity (paraphrased framing)
- SolidStart’s head-and-metadata docs warn: “Be sure to avoid adding any normal
<title />tags in any server files, as they would override the functionality of @solidjs/meta.” SolidStart — Head and Metadata
SolidJS SEO checklist
A pass to confirm a SolidJS site is crawlable, indexable, and fast:
- You’re using SolidStart with SSR or SSG — not bare SolidJS in CSR mode.
- View Source shows real content and
<a href>links in the raw HTML — not just<div id="root"></div>. - App is wrapped in
<MetaProvider>so head tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. render during SSR. -
<Title>and<Meta name="description">set per route via @solidjs/meta. - No raw
<title>tags in server files (they override @solidjs/meta). - Open GraphOpen Graph (OG) tags are `<meta>` elements in a page's head, defined by the Open Graph protocol (ogp.me, created by Facebook), that describe a page as a shareable object — its title, description, image, URL, and type. They control how a link preview card looks when the page is shared on Facebook, LinkedIn, Slack, Discord, WhatsApp, and iMessage. They are not a direct Google ranking factor, though Google reads og:title, og:image, and og:site_name as inputs to how a result appears. + Twitter tags present via
<Meta property="og:…">so social previews work. - Canonical set with
<Link rel="canonical">(not changed via JS after load). - Routing uses the History API — no hash (
#/page) routes. - Rankable content loaded with
createAsync/server functions, notonMount. - Missing pages return a real 404 via
<HttpStatusCode code={404} />. -
public/robots.txtexists, points to the sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing., and doesn’t block/api/data routes. - XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. generated (e.g.
solid-start-sitemap) with canonical URLsHow search engines pick one canonical URL among duplicates and consolidate signals onto it.. - JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. rendered in the route component and present in the SSR HTML.
- URL InspectionA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. (Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results.) confirms the rendered HTML matches.
- Field Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. checked in CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. / Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance., not just lab.
The mental models
1. Library vs. meta-framework. SolidJS (the library) decides how the UI updates; SolidStart (the meta-framework) decides where it renders. SEO is governed by the second one. Bare SolidJS = CSR = empty shell. SolidStart SSR/SSG = content in the HTML. Always locate which one you’re actually shipping.
2. The renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM.-mode ladder. For any route, pick the highest rung the content allows: SSG (static, fastest, best for stable content) → SSR (dynamic, per-request) → streaming SSR (data-heavy) → CSR (only for non-ranking, authenticated views). Higher rungs are better for both crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. and Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data..
3. Two waves, one goal. Google crawls in Wave 1 (raw HTML) and renders in Wave 2 (queued). The entire point of SolidStart SSR is to make your content complete in Wave 1 so you never depend on the unpredictable Wave 2 queue.
4. HydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. ≠ resumability. SolidJS hydrates (download → execute → attach). Qwik resumes (no re-execution). Fine-grained reactivity speeds the updates after hydration; it doesn’t remove hydration. Keep this straight and you’ll never miscategorize SolidJS.
5. Server-load for anything that must rank.
If content is fetched in onMount, it lands after the HTML is sent — invisible
to Wave 1. Fetch it with createAsync/server functions so it’s baked into the
SSR response.
SolidJS SEO — cheat sheet
SolidJS vs. SolidStart
| SolidJS (library) | SolidStart (meta-framework) | |
|---|---|---|
| Default renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. | CSR (empty shell) | SSR (content in HTML) |
| RenderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. modes | CSR only | SSR, SSG, streaming, CSR |
| Meta tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. in raw HTML | No (set client-side) | Yes (@solidjs/meta + SSR) |
| Real HTTP 404 | No (soft 404A soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing.) | Yes (<HttpStatusCode>) |
| SitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. generation | Manual | solid-start-sitemap plugin |
| SEO verdict (per route) | Risky unless you build in SSR/SSG yourself | Can be SEO-viable — verify each route’s actual rendering mode and output; SolidStart doesn’t guarantee it site-wide |
@solidjs/meta components
| Component | Sets |
|---|---|
<MetaProvider> | Wrapper that collects tags during SSR (required) |
<Title> | <title> |
<Meta> | description, robots, OG, Twitter cardsTwitter Card tags (now often called \"X Cards\") are <meta name=\"twitter:...\"> tags in a page's <head> that tell X's link-unfurling system what rich preview to build for a shared URL — image, headline, description, and (for player cards) an embeddable frame. The four card types are summary, summary_large_image, app, and player. Every twitter:* property falls back to its og:* equivalent if missing — except twitter:card itself, which has no fallback and must be set explicitly. They are not a Google or Bing ranking factor. |
<Link> | canonical, hreflangHreflang is an annotation (in HTML, HTTP headers, or XML sitemaps) that tells search engines which language and optional region a page targets, and which alternate versions exist. It only works when every page in the cluster references all the others., preloadResource hints are <link> elements (or equivalent HTTP Link headers) that tell the browser to do network work — DNS lookups, connection setup, or fetching a resource — earlier than it would discover the need on its own. The main ones are dns-prefetch, preconnect, preload, modulepreload, and prefetch., stylesheets |
<Style> / <Base> | inline <style> / <base> |
Do / don’t
- ✅ Use
<Title>from @solidjs/meta. ❌ Raw<title>in server files. - ✅ History API routing. ❌ Hash (
#/page) routing. - ✅
createAsync/ server functions for rankable data. ❌onMountfetch. - ✅
<HttpStatusCode code={404} />. ❌ Soft 404 (200 + shell).
Myth-busting
- ❌ “SolidJS is resumable like Qwik.” → It hydrates (cheaply); only Qwik resumes.
- ❌ “SolidJS is bad for SEO.” → Bare CSR is; SolidStart SSR/SSG is fully indexable.
- ❌ “Google can’t read SolidJS.” → It can (modern Chromium); the risk is Wave-2 delay, removed by SSR.
SolidJS SEO mistakes to avoid
Shipping public content with bare SolidJS CSR
Why it’s wrong: The first response is an app shell, so crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. do not receive the page’s content or metadata immediately. Do this instead: use SolidStart SSR or route prerenderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. for every public route that needs to rank.
Fetching rankable data in onMount
Why it’s wrong: onMount runs after the server response, leaving the content out
of raw HTML. Do this instead: fetch with createAsync, route loaders, or server
functions so the data is present during SSR.
Forgetting MetaProvider or adding a raw title
Why it’s wrong: Without MetaProvider, @solidjs/meta cannot collect tags for SSR;
a raw <title> in a server file can override its output. Do this instead: wrap
the app in MetaProvider and use <Title>, <Meta>, and <Link> consistently.
Using hash routes or soft 404s
Why it’s wrong: #/page routes are poor discovery targets, and a missing page
that returns HTTP 200HTTP 200 OK is the standard 2xx success status code, meaning the server received, understood, and fulfilled the request and is returning the resource. It's the code every page you want indexed should return — but a 200 alone doesn't guarantee Google will index the page. looks like a soft 404A soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing.. Do this instead: use History API
routes and set a real status with <HttpStatusCode code={404} />.
Calling fine-grained reactivity resumability
Why it’s wrong: SolidJS still hydrates; it does not resume server execution state the way Qwik does. Do this instead: describe Solid’s advantage as efficient client updates, then verify the actual server renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. and field performance.
Trusting SSR without checking the response
Why it’s wrong: A route can use SolidStart and still leave copy, metadata, or JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. in client-only code. Do this instead: inspect View Source and the initial network response after every rendering or data-loading change.
Audit a SolidStart response from the command line
macOS / Linux — inspect status, metadata, and body content
URL="https://example.com/blog/example-post"
curl -sSIL "$URL" | sed -n '1,12p'
curl -sSL "$URL" -o /tmp/solidstart-page.html
grep -Ei '<title>|name="description"|rel="canonical"|<h1|application/ld\+json' \
/tmp/solidstart-page.htmlThe first response should be a real success status for a live route, and the raw HTML should contain the route’s title, description, canonical, H1An H1 tag is the HTML `<h1>` element that marks a page's primary heading — the big visible headline at the top of the content. It helps users, search engines, and screen readers understand what the page is about., and any JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. without running JavaScript.
Windows PowerShell — run the same raw-HTML check
$url = "https://example.com/blog/example-post"
$response = Invoke-WebRequest -Uri $url
$response.StatusCode
$response.Content | Select-String -Pattern '<title>|name="description"|rel="canonical"|<h1|application/ld\+json'Check a missing route returns a true 404
curl -sS -o /dev/null -w '%{http_code}\n' \
'https://example.com/this-route-should-not-exist'
# Expected: 404DevTools Console — list the rendered head signals
({
title: document.title,
description: document.querySelector('meta[name="description"]')?.content,
canonical: document.querySelector('link[rel="canonical"]')?.href,
h1: [...document.querySelectorAll('h1')].map((node) => node.textContent.trim()),
})Run the snippet in the browser Console, but compare it with the command-line result. If a signal exists only in the rendered DOM, it is still being added after the initial HTML response.
Measure SolidStart SEO performance in the field
Largest Contentful Paint by route type
Metric: Field LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good. for public content, marketing, and other representative route groups.
What it tells you: Whether the largest visible content arrives promptly for real users; SSR helps only if data, images, and hosting complete the path.
How to pull it: Use CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. or the Search Console Core Web VitalsThe Google Search Console report (under Experience) that shows how your indexed URLs perform on the Core Web Vitals — LCP, INP, and CLS — using real-user field data from CrUX, grouped by device, status, and clusters of similar-performing URLs. report, segmented by similar URL groups where possible.
Benchmark / realistic range: Use Google’s current field-data classification and the site’s own pre-release baseline; do not substitute a synthetic framework benchmark for user data.
Cadence: Monthly and after a material renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., hosting, or image-delivery change has accumulated field dataPerformance metrics captured from real users, not lab tests..
Interaction to Next Paint
Metric: Field INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good. on interactive SolidJS routes.
What it tells you: Whether fine-grained updates translate into responsive real interactions rather than just favorable library benchmarks.
How to pull it: Use CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. or Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results., then reproduce poor page groups with browser performance tooling to find the long interaction.
Benchmark / realistic range: Compare with Google’s current classification and the route group’s own baseline; the framework alone does not establish a guaranteed range.
Cadence: Monthly and after adding large client-side components or third-party scripts.
Cumulative Layout Shift
Metric: Field CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. for SSR and streaming routes.
What it tells you: Whether hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers., streamed data, images, or late components move content after the initial HTML is displayed.
How to pull it: Use CrUX or Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance. for the standing KPI and DevTools for diagnosis on affected templates.
Benchmark / realistic range: Use Google’s current field-data classification and compare new releases with the established route baseline.
Cadence: Monthly and after changing streaming boundaries, image dimensions, or client-only components.
Patrick's relevant free tools
- SEO Incident Simulator — Practice thirty deterministic technical SEO incident investigations — indexability, crawl controls, redirects, sitemaps, markup, caching, DNS, bot verification, rendering, hreflang, and faceted navigation — with clearly labeled fixture evidence and Find → Fix → Verify handoffs.
- Raw vs. Rendered HTML Checker — See what's in your page's initial HTML versus after JavaScript runs — headless-Chrome rendering only when the page actually needs it, a rendering-strategy verdict (SSR / prerendered / CSR / hybrid), ~15 calibrated JavaScript-SEO checks (noindex, canonicals, robots.txt blocking, links, soft 404s), a side-by-side raw-vs-rendered diff, and shareable reports.
- Page Speed Test & Core Web Vitals Checker — One sentence tells you whether a page passes Core Web Vitals and what to fix first — real Chrome user data (CrUX) with a Lighthouse lab fallback, mobile and desktop side by side, loudly-labeled data sources, and prioritized diagnostic fixes. Plus a bulk origin scorecard with CSV export.
Tools for SolidJS SEO
- View Page Source (browser) — the fastest SSR check. If your content is in
the raw HTML (not just
<div id="root"></div>), SSR is working. - Google Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results. — URL InspectionA Google Search Console feature that reports how Google sees one specific URL on a property you own. By default it shows the last-indexed snapshot; a separate \"Test live URL\" mode fetches the current version. — the source of truth for what GooglebotGooglebot is Google's web crawler — the software that fetches pages so Google can index and rank them. It comes in two variants, Googlebot Smartphone (primary, under mobile-first indexing) and Googlebot Desktop, and runs an evergreen Chromium renderer. crawled and rendered; “View Tested Page → HTML” shows the rendered output.
- Rich ResultsRich results (formerly 'rich snippets') are enhanced search listings — stars, images, prices, breadcrumbs, video thumbnails, and more — that Google and Bing build from structured data. They're a display feature, not a ranking factor, and eligibility never guarantees they'll show. Test — validate JSON-LD structured dataJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal. on a SolidStart page.
- Bing Webmaster ToolsMicrosoft's free portal for monitoring and improving how a site appears in Bing search — the peer to Google Search Console, plus IndexNow instant indexing, richer backlink data, and keyword volumes. Because Bing's index also feeds Microsoft Copilot, it doubles as a window into AI-search visibility. — URL Inspection — shows Bing’s rendered version, important because Bing is more conservative about JavaScript than Google.
- Ahrefs Site Audit (JS renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. enabled) — crawl a SolidJS site the way a renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. crawlerA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. would, surfacing missing metadata and uncrawlable links.
solid-start-sitemap— build-time XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. generation for SolidStart.- CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. / Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance. Core Web Vitals reportThe Google Search Console report (under Experience) that shows how your indexed URLs perform on the Core Web Vitals — LCP, INP, and CLS — using real-user field data from CrUX, grouped by device, status, and clusters of similar-performing URLs. — confirm the INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good./LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good./CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. advantage actually lands for real users, not just in the lab.
- DevTools Network tab — inspect the initial HTML response body to verify SSR content (vs. content injected after JS runs).
Test yourself: SolidJS SEO
Five quick questions on SolidJS, SolidStart, and getting a Solid site indexedStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed.. Pick an answer for each, then check.
Resources worth your time
My writing
- JavaScript SEO Issues & Best Practices — my definitive guide to renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., DOM parityWhether the rendered DOM matches what you expect the raw HTML to become., crawlable links, and getting JS-built content indexedStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed.; the foundation a SolidJS site builds on.
- Core Web Vitals: A Complete Guide — what INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good., LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good., and CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. measure and how they factor into SEO — the metrics SolidJS’s runtime helps with.
- The Beginner’s Guide to Technical SEO — where renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. and framework choice fit in the bigger picture.
My speaking
- SMX Advanced 2018: SEO for JavaScript Frameworks (SlideShare) — my walkthrough of how search engines handle JS frameworks.
- JavaScript SEO — Ungagged 2019 (SlideShare) — rendering modes, the two-wave process, and diagnosis.
From around the industry
- SolidStart — Head and Metadata — the primary-source guide to @solidjs/meta and SSR head tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored..
- SolidStart — Route Pre-rendering — configuring SSG in
app.config.ts. - SolidJS — Fine-Grained Reactivity — signals and no-virtual-DOM updates straight from the docs.
- Google — Understand JavaScript SEO Basics — Google’s own rules for crawlable links, canonicals, and the rendering pipeline.
- solid-start-sitemap plugin — build-time XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. generation for SolidStart.
- js-framework-benchmark (current results) — the long-running benchmark where SolidJS sits near the top and ahead of React on update-heavy work.
SolidJS SEO
SolidJS SEO is the set of practices for making SolidJS apps crawlable, indexable, and fast. Bare SolidJS renders client-side (an empty HTML shell), so SEO depends on using SolidStart for SSR or SSG to put real content and metadata in the initial HTML.
Related: JavaScript SEO
SolidJS SEO
SolidJS is a fine-grained reactive UI library with JSX syntax — similar in developer experience to React, but with no virtual DOM. Components run once, and reactive signals update only the exact DOM nodes that depend on a changed value, which is why SolidJS sits at or near the top of runtime benchmarks. The catch for SEO: out of the box, SolidJS is a client-side renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. (CSR) library. The server sends a near-empty HTML shell, the browser downloads and runs the JS, and only then does content appear — the same indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. problem that affects bare React, Vue, or Angular.
SolidStart is the official meta-framework (the SolidJS equivalent of Next.js or Nuxt). It adds server-side renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM., static site generation, streaming SSR, and file-based routing, so the first response contains fully rendered HTML — crawlable by Google on the first wave, and readable by Bing and social crawlersA crawler — also called a spider or bot — is an automated program that fetches web pages, extracts their links, and queues new URLs to visit. Search engines use crawlers to discover and download content for their index. that may never execute JavaScript. Head tagsMeta tags are HTML elements in a page's head that pass metadata about the page to search engines and browsers. For SEO only a few matter — the title element, the meta description, and the robots meta tag — while meta keywords and most others are ignored. are managed with the @solidjs/meta package (<Title>, <Meta>, <Link> components), and SolidStart’s <HttpStatusCode> lets routes return real HTTP status codesAn HTTP status code is the three-digit number a server returns with every response to tell a browser or crawler what happened to its request — success, redirect, client error, or server error. For SEO the code matters as much as the content: it tells Google and Bing whether to index a page, follow a redirect, retry later, or drop the URL from the index. instead of soft 404sA soft 404 is a URL that returns a success status code (usually 200 OK) even though the page is empty, missing, or shows a 'not found' message. It isn't a status code a server sends — it's a label search engines apply after comparing the response code against the rendered content, and they treat the page like a 404 for indexing..
One distinction matters: SolidJS uses hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers., not resumability. Resumability is Qwik’s architecture. SolidJS’s fine-grained reactivity makes its hydration cheaper than React’s, but the client still downloads and executes the framework before the page is interactive — so the SEO win is largely a Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. (INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good./TBTTotal Blocking Time — the sum of the blocking portion (time above 50 ms) of every long task between First Contentful Paint and Time to Interactive. It's a lab-recommended metric and the lab proxy for INP, not a Core Web Vital.) advantage layered on top of standard SSR.
Related: JavaScript SEO
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Updated Jul 18, 2026.
Editorial summary and recorded change details.Summary
Corrected the SolidStart router/metadata claim against the live docs (they are not auto-bundled — @solidjs/router and @solidjs/meta are explicit project choices), reframed 'SEO-viable' language to be per-route rather than project-wide, version-gated the rendering-mode list to SolidStart's current beta docs, and softened the Core Web Vitals section to avoid promising outcomes the framework alone can't guarantee.
Change details
-
Added a correction, verified live against docs.solidjs.com/solid-start, that SolidStart does not ship with a router or metadata library by default — file-based routing and @solidjs/meta are explicit additions the official templates happen to include, not automatic bundling.
-
Reframed the beginner TL;DR, the SolidStart feature list, and the cheat-sheet 'SEO verdict' row to state rendering mode and SEO viability as a per-route setting, not a whole-project guarantee.
-
Version-gated the rendering-mode list to match the live docs' current terminology (CSR, SSR — sync, async, or streaming — and SSG), noting SolidStart 1.0 is stable but its docs are still labeled beta as of their last update (4/28/26).
-
Softened the Core Web Vitals section from asserting SolidJS 'translates into real wins' to stating it 'can' improve CWV on SSR'd routes, contingent on data, images, and hosting — not the framework alone.
Full comparison unavailable — no prior snapshot was archived for this revision.