JavaScript SEO
Definition
Most generated single-file apps ship an almost empty HTML document: a head, a div with an id of root, and a script that builds everything else once a browser opens it. That is fine for a person and a problem for everything else. Googlebot deals with it in two waves — it crawls the raw HTML first and takes whatever is there, then queues the page for rendering in a headless Chromium instance and indexes what the script eventually produced. Rendering is deferred rather than immediate, and it is not guaranteed: pages can sit in the render queue, and a script that fails, times out or depends on a blocked resource leaves an indexed page containing nothing but that empty div. Other crawlers are stricter still, because most social and chat preview bots never execute JavaScript at all. The discipline is about making the important parts survive every one of those cases.
Why It Matters
The failure is invisible from your own browser. You open the link, the app loads, everything looks right — and the copy in the index is blank, or carries whatever placeholder title the generator left behind. The preview case is worse because it is immediate and public: paste a client-side-rendered link into Slack, LinkedIn, WhatsApp or a chat assistant and the card comes back with no title, no description and no image, because the bot fetched the HTML, found an empty container and stopped there. It does not wait for scripts, it does not run them, and it does not come back later to try again. A link that looks broken in the first place it is shared is a link nobody clicks.
How It Works
The first wave is a plain HTTP fetch: the crawler takes whatever HTML the server returns and pulls out links, the title, meta tags and any text already present. The page then enters a rendering queue, where a current headless browser loads it, runs the scripts, waits for the network to settle and treats the resulting DOM as the version to index. Anything the renderer cannot reach is lost — scripts blocked in robots.txt, files on a host that is down, content that only appears after a click. Links must be real anchor elements with an href, because a div with a click handler that pushes a route is not a link and will not be followed. Titles and meta tags injected by script are usually picked up in the second wave, but never by a preview bot, which is why they belong in the served markup. Check with the URL Inspection tool in Search Console, which shows the rendered HTML Google is actually holding, rather than trusting what your own browser draws.
Real-World Example
Someone generates a sales dashboard in a chat assistant, exports the single HTML file and publishes it at sales-view.99helpers.site. The file is 4 KB of markup and 300 KB of script. Shared in Slack it previews as a bare address with no title; inspected later, the rendered page has content but the indexed title is still the placeholder. Three fixes exist, in rising order of effort: put a real title, meta description and Open Graph tags in the head so every crawler sees them without executing anything; prerender the page once to static HTML and upload that instead; or move to a framework that renders on the server. For a generated single-file app the first fix takes two minutes and solves the preview problem outright.
Common Mistakes
- ✕Checking the page in your own browser and concluding it is fine — your browser runs the script, and the bot that builds the preview card does not
- ✕Leaving the framework's placeholder title in the head — that is what gets indexed and shared, and a preview bot never sees the version the script writes later
- ✕Using div elements with click handlers for navigation — crawlers follow href attributes, so routes reachable only by clicking are invisible
- ✕Assuming rendering is guaranteed because Google can render — it is queued, delayed and occasionally skipped, so nothing essential should depend on it
Related Terms
Prerendering
Prerendering is running a page's JavaScript once, ahead of time, and saving the result as a static HTML file — so that what a crawler downloads is the finished page rather than an empty container.
Search Engine Indexing
Indexing is the step where a search engine stores a fetched page so it can be returned for queries. It happens after crawling, and it does not follow automatically from it.
Client-Side Rendering
A model where the server sends a nearly empty HTML file and JavaScript builds the page in the browser. Nothing is visible until the script has downloaded and run.
Open Graph Tags
Meta tags in the head of a page that tell other sites how to draw a link to it — the title, the summary and the picture in a shared card. Without them a link shows as a bare URL.
Single-File Web App
A single-file web app is a complete, working application contained in one HTML document, with the styles and the JavaScript written inside the same file. Open it in a browser and it runs — there is nothing to install and nothing to build.
Put a file online in seconds
Drop in a document, an image, a page or a whole static website and share the link — free, with no build step and no server to set up.
Host a file free →