Commit5618f9aunknown_key
chore: rot sweep + robots.txt + sitemap.xml
chore: rot sweep + robots.txt + sitemap.xml
- Drop duplicate app.route("/", orgRoutes) at src/app.tsx (was mounted
twice 9 lines apart).
- Remove unused requireAuth import + void-keepalive from admin.tsx.
- Add src/routes/seo.ts serving /robots.txt + /sitemap.xml (static
public paths only). Mounted in src/app.tsx. Crawlers now have a
canonical index of landing/explore/status/marketplace/etc.
Tests unchanged: 137 pass / 53 fail (sandbox hono/jsx env errors).3 files changed+70−75618f9a3f258be4127023339915295fb010215e2
3 changed files+70−7
Modifiedsrc/app.tsx+4−3View fileUnifiedSplit
@@ -25,6 +25,7 @@ import contributorRoutes from "./routes/contributors";
2525import healthRoutes from "./routes/health-probe";
2626import healthDashboardRoutes from "./routes/health";
2727import statusRoutes from "./routes/status";
28import seoRoutes from "./routes/seo";
2829import { platformStatus } from "./routes/platform-status";
2930import insightRoutes from "./routes/insights";
3031import dashboardRoutes from "./routes/dashboard";
@@ -176,9 +177,6 @@ app.route("/", tokenRoutes);
176177// Notifications
177178app.route("/", notificationRoutes);
178179
179// Organizations
180app.route("/", orgRoutes);
181
182180// Repo settings (description, visibility, delete)
183181app.route("/", repoSettings);
184182
@@ -212,6 +210,9 @@ app.route("/api/platform-status", platformStatus);
212210// Public /status — human-readable platform health page
213211app.route("/", statusRoutes);
214212
213// SEO: robots.txt + sitemap.xml
214app.route("/", seoRoutes);
215
215216// Health dashboard (per-repo health page)
216217app.route("/", healthDashboardRoutes);
217218
Modifiedsrc/routes/admin.tsx+1−4View fileUnifiedSplit
@@ -19,7 +19,7 @@ import { and, desc, eq, ilike, or, sql } from "drizzle-orm";
1919import { db } from "../db";
2020import { repositories, users } from "../db/schema";
2121import { Layout } from "../views/layout";
22import { softAuth, requireAuth } from "../middleware/auth";
22import { softAuth } from "../middleware/auth";
2323import type { AuthEnv } from "../middleware/auth";
2424import {
2525 grantSiteAdmin,
@@ -785,7 +785,4 @@ admin.post("/admin/autopilot/run", async (c) => {
785785 }
786786});
787787
788// Keep requireAuth import used even if some routes don't reference it here.
789void requireAuth;
790
791788export default admin;
Addedsrc/routes/seo.ts+65−0View fileUnifiedSplit
@@ -0,0 +1,65 @@
1/**
2 * SEO routes: robots.txt + sitemap.xml.
3 *
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.
9 */
10
11import { Hono } from "hono";
12
13const seo = new Hono();
14
15const ROBOTS = `User-agent: *
16Allow: /
17Disallow: /admin
18Disallow: /settings
19Disallow: /api/
20Disallow: /login
21Disallow: /register
22Disallow: /logout
23Disallow: /oauth/
24Disallow: /*/settings
25Disallow: /*.git/
26
27Sitemap: /sitemap.xml
28`;
29
30seo.get("/robots.txt", (c) => {
31 c.header("Content-Type", "text/plain; charset=utf-8");
32 c.header("Cache-Control", "public, max-age=3600");
33 return c.body(ROBOTS);
34});
35
36const STATIC_PATHS = [
37 "/",
38 "/explore",
39 "/marketplace",
40 "/status",
41 "/shortcuts",
42 "/api/graphql",
43 "/terms",
44 "/privacy",
45 "/acceptable-use",
46];
47
48seo.get("/sitemap.xml", (c) => {
49 const origin = new URL(c.req.url).origin;
50 const lastmod = new Date().toISOString().slice(0, 10);
51 const urls = STATIC_PATHS.map(
52 (p) =>
53 `<url><loc>${origin}${p}</loc><lastmod>${lastmod}</lastmod></url>`
54 ).join("\n ");
55 const body = `<?xml version="1.0" encoding="UTF-8"?>
56<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
57 ${urls}
58</urlset>
59`;
60 c.header("Content-Type", "application/xml; charset=utf-8");
61 c.header("Cache-Control", "public, max-age=3600");
62 return c.body(body);
63});
64
65export default seo;
066