# Content that needs no JavaScript

> Content that needs no JavaScript: If content is only produced client-side, the page is empty for agents that do not run JavaScript.

- Source: /checks/no-js-fallback
- Site: AgenticWebScore
- Language: English

---
If content is only produced client-side, the page is empty for agents that do not run JavaScript.

| Property | Value |
| --- | --- |
| Check id | `no-js-fallback` |
| Dimension | Content Accessibility (22%) |
| Tier | Essential — pool 80 pts |
| Weight inside tier | 2 |
| Impact | High |
| Maturity | Adopted — A ratified standard with real deployment. |
| Conditional | No |
| Publishing skill | `server-rendering` |
| Standards | — |

## What is measured

The scanner fetches the homepage `/` without executing JavaScript, removes `<script>`, `<style>`, `<noscript>` and `<template>` blocks and measures the visible text that remains. Pass when the static HTML holds at least 400 characters of text plus an `<h1>`; partial when 100-399 characters remain, or when all the copy sits inside `<noscript>`; fail below 100 characters, the signature of `<div id="root"></div>` filled entirely on the client.

## Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

```bash
DOMAIN="https://example.com"
curl -sL "$DOMAIN/" | perl -0777 -pe 's{<(script|style|noscript|template)[^>]*>.*?</\1>}{}gsi; s/<[^>]*>/ /g; s/\s+/ /g' | wc -m
```

## The fix

This is the artifact to ship. It is the complete change, not a description of one.

```javascript
import express from 'express';
const app = express();

const pages = {
  '/': { title: 'Agent readiness audit', body: '<p>We measure how well your site serves AI agents.</p>' },
  '/pricing': { title: 'Pricing', body: '<p>Audits start at $490 per site.</p>' },
};

// The first byte already contains the content: no JavaScript is needed to read the page.
app.use((req, res) => {
  const page = pages[req.path] ?? { title: 'Not found', body: '<p>Try the homepage.</p>' };
  res.status(pages[req.path] ? 200 : 404).type('html').send(`<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>${page.title}</title></head>
<body><main><h1>${page.title}</h1>${page.body}</main>
<script type="module" src="/app.js"></script></body></html>`);
});

app.listen(3000);
```

> Escape any user data before interpolating it, and keep the client bundle an enhancement: the text has to be in the HTML before the script runs.

## Related checks

| Check | Tier | Impact | Same skill |
| --- | --- | --- | --- |
| `markdown-negotiation` — Markdown content negotiation | Recommended | Critical | — |
| `headings` — Semantic heading structure | Essential | High | — |
| `meta` — Title and summary metadata | Essential | High | — |
| `jsonld` — JSON-LD structured data | Essential | Critical | — |
| `faq-schema` — FAQ / question-answer schema | Recommended | High | — |
| `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — |
| `summary` — Prominent summary block | Recommended | Medium | — |
| `lang` — Language declaration and multilingual access | Recommended | Medium | — |
