Free

Để Claude biến site Rails của tôi thành AI-native

Sáu việc thực tế để phục vụ cả người đọc và AI agent từ cùng một site, kèm checklist sao chép được


Trong bốn ngày qua, tôi và Claude Code đã biến smarts.md từ một site tài liệu smart contract dành cho con người thành một site dành cho AI agent.

Nghe thì giống nhau. Nhưng khác xa. Site cho con người tối ưu tính dễ đọc, khả năng tìm kiếm và tốc độ tải. Site cho AI agent phải trả lời một loạt câu hỏi khác:

  • AI crawler có tìm được bạn không, hay robots.txt mặc định đang khóa chúng ngoài cửa?
  • AI có thể bỏ qua việc render HTML và lấy thẳng nội dung sạch không?
  • AI có thể gọi tool của bạn mà không cần "đọc tài liệu" trước không?
  • Từng trang có nói cho AI biết chính xác cách tham chiếu và cách truy vấn trang đó không?

Đây là 6 thứ tôi đã nhờ Claude dựng. Mỗi thứ đều có thể dùng độc lập và mang sang site của bạn.

1. Chào đón AI crawler một cách rõ ràng trong robots.txt

Phần lớn site kế thừa robots.txt từ một template cũ, mặc định chặn các User-Agent lạ. Nhưng sau 2025, nhiều AI crawler là User-Agent mới — GPTBot, ClaudeBot, PerplexityBot, Applebot-Extended, Google-Extended, CCBot, meta-externalagent, v.v. Muốn mời chúng vào thì phải Allow rõ ràng.

robots.txt của smarts mở đầu bằng một ghi chú chính sách, sau đó liệt kê User-agent + Allow: / cho 12 crawler bao gồm OpenAI, Anthropic, Perplexity, Google Gemini, Apple, Common Crawl, Meta và Cohere. Lập trường rất rõ: site này sinh ra là để AI đọc.

2. llms.txt — thực đơn dành cho LLM

llms.txt là quy ước do llmstxt.org đề xuất: đặt một file Markdown ngắn gọn ở gốc site, nói với LLM site này là gì, dùng thế nào và các cửa ngõ chính ở đâu. Nó là elevator pitch của site bạn.

llms.txt của smarts dài khoảng 60 dòng:

  • Một câu định vị (Live docs for every verified smart contract)
  • Cách dùng từ AI agent (endpoint MCP, lệnh cấu hình một dòng)
  • Mẫu URL (/{chain}/{address} vs slug ngắn)
  • Danh sách tool MCP kèm mô tả một câu
  • Danh sách contract chọn lọc (cung cấp cho LLM "đáp án mặc định")
  • Phạm vi và giới hạn (chain nào không hỗ trợ, chính sách cache)

Ý chính: LLM trả token để đọc tài liệu của bạn, nên nó sẽ không crawl toàn site. Đưa cho nó một index đã được chắt lọc, hit rate sẽ tăng hẳn.

3. .well-known/mcp.json — đặt cược sớm

Giao thức MCP chưa chuẩn hóa quy ước discovery kiểu /.well-known/openid-configuration. Hiện chưa có client công khai nào crawl một well-known path cố định.

Nhưng xuất bản manifest này chỉ tốn 30 dòng:

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

Khi nào một quy ước discovery xuất hiện, tôi không phải sửa một dòng. Đồng thời đây cũng là tự tài liệu hóa cho dev — ai tò mò MCP của tôi cứ curl smarts.md/.well-known/mcp.json là đủ.

Mấu chốt: mảng tools được sinh từ hằng MCP_TOOLS, single source of truth. Một test cấu trúc có sẵn ép mọi app/tools/*_tool.rb phải xuất hiện trong hằng đó, nên manifest kế thừa đảm bảo "tool mới không bị bỏ quên" miễn phí.

4. Biến thể .md: bản chắt lọc thân thiện WebFetch cho mọi trang

Đây là phần tôi thích nhất. WebFetch của Claude Code phải tự dọn và bóc nội dung từ HTML bất kỳ — tốn token và không ổn định. Nếu bạn chủ động đưa .md thì sao?

respond_to của Rails hỗ trợ sẵn:

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

https://smarts.md/usdc-eth trả về HTML; https://smarts.md/usdc-eth.md trả về 40 dòng Markdown — địa chỉ, chain, phân loại, endpoint MCP, cách truy vấn qua AI agent, link gốc.

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

Một cú fetch, toàn bộ nội dung có cấu trúc mà AI agent cần nằm ở đó, không cần DOM parser. Claude làm phần này rất nhanh — một controller, hai template .md.erb, thêm (.:format) vào routes, xong.

5. Card MCP trên mỗi trang: để người dùng trỏ AI của họ về đây

Đây là discovery theo chiều ngược: một phần visitor của tôi đã dùng Claude Code / Cursor / Windsurf. Họ vào một trang contract, bước tiếp theo thường là "cho AI của mình nhìn qua cái này".

Vậy nên mỗi trang contract đều render một card với:

  • Reference: slug được chọn lọc (ví dụ usdc-eth) hoặc chain/address, kèm nút Copy
  • Sample prompt: "Tell me the current state of usdc-eth", kèm nút Copy
  • Chưa cắm MCP?: một dòng trỏ tới mcp.smarts.md (setup một dòng lệnh)

Chỉ một cú click ma sát giữa "tôi đang nhìn contract này" và "tôi đang hỏi AI". Card dùng card của DaisyUI và một Stimulus controller copy dùng chung — 50 dòng erb. Một test hồi quy khóa các thuộc tính data-copy-text-value để refactor tương lai không lặng lẽ dán chuỗi sai vào clipboard người dùng.

6. SEO truyền thống, nhưng dùng schema.org cho đúng

OpenGraph, Twitter Card, JSON-LD — lớp truyền thống cho tìm kiếm và social card. Đáng làm, vì AI crawler cũng đọc ở đây.

Điều thú vị là JSON-LD nên mô tả một smart contract thế nào. Claude chọn WebPage bọc SoftwareApplication:

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

operatingSystem nhét tên chain, identifier nhét địa chỉ, additionalType nhét phân loại (ví dụ "Uniswap V3 Pool"). schema.org chưa có type dành riêng cho SmartContract, nhưng SoftwareApplication cộng mấy field này đủ để LLM hiểu "đây là một contract chạy trên Ethereum, có địa chỉ định danh rõ ràng".

Ảnh OG là summary_large_image 1200×630; Twitter Card, breadcrumb, softwareVersion, license đều được điền đủ.

Toàn bộ việc này tốn bao nhiêu công

Sáu mục trên đến từ bảy PR trong bốn ngày:

PR Số file Kích thước
feat/ai-crawler-discovery 2 ~126 dòng
feat/well-known-mcp-manifest 4 ~129 dòng
feat/markdown-contract-pages 6 ~298 dòng
feat/contract-mcp-card 3 ~126 dòng
feat/seo-meta-tags 8 ~292 dòng
feat/seo-enrichments 8 ~189 dòng
feat/og-card

Mỗi cái đều là PR độc lập với test và commit message riêng. Nhịp chia nhỏ thế này là điều giá trị nhất khi làm với Claude — từng PR đủ nhỏ để review diff trong một cái nhìn, nhưng xếp chồng lại thì site đã mọc ra một bề mặt AI hoàn chỉnh.

Một checklist sao chép được

Nếu bạn có một site nội dung và muốn thân thiện với AI, làm theo thứ tự này:

  1. Allow rõ ràng các AI crawler chính trong robots.txt
  2. Viết /llms.txt (một menu đã được chắt lọc)
  3. Thêm biến thể .md cho các trang nội dung chính
  4. Nếu bạn chạy MCP server, publish /.well-known/mcp.json
  5. Đặt card "hỏi AI của bạn về trang này" trên các trang nội dung
  6. Điền JSON-LD / OpenGraph bằng type schema.org phù hợp với nội dung

Phần lớn SEO engineer sẽ không nói cho bạn năm cái đầu — không có trong playbook SEO truyền thống. Nhưng nhìn từ bốn ngày dữ liệu của tôi, đường tăng traffic AI và đường traffic con người là hai chuỗi độc lập hoàn toàn. Bạn phải phục vụ cả hai.