Free

Как Claude сделал мой Rails-сайт AI-native

Шесть практических шагов, чтобы сайт одновременно служил людям и AI-агентам, с готовым чек-листом


Последние четыре дня мы с Claude Code превращали smarts.md из сайта с документацией смарт-контрактов для людей в сайт для AI-агентов.

Звучит как одно и то же. Это не так. Сайт для людей оптимизируется под читаемость, поиск и скорость загрузки. Сайту для AI-агентов надо отвечать на другие вопросы:

  • Смогут ли AI-краулеры до тебя добраться или стандартный robots.txt запирает их снаружи?
  • Может ли AI пропустить рендер HTML и забрать чистый контент напрямую?
  • Может ли AI вызвать твои инструменты, не «читая документацию» сначала?
  • Подсказывает ли каждая страница AI, как на неё ссылаться и как её опрашивать?

Вот шесть вещей, которые я попросил Claude построить. Каждая полезна сама по себе, её можно взять в свой сайт отдельно.

1. Явно пригласить AI-краулеров в robots.txt

Большинство сайтов наследуют robots.txt из какого-то старого шаблона, который неявно блокирует любого неизвестного User-Agent. Но после 2025 года многие AI-краулеры — это новые User-Agent: GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent и другие. Чтобы пустить их внутрь, надо явно указать Allow.

robots.txt у smarts начинается с заметки о политике, а затем перечисляет User-agent + Allow: / для 12 краулеров — OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta, Cohere. Позиция прямая: этот сайт существует, чтобы его читали AI.

2. llms.txt — меню для LLM

llms.txt — соглашение, которое предлагает llmstxt.org: кладёшь короткий Markdown в корень сайта, объясняющий LLM что это за сайт, как его использовать и где ключевые точки входа. Своего рода elevator pitch сайта.

llms.txt у smarts — около 60 строк:

  • Позиционирование одной строкой (Live docs for every verified smart contract)
  • Как использовать из AI-агента (MCP endpoint, однострочный setup)
  • Паттерны URL (/{chain}/{address} vs короткий slug)
  • Список инструментов MCP с односложным описанием
  • Курированный список контрактов (даёт LLM «ответы по умолчанию»)
  • Границы и ограничения (какие сети не поддерживаются, политика кеша)

Суть: LLM платит токенами за чтение твоей документации, поэтому не будет краулить весь сайт. Подсунь ему дистиллят — и попадание в цель резко вырастет.

3. .well-known/mcp.json — ставка заранее

Протокол MCP пока не стандартизировал соглашение об автообнаружении типа /.well-known/openid-configuration. Сегодня ни один публичный клиент не обходит фиксированный well-known-путь.

Но опубликовать манифест — это 30 строк:

def well_known_mcp
  response.set_header("Cache-Control", "public, max-age=3600")
  response.set_header("Access-Control-Allow-Origin", "*")
  render json: {
    name: "smarts",
    version: "0.1.0",
    description: "...",
    protocol_version: "2024-11-05",
    transports: [{ type: "sse", endpoint: "https://smarts.md/mcp/sse" }],
    capabilities: { tools: true, resources: false, prompts: false },
    tools: MCP_TOOLS.map { |t| { name: t[:name], description: t[:blurb] } }
  }
end

Как только соглашение появится — не меняю ни строки. И это самодокументация для разработчиков — кто захочет увидеть мой MCP, просто curl smarts.md/.well-known/mcp.json.

Ключ: массив tools выводится из константы MCP_TOOLS — единый источник правды. Существующий структурный тест требует, чтобы каждый app/tools/*_tool.rb попал в эту константу, так что манифест бесплатно наследует гарантию «новый инструмент не забудется».

4. Вариант .md: WebFetch-friendly дистиллят каждой страницы

Моё любимое. Инструмент WebFetch у Claude Code должен сам чистить и вытягивать контент из произвольного HTML — это дорого по токенам и ненадёжно. А если сразу отдавать .md?

respond_to в Rails поддерживает это нативно:

# config/routes.rb
get ":slug(.:format)", to: "contracts#show",
    constraints: { slug: ContractSlugs::ROUTE_PATTERN, format: /html|md/ }

https://smarts.md/usdc-eth возвращает HTML; https://smarts.md/usdc-eth.md возвращает 40 строк Markdown — адрес, сеть, классификацию, endpoint MCP, как опрашивать из AI-агента, ссылки на источник.

# USD Coin on Ethereum

- **Address:** `0xa0b8...`
- **Chain:** Ethereum
- **Classification:** ERC-20 Token

## Query via AI agent

- **MCP endpoint:** `https://smarts.md/mcp/sse`
- **Reference:** `usdc-eth`
- **Sample prompt:** "Tell me the current state of usdc-eth"

Один fetch — вся нужная агенту структура внутри, никакого DOM-парсера. Claude сделал это быстро — один контроллер, два шаблона .md.erb, (.:format) в routes, готово.

5. MCP-карточка на каждой странице: пусть пользователи направят свой AI сюда

Это обратное обнаружение: часть моих посетителей уже пользуется Claude Code / Cursor / Windsurf. Попадают на страницу контракта, а следующий импульс — «дай моему AI посмотреть».

Поэтому на каждой странице контракта рендерится карточка:

  • Reference: курированный slug (например, usdc-eth) или chain/address, с кнопкой «Копировать»
  • Sample prompt: «Tell me the current state of usdc-eth», с кнопкой «Копировать»
  • Ещё не подключил AI?: указатель на mcp.smarts.md (setup в одну строку)

Между «я смотрю на этот контракт» и «я спрашиваю свой AI» остаётся один клик трения. Карточка построена на карточке DaisyUI и общем Stimulus-контроллере copy — 50 строк erb. Регрессионный тест фиксирует атрибуты data-copy-text-value, чтобы будущий refactor не вставил пользователям тихо неверную строку в буфер обмена.

6. Классическое SEO, но schema.org по-взрослому

OpenGraph, Twitter Card, JSON-LD — традиционный слой для поиска и социальных карточек. Делать стоит, потому что AI-краулеры тоже читают это.

Самое интересное — как JSON-LD должен описывать смарт-контракт. Claude выбрал WebPage, оборачивающий SoftwareApplication:

{
  "@type": "WebPage",
  "about": {
    "@type": "SoftwareApplication",
    "name": "USD Coin",
    "applicationCategory": "SmartContract",
    "operatingSystem": "Ethereum",
    "identifier": "0xa0b8..."
  }
}

В operatingSystem — имя сети, в identifier — адрес, в additionalType — классификация (например, «Uniswap V3 Pool»). У schema.org нет отдельного типа SmartContract, но SoftwareApplication плюс эти поля хватает, чтобы LLM понял: «это контракт на Ethereum с конкретным адресом».

OG-картинка — summary_large_image 1200×630; Twitter Card, хлебные крошки, softwareVersion и license довершают картину.

Сколько вообще это работы

Шесть пунктов выше — это семь PR за четыре дня:

PR Файлов Размер
feat/ai-crawler-discovery 2 ~126 loc
feat/well-known-mcp-manifest 4 ~129 loc
feat/markdown-contract-pages 6 ~298 loc
feat/contract-mcp-card 3 ~126 loc
feat/seo-meta-tags 8 ~292 loc
feat/seo-enrichments 8 ~189 loc
feat/og-card

Каждый — самостоятельный PR со своими тестами и commit-сообщением. Этот ритм мелкой нарезки — самое ценное в работе с Claude: каждый PR достаточно мал, чтобы прочитать diff одним взглядом, но в сумме на сайте выросла полноценная AI-поверхность.

Чек-лист для копирования

Если у тебя контентный сайт и ты хочешь сделать его AI-дружелюбным, делай в этом порядке:

  1. Явно разрешить основных AI-краулеров в robots.txt
  2. Написать /llms.txt (дистиллированное меню)
  3. Добавить вариант .md для основных контентных страниц
  4. Если у тебя есть MCP-сервер, опубликовать /.well-known/mcp.json
  5. На контентные страницы положить карточку «спроси свой AI про эту страницу»
  6. Заполнить JSON-LD / OpenGraph подходящими типами schema.org

Первые пять тебе не расскажет большинство SEO-инженеров — их нет в традиционном playbook. Но по моим данным за четыре дня, кривая AI-трафика и кривая человеческого трафика — это две совершенно независимые линии. Обслуживать нужно обе.