Files
hanzo.ai/app/robots.ts
zeekay 4449d9234a agents: auth.md, an MCP server card, a skills index, content signals
robots.txt states its Content Signals in both groups: search, ai-input
and ai-train, which the groups already allow. /auth.md says how an
agent gets a credential today (wallet sign-in, device flow, an API key)
and that the auth.md registration protocol is not implemented.

/.well-known/mcp/server-card.json describes the MCP endpoint at
api.hanzo.ai/v1/mcp (SEP-2127, protocol 2026-07-28), and the API
catalog names it. skill.mjs writes /skill.md again as an Agent Skill
with its index (Agent Skills Discovery 0.2.0), the digest taken from
the bytes it writes. wellknown.mjs copies subdirectories and refuses a
server card that does not point at the API host.
2026-10-26 20:41:36 -07:00

59 lines
2.1 KiB
TypeScript

import type { MetadataRoute } from 'next'
import { DISALLOW } from '@/lib/publish'
// Static export: emits /robots.txt at build.
export const dynamic = 'force-static'
/**
* The AI crawlers, named so that reading this file answers whether each one is
* welcome rather than leaving it to inference from `*`. A crawler that finds a
* group with its own name obeys that group alone (RFC 9309 §2.2.1), so each
* named group carries the same Disallow lines as `*`; written once, here.
*
* Bytespider is not named: whether it is welcome is the owner's decision, and
* until it is made it reads the `*` group like any other crawler.
*/
const AGENTS = [
'GPTBot',
'OAI-SearchBot',
'ChatGPT-User',
'ClaudeBot',
'Claude-User',
'Claude-SearchBot',
'anthropic-ai',
'PerplexityBot',
'Perplexity-User',
'Google-Extended',
'CCBot',
'Applebot-Extended',
]
/**
* What a crawler may do with what it reads (https://contentsignals.org). It
* states what the groups below already grant: search engines, the agents that
* fetch for a person (ChatGPT-User, Claude-User, Perplexity-User) and the
* training crawlers (GPTBot, Google-Extended, CCBot) are each allowed `/`. In
* both groups, because a named crawler reads its own group alone.
*/
const SIGNAL = { 'Content-Signal': 'search=yes, ai-input=yes, ai-train=yes' }
export default function robots(): MetadataRoute.Robots {
return {
// DISALLOW, not the route prefixes: lib/publish turns one prefix into the
// pair of RFC 9309 patterns that mean it, and this surface cannot spell a
// bare prefix. `Disallow: /auth` reads as a string and takes /authz with
// it; `/auth$` + `/auth/` is the same segment written in the crawler's own
// grammar.
//
// Private routes only. An unapproved route is deliberately fetchable, so
// that the `noindex` it carries is read — a Disallow here would be the one
// thing that prevents it.
rules: [
{ userAgent: '*', allow: '/', disallow: [...DISALLOW], other: SIGNAL },
{ userAgent: AGENTS, allow: '/', disallow: [...DISALLOW], other: SIGNAL },
],
sitemap: 'https://hanzo.ai/sitemap.xml',
host: 'https://hanzo.ai',
}
}