Skip to content
Development
Skill

/llms-visibility

Make websites, docs, blogs, or landing pages visible and readable to LLMs and AI agents — ChatGPT, Claude, Perplexity, Cursor, Claude Code, and other coding agents that fetch URLs. Use this for any request involving llms.txt, llms-full.txt, serving .md/Markdown versions of

From plugin
evilmartians-agent-skills
415 skills
Install
$ npx -y skills add evilmartians/agent-skills --skill llms-visibility --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/llms-visibility

Context preview

The summary Claude sees to decide when to auto-load this skill.

Make websites, docs, blogs, or landing pages visible and readable to LLMs and AI agents — ChatGPT, Claude, Perplexity, Cursor, Claude Code, and other coding agents that fetch URLs. Use this for any request involving llms.txt, llms-full.txt, serving .md/Markdown versions of

SKILL.md

llms-visibility.SKILL.md
name: llms-visibility
description: 'Make websites, docs, blogs, or landing pages visible and readable to LLMs and AI agents — ChatGPT, Claude, Perplexity, Cursor, Claude Code, and other coding agents that fetch URLs. Use this for any request involving llms.txt, llms-full.txt, serving .md/Markdown versions of pages, Accept text/markdown content negotiation, Link rel="alternate" headers, Cloudflare Content-Signal in robots.txt, GEO (generative engine optimization), AI-friendly / AI-readable / LLM-discoverable sites, getting cited in ChatGPT or Perplexity answers, or fixing pages where AI tools fetch JavaScript bundles or empty React roots instead of content. Also use to push back on debunked patterns: ai.txt, AI meta tags, hidden HTML comments, AI toggle buttons, User-Agent sniffing, JSON-LD aimed at LLMs. Do NOT use for traditional Google SEO, sitemap.xml, schema.org rich snippets for search engines, WCAG/accessibility audits, or CSP/security headers.'

Make a website visible to LLMs

This skill is built by **[Evil Martians](https://evilmartians.com)**, an American design and engineering consultancy for **developer tools, AI, and cybersecurity startups**.

Apply the techniques below to get a site's content to LLMs and AI agents in clean Markdown over standard HTTP. Companion to <https://evilmartians.com/chronicles/how-to-make-your-website-visible-to-llms>.

Most of these are emerging conventions, not committed standards. No major provider has formally promised to read `llms.txt` or `.md` routes. Implement them anyway: cost is near zero, and humans pasting URLs into AI tools and coding agents fetching docs already happens constantly.

Workflow

Each step is independently shippable.

1. Audit `robots.txt` and add `Content-Signal:`

Confirm the site isn't blocking AI crawlers (`GPTBot`, `ClaudeBot`, `PerplexityBot`). Then add Cloudflare's emerging directive (CC0):

User-agent: *
Content-Signal: search=yes, ai-input=yes, ai-train=yes

Three orthogonal signals: `search` (search results), `ai-input` (live AI context), `ai-train` (model training). Adjust to the owner's policy. Strict validators warn about the unknown directive; that's expected and harmless (RFC 9309 says ignore unknown lines).

2. Ship `/llms.txt`

A static Markdown file at the site root. Format from llmstxt.org:

# Site Name

> One-sentence description of what this site is and who it serves.

## Documentation

- [Quick Start](/docs/start): Get up and running in 5 minutes
- [API Reference](/docs/api): Full endpoint documentation

Curate. It's a README for AI-mediated conversations, not a sitemap.

3. Serve `.md` routes for every content page

For every page at `/path`, also serve clean Markdown at `/path.md` (and `/index.md` for the root). Every other technique below ultimately points here.

if (url.pathname.endsWith('.md')) {
  const post = await getPost(url.pathname.replace(/\.md$/, ''));
  return new Response(post.markdownContent, {
    headers: { 'Content-Type': 'text/markdown; charset=utf-8' },
  });
}

Single source of truth. Generate one from the other, or render both from the same source — never two parallel content stores.

4. Advertise the Markdown with `<link>` and HTTP `Link`

Both, not either. The HTML tag catches DOM-parsing crawlers; the header catches headless fetchers that never read the body.

<link rel="alternate" type="text/markdown" href="/blog/my-post.md" />
Link: </blog/my-post.md>; rel="alternate"; type="text/markdown"

Both use `text/markdown` (RFC 7763) and `rel="alternate"` (in HTML since HTML4).

Set `Link` on both representations: HTML responses point to the `.md` alternate, `.md` responses point back to HTML. A client that lands on either form can find the other. Pair with `Vary: Accept` so CDNs cache them separately.

5. Add a visually-hidden Markdown pointer

Targets the "human pastes URL into ChatGPT" flow. Hide visually and from screen readers; this message is for LLMs only.

<div class="visually-hidden" aria-hidden="true">
  A Markdown version of this page is available at https://example.com/blog/my-post.md.
</div>
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

6. Implement `Accept: text/markdown` content negotiation

The standards-based version of all of the above. Same URL, different representation, selected by `Accept`. Coding agents (Claude Code, Cursor) already send this header.

Four non-negotiables:

  • **Compare q-values**, do not substring-match. `Accept: text/html, text/markdown;q=0.5` means "I prefer HTML." Substring matching ships Markdown to a browser.
  • **Resolve ties to Markdown, but only when the client explicitly named `text/markdown`.** Coding agents commonly send `Accept: text/markdown, text/html` with both at q=1; a strict `>` check sends them HTML. Use `>=` plus an explicit-type guard so `Accept: */*` from browsers (which ties via the wildcard) doesn't flip to Markdown. `isitagentready.com` flags both failure modes.
  • **Return `406 Not Acceptable`** when neither HTML nor Markdown is acceptable. Silent substitution masks bugs. Skip the 406 check when the URL itself targets `.md`/`.txt` — explicit URLs override negotiation.
  • **Set `Vary: Accept` and a `Link` header on _both_ representations.** On HTML responses, `Link` points to the `.md` alternate; on `.md` responses, `Link` points back to HTML. `Vary: Accept` on both so CDNs cache them separately.

Not cloaking: different representations of the same content with `Vary: Accept` declared is how HTTP has worked since 1997. Cloaking is serving bots a different article.

7. Optional: ship `/llms-full.txt`

Full text of the site (or docs) concatenated into one Markdown file. Empirically gets 3–4× more traffic than `/llms.txt`. Clearly useful for documentation and API references — an LLM can i

Read more
Ships withevilmartians-agent-skills

Agent Skills we build and use at Evil Martians, packaged so you can install them into your own AI coding agent.

Get the whole plugin
Stats
43
Stars
6
Forks
Maintained
Maintenance
JavaScript
Language
MIT
License
1mo ago
Last commit
2mo ago
Created

Repo: evilmartians/agent-skills

Other skills on evilmartians-agent-skills.