Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

seo.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

seo.tsBlame122 lines · 2 contributors
5618f9aClaude1/**
a0071d7ccanty labs2 * SEO + agent-discovery routes: robots.txt, sitemap.xml, llms.txt.
5618f9aClaude3 *
4 * robots.txt — allow crawlers on public surfaces, disallow admin/settings
5 * and API write paths.
6 * sitemap.xml — lists the stable public URLs (landing, explore, status,
7 * marketplace, graphql explorer, shortcuts, terms). Public repo URLs are
8 * not enumerated here — those live behind /explore which crawlers follow.
a0071d7ccanty labs9 * llms.txt — the llmstxt.org convention: a curated map of the platform for
10 * AI agents, pointing at the MCP endpoint, API docs, and OAuth discovery so
11 * any LLM/agent can orient itself and connect.
5618f9aClaude12 */
13
14import { Hono } from "hono";
a0071d7ccanty labs15import { config } from "../lib/config";
5618f9aClaude16
17const seo = new Hono();
18
19const ROBOTS = `User-agent: *
20Allow: /
21Disallow: /admin
22Disallow: /settings
23Disallow: /api/
24Disallow: /login
25Disallow: /register
26Disallow: /logout
27Disallow: /oauth/
28Disallow: /*/settings
29Disallow: /*.git/
30
31Sitemap: /sitemap.xml
32`;
a0071d7ccanty labs33// Note: /llms.txt is intentionally allowed (agent-facing map, public).
5618f9aClaude34
35seo.get("/robots.txt", (c) => {
36 c.header("Content-Type", "text/plain; charset=utf-8");
37 c.header("Cache-Control", "public, max-age=3600");
38 return c.body(ROBOTS);
39});
40
a0071d7ccanty labs41/**
42 * llms.txt (llmstxt.org) — a curated, agent-facing map of the platform.
43 * Served at both /llms.txt and /.well-known/llms.txt. Built from the live
44 * base URL so links are always absolute + correct for this deployment.
45 */
46function buildLlmsTxt(): string {
47 const b = config.appBaseUrl;
48 return `# Gluecron
49
50> AI-native git hosting. Git over HTTPS + SSH, issues, pull requests with AI
51> code review and gated auto-merge, CI workflows, package + container
52> registries, and a Model Context Protocol (MCP) server so any LLM/agent can
53> read and drive repositories directly. Self-hosted-friendly and MCP-native.
54
55## For AI agents
56
57- [MCP server](${b}/mcp): Model Context Protocol endpoint (JSON-RPC 2.0 over HTTP). GET for discovery, POST to call tools. Read tools work anonymously on public repos; write tools require an OAuth/PAT bearer token.
58- [OAuth authorization server metadata](${b}/.well-known/oauth-authorization-server): RFC 8414 — how to authenticate (authorize/token endpoints, PKCE S256, scopes).
59- [OAuth protected resource metadata](${b}/.well-known/oauth-protected-resource): RFC 9728 — which authorization server guards the MCP resource.
60
61## API
62
63- [REST + GraphQL API docs](${b}/api/docs): endpoints, authentication, and scopes for programmatic access.
64- [GraphQL explorer](${b}/api/graphql): read queries over repos, users, issues, and search.
65
66## Get started
67
68- [Sign up](${b}/register): create an account.
69- [Explore public repos](${b}/explore): browse what's hosted here.
70- [Import from GitHub](${b}/import): mirror an existing repo in one step.
71- [Install script](${b}/install): one-line setup for the CLI + Claude Desktop MCP config.
72
73## Conventions
74
75- Personal access tokens are prefixed \`glc_\`; OAuth access tokens \`glct_\`. Pass either as \`Authorization: Bearer <token>\`.
76- Repos are addressed as \`${b}/<owner>/<repo>\`; clone over HTTPS at \`${b}/<owner>/<repo>.git\`.
77`;
78}
79
80seo.get("/llms.txt", (c) => {
81 c.header("Content-Type", "text/plain; charset=utf-8");
82 c.header("Cache-Control", "public, max-age=3600");
83 return c.body(buildLlmsTxt());
84});
85
86seo.get("/.well-known/llms.txt", (c) => {
87 c.header("Content-Type", "text/plain; charset=utf-8");
88 c.header("Cache-Control", "public, max-age=3600");
89 return c.body(buildLlmsTxt());
90});
91
5618f9aClaude92const STATIC_PATHS = [
93 "/",
94 "/explore",
95 "/marketplace",
96 "/status",
80bed05Claude97 "/help",
5618f9aClaude98 "/shortcuts",
99 "/api/graphql",
100 "/terms",
101 "/privacy",
102 "/acceptable-use",
103];
104
105seo.get("/sitemap.xml", (c) => {
106 const origin = new URL(c.req.url).origin;
107 const lastmod = new Date().toISOString().slice(0, 10);
108 const urls = STATIC_PATHS.map(
109 (p) =>
110 `<url><loc>${origin}${p}</loc><lastmod>${lastmod}</lastmod></url>`
111 ).join("\n ");
112 const body = `<?xml version="1.0" encoding="UTF-8"?>
113<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
114 ${urls}
115</urlset>
116`;
117 c.header("Content-Type", "application/xml; charset=utf-8");
118 c.header("Cache-Control", "public, max-age=3600");
119 return c.body(body);
120});
121
122export default seo;