Free

Jak Claude zamienił mój serwis Rails w AI-native

Sześć praktycznych ruchów, by serwis obsługiwał zarówno ludzi, jak i agentów AI, z gotową checklistą


Przez ostatnie cztery dni razem z Claude Code przerobiliśmy smarts.md z serwisu dokumentacji smart kontraktów zbudowanego dla ludzi w serwis zbudowany dla agentów AI.

Brzmi jak to samo. Nie jest. Serwis dla ludzi optymalizuje czytelność, wyszukiwanie i czas ładowania. Serwis dla agentów AI musi odpowiadać na inne pytania:

  • Czy crawlery AI w ogóle do ciebie dotrą, czy domyślny robots.txt zamyka im drzwi?
  • Czy AI może pominąć renderowanie HTML i pobrać czystą treść wprost?
  • Czy AI może wywołać twoje narzędzia bez wcześniejszego „czytania dokumentacji"?
  • Czy każda strona mówi AI dokładnie, jak się na nią powoływać i jak ją odpytywać?

Oto sześć rzeczy, które kazałem Claude zbudować. Każda jest użyteczna samodzielnie i możesz ją przenieść do swojego serwisu osobno.

1. Witaj crawlery AI wprost w robots.txt

Większość serwisów dziedziczy robots.txt po jakimś starym szablonie, który domyślnie blokuje każdego nieznanego User-Agenta. Ale po 2025 roku wiele crawlerów AI to nowe User-Agenty — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent i inni. Jeśli chcesz ich wpuścić, musisz jawnie dać Allow.

robots.txt w smarts zaczyna się notatką polityki, a dalej wymienia User-agent + Allow: / dla 12 crawlerów obejmujących OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta i Cohere. Stanowisko jest proste: ten serwis istnieje po to, by czytały go AI.

2. llms.txt — menu dla LLM-ów

llms.txt to konwencja zaproponowana przez llmstxt.org: wrzucasz zwięzły Markdown w korzeniu serwisu, który mówi LLM-owi, czym jest ten serwis, jak go używać i gdzie są kluczowe punkty wejścia. To elevator pitch twojego serwisu.

llms.txt w smarts ma około 60 linii:

  • Jednozdaniowe pozycjonowanie (Live docs for every verified smart contract)
  • Jak używać z agenta AI (endpoint MCP, jednolinijkowa komenda setupu)
  • Wzorce URL (/{chain}/{address} vs krótki slug)
  • Narzędzia MCP z jednozdaniowymi opisami
  • Kuratorowana lista kontraktów (daje LLM-owi „domyślne odpowiedzi")
  • Zakres i ograniczenia (które sieci nie są wspierane, polityka cache)

Kluczowa myśl: LLM-y płacą tokenami za czytanie dokumentacji, więc nie przeglądają całego serwisu. Podaj im destylowany indeks — trafialność wyraźnie rośnie.

3. .well-known/mcp.json — wczesny zakład

Protokół MCP nie znormalizował jeszcze konwencji autowykrywania w stylu /.well-known/openid-configuration. Dziś żaden publiczny klient nie przeszukuje stałej ścieżki well-known.

Ale publikacja manifestu to 30 linii:

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

W chwili, gdy konwencja wykrywania się pojawi, nie muszę ruszać ani linii. A poza tym to samodokumentacja dla deweloperów — kto ciekaw mojego MCP, po prostu robi curl smarts.md/.well-known/mcp.json.

Myk: tablica tools wywodzi się ze stałej MCP_TOOLS, jedno źródło prawdy. Istniejący strukturalny test wymusza, żeby każdy app/tools/*_tool.rb pojawiał się w tej stałej, więc manifest darmo dziedziczy gwarancję „żaden nowy tool się nie zgubi".

4. Wariant .md: destylacja przyjazna WebFetch dla każdej strony

Mój ulubiony. Narzędzie WebFetch w Claude Code musi samo czyścić i wyciągać treść z dowolnego HTML-a — drogo tokenowo i zawodnie. A co, jeśli od razu podajemy .md?

respond_to w Railsach wspiera to natywnie:

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

https://smarts.md/usdc-eth zwraca HTML; https://smarts.md/usdc-eth.md zwraca 40 linii Markdowna — adres, sieć, klasyfikacja, endpoint MCP, jak odpytać przez agenta AI, linki źródłowe.

# 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"

Jeden fetch — cała strukturyzowana treść, której chce agent AI, jest w środku, bez potrzeby parsera DOM. Claude zrobił to szybko — jeden controller, dwa szablony .md.erb, (.:format) w routes, gotowe.

5. Karta MCP na każdej stronie: pozwól użytkownikom skierować swoje AI tutaj

To odwrotne wykrywanie: część moich gości używa już Claude Code / Cursor / Windsurf. Lądują na stronie kontraktu, a kolejny odruch brzmi „niech moje AI na to zerknie".

Dlatego każda strona kontraktu renderuje kartę z:

  • Reference: kuratorowany slug (np. usdc-eth) albo chain/address, z przyciskiem Kopiuj
  • Sample prompt: „Tell me the current state of usdc-eth", z przyciskiem Kopiuj
  • Nie masz jeszcze podpiętego AI?: wskazanie na mcp.smarts.md (setup w jednej linijce)

Między „patrzę na ten kontrakt" a „pytam swoje AI" zostaje jedno kliknięcie tarcia. Karta używa card z DaisyUI i ogólnego Stimulus-controllera copy — 50 linii erb. Test regresji blokuje atrybuty data-copy-text-value, żeby przyszły refactor po cichu nie wkleił użytkownikom złego ciągu znaków do schowka.

6. Klasyczne SEO, ale ze schema.org zrobionym jak należy

OpenGraph, Twitter Card, JSON-LD — tradycyjna warstwa wyszukiwania i kart społecznościowych. Warto, bo crawlery AI też to czytają.

Ciekawy wybór to, jak JSON-LD powinien opisać smart kontrakt. Claude zdecydował się na WebPage opakowujący SoftwareApplication:

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

operatingSystem dostaje nazwę sieci, identifier adres, additionalType klasyfikację (np. „Uniswap V3 Pool"). schema.org nie ma dedykowanego typu SmartContract, ale SoftwareApplication plus te pola wystarcza, by LLM zrozumiał „to jest kontrakt na Ethereum o konkretnym adresie".

Obraz OG to summary_large_image 1200×630; Twitter Card, breadcrumbs, softwareVersion i license dopełniają całość.

Ile to w sumie pracy

Sześć punktów wyżej wyszło z siedmiu PR-ów w cztery dni:

PR Pliki Rozmiar
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

Każdy to niezależny PR z własnymi testami i komunikatem commita. Ten rytm drobnego cięcia to najcenniejsza rzecz we współpracy z Claude — każdy PR jest na tyle mały, by przejrzeć diff jednym spojrzeniem, ale poukładane razem pokazują, że serwisowi wyrosła kompletna powierzchnia AI.

Lista do skopiowania

Jeśli masz serwis treściowy i chcesz, by był AI-przyjazny, rób to w takiej kolejności:

  1. W robots.txt jawnie Allow głównych crawlerów AI
  2. Napisz /llms.txt (destylowane menu)
  3. Dodaj wariant .md do głównych stron treści
  4. Jeśli prowadzisz serwer MCP, opublikuj /.well-known/mcp.json
  5. Na stronach treści postaw kartę „zapytaj swoje AI o tę stronę"
  6. Wypełnij JSON-LD / OpenGraph odpowiednimi dla treści typami schema.org

Pierwszych pięciu nie powie ci większość inżynierów SEO — nie ma ich w klasycznym playbooku. Ale z czterech dni danych po mojej stronie krzywa ruchu AI i krzywa ruchu ludzkiego to dwa kompletnie niezależne szeregi. Trzeba obsługiwać oba.