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 — адресу, мережу, класифікацію, MCP endpoint, як запитувати з 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». Картка використовує card із 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-трафіку і крива людського трафіку — це дві повністю незалежні серії. Треба обслуговувати обидві.