From 1b9fd1867a31259af9f3bc97ac3c7fe18e8a124b Mon Sep 17 00:00:00 2001 From: Cahl-Dee Date: Wed, 9 Sep 2026 15:53:55 -0500 Subject: [PATCH 1/2] fix: improve AgentSea search discovery --- packages/ui/public/llms.txt | 30 ++++++++++++++++++++ packages/ui/src/app/[agent]/[cloud]/page.tsx | 2 ++ packages/ui/src/app/cli/page.tsx | 3 ++ packages/ui/src/app/how-it-works/page.tsx | 19 +++++-------- packages/ui/src/app/landing-from-manifest.ts | 29 ++++--------------- packages/ui/src/app/layout.tsx | 2 ++ packages/ui/src/app/page.tsx | 23 ++++++++++++--- packages/ui/src/app/robots.ts | 27 ++++++++++++++++++ packages/ui/src/app/sitemap.ts | 11 ++++--- packages/ui/src/app/why-agentsea/page.tsx | 5 ++-- 10 files changed, 103 insertions(+), 48 deletions(-) create mode 100644 packages/ui/public/llms.txt create mode 100644 packages/ui/src/app/robots.ts diff --git a/packages/ui/public/llms.txt b/packages/ui/public/llms.txt new file mode 100644 index 0000000..24ab398 --- /dev/null +++ b/packages/ui/public/llms.txt @@ -0,0 +1,30 @@ +# AgentSea + +> AgentSea launches supported AI coding agents locally or on cloud infrastructure, pre-wired to The Grid inference API. + +## Start here + +- Homepage: https://agentsea.thegrid.ai/ +- CLI reference: https://agentsea.thegrid.ai/cli +- How AgentSea works: https://agentsea.thegrid.ai/how-it-works +- Why AgentSea: https://agentsea.thegrid.ai/why-agentsea +- Sitemap: https://agentsea.thegrid.ai/sitemap.xml +- Public agent and cloud manifest: https://agentsea.thegrid.ai/manifest.json +- Source repository: https://github.com/the-gridai/agentsea + +## Priority launch guides + +- OpenClaw locally: https://agentsea.thegrid.ai/openclaw/local +- OpenClaw on DigitalOcean: https://agentsea.thegrid.ai/openclaw/digitalocean +- Hermes Agent locally: https://agentsea.thegrid.ai/hermes/local +- Hermes Agent on DigitalOcean: https://agentsea.thegrid.ai/hermes/digitalocean + +Use the sitemap to enumerate every supported agent and cloud launch guide. Every launch guide has a self-referencing canonical URL and contains the exact AgentSea command for that combination. + +## The Grid + +- The Grid homepage: https://thegrid.ai/ +- The Grid agent map: https://thegrid.ai/llms.txt +- Integration documentation: https://thegrid.ai/docs/integrations-and-best-practices/integrations +- OpenClaw integration: https://thegrid.ai/docs/integrations-and-best-practices/integrations/openclaw.md +- Hermes Agent integration: https://thegrid.ai/docs/integrations-and-best-practices/integrations/hermes-agent.md diff --git a/packages/ui/src/app/[agent]/[cloud]/page.tsx b/packages/ui/src/app/[agent]/[cloud]/page.tsx index 039cf6a..4ff2835 100644 --- a/packages/ui/src/app/[agent]/[cloud]/page.tsx +++ b/packages/ui/src/app/[agent]/[cloud]/page.tsx @@ -16,6 +16,8 @@ type PageProps = { params: Promise<{ agent: string; cloud: string }>; }; +export const dynamicParams = false; + export async function generateMetadata({ params }: PageProps) { const { agent: agentSlug, cloud: cloudSlug } = await params; const manifest = await loadManifest(false); diff --git a/packages/ui/src/app/cli/page.tsx b/packages/ui/src/app/cli/page.tsx index c495fe7..65a930c 100644 --- a/packages/ui/src/app/cli/page.tsx +++ b/packages/ui/src/app/cli/page.tsx @@ -36,6 +36,7 @@ export async function generateMetadata({ searchParams }: CliGuidePageProps): Pro return { title: "CLI Reference", description: "Install and use the agentsea CLI: commands, environment variables, and tokens.", + alternates: { canonical: "https://agentsea.thegrid.ai/cli" }, }; } @@ -44,6 +45,7 @@ export async function generateMetadata({ searchParams }: CliGuidePageProps): Pro return { title: "CLI Reference", description: "Install and use the agentsea CLI: commands, environment variables, and tokens.", + alternates: { canonical: "https://agentsea.thegrid.ai/cli" }, }; } @@ -56,6 +58,7 @@ export async function generateMetadata({ searchParams }: CliGuidePageProps): Pro return { title: "CLI reference — AgentSea", description: "Install and use the agentsea CLI: commands, environment variables, and tokens.", + alternates: { canonical: "https://agentsea.thegrid.ai/cli" }, }; } diff --git a/packages/ui/src/app/how-it-works/page.tsx b/packages/ui/src/app/how-it-works/page.tsx index fea3064..34516dc 100644 --- a/packages/ui/src/app/how-it-works/page.tsx +++ b/packages/ui/src/app/how-it-works/page.tsx @@ -3,11 +3,7 @@ import Link from "next/link"; import { CopyCode } from "../copy-code"; import { hoodStepsForCloud } from "../how-it-works-steps"; -import { - AGENTSEA_INSTALL_URL, - AGENTSEA_PUBLIC_ORIGIN, - THE_GRID_EXTERNAL_URL, -} from "../home-public-constants"; +import { AGENTSEA_INSTALL_URL, AGENTSEA_PUBLIC_ORIGIN, THE_GRID_EXTERNAL_URL } from "../home-public-constants"; import { SiteHeader } from "../site-header"; import styles from "../cli/page.module.scss"; import homeStyles from "../page.module.scss"; @@ -20,6 +16,7 @@ export const metadata: Metadata = { title: "How it works", description: "How AgentSea provisions cloud VMs, wires The Grid API, and connects you to interactive AI agents — from install to SSH session.", + alternates: { canonical: "https://agentsea.thegrid.ai/how-it-works" }, openGraph: { title: "How it works — AgentSea", description: @@ -113,11 +110,9 @@ export default function HowItWorksPage() {

Bootstrap scripts are served from the CDN at{" "} - - {AGENTSEA_PUBLIC_ORIGIN}/<cloud>/<agent>.sh - - . The VM inherits THEGRID_API_KEY and OpenAI-compatible - base URLs targeting the Grid API. + {AGENTSEA_PUBLIC_ORIGIN}/<cloud>/<agent>.sh. The + VM inherits THEGRID_API_KEY and OpenAI-compatible base URLs + targeting the Grid API.

@@ -141,8 +136,8 @@ export default function HowItWorksPage() { Open Dashboard for Hermes / OpenClaw UIs
  • - agentsea <agent> <cloud> — provision a - fresh environment with Grid credentials wired + agentsea <agent> <cloud> — provision a fresh + environment with Grid credentials wired
  • THEGRID_API_KEY — consumption key from{" "} diff --git a/packages/ui/src/app/landing-from-manifest.ts b/packages/ui/src/app/landing-from-manifest.ts index 67aa581..90071a4 100644 --- a/packages/ui/src/app/landing-from-manifest.ts +++ b/packages/ui/src/app/landing-from-manifest.ts @@ -1,12 +1,6 @@ import type { Metadata } from "next"; import type { AgentSortMode, Manifest } from "@agentsea/sdk"; -import { - agentKeys, - allAgentKeys, - cloudKeys, - DEFAULT_AGENT_SORT_MODE, - matrixStatus, -} from "@agentsea/sdk"; +import { agentKeys, allAgentKeys, cloudKeys, DEFAULT_AGENT_SORT_MODE, matrixStatus } from "@agentsea/sdk"; import { CHAT_VERIFIED_AGENT_SLUGS, @@ -15,9 +9,7 @@ import { LINODE_PLACEHOLDER, } from "./home-public-constants"; -const CHAT_VERIFIED_ORDER = new Map( - CHAT_VERIFIED_AGENT_SLUGS.map((slug, i) => [slug, i]), -); +const CHAT_VERIFIED_ORDER = new Map(CHAT_VERIFIED_AGENT_SLUGS.map((slug, i) => [slug, i])); export { DEFAULT_AGENT_SORT_MODE }; export type { AgentSortMode }; @@ -43,15 +35,7 @@ export function isCloudImplementedForAgent(m: Manifest, cloud: string, agentSlug } /** Cloud slugs included in sitemap and static `/{agent}/{cloud}` routes. */ -export const INDEXED_CLOUD_SLUGS = [ - "local", - "digitalocean", - "hetzner", - "aws", - "gcp", - "daytona", - "sprite", -] as const; +export const INDEXED_CLOUD_SLUGS = ["local", "digitalocean", "hetzner", "aws", "gcp", "daytona", "sprite"] as const; export function agentCloudPath(agentSlug: string, cloudSlug: string): string { return `/${agentSlug}/${cloudSlug}`; @@ -77,7 +61,7 @@ export function implementedAgentCloudPairs(m: Manifest): Array<{ agent: string; } function publicOriginBase(): string { - return process.env.NEXT_PUBLIC_AGENTSEA_PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "https://spawn.thegrid.ai"; + return process.env.NEXT_PUBLIC_AGENTSEA_PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "https://agentsea.thegrid.ai"; } /** Per-route title, description, canonical URL, and Open Graph / Twitter tags for launch pages. */ @@ -245,10 +229,7 @@ export function sortHomeAgents(agents: readonly HomeAgentVm[], mode: AgentSortMo }); } -export function homeAgentsFromManifest( - m: Manifest, - mode: AgentSortMode = DEFAULT_AGENT_SORT_MODE, -): HomeAgentVm[] { +export function homeAgentsFromManifest(m: Manifest, mode: AgentSortMode = DEFAULT_AGENT_SORT_MODE): HomeAgentVm[] { const rows: HomeAgentVm[] = []; for (const slug of allAgentKeys(m, mode)) { diff --git a/packages/ui/src/app/layout.tsx b/packages/ui/src/app/layout.tsx index 5a27ad6..00644c2 100644 --- a/packages/ui/src/app/layout.tsx +++ b/packages/ui/src/app/layout.tsx @@ -19,6 +19,7 @@ const dmMono = DM_Mono({ }); export const metadata: Metadata = { + metadataBase: new URL("https://agentsea.thegrid.ai"), title: "AgentSea — AI agents on any cloud | The Grid", description: "Pick an agent, pick a cloud, one CLI. Provision VMs, Grid API key, browser terminal — AgentSea for The Grid.", @@ -29,6 +30,7 @@ export const metadata: Metadata = { title: "AgentSea — AI agents on any cloud", description: "Pick an agent, pick a cloud, one CLI. Provision VMs wired to The Grid API.", type: "website", + url: "https://agentsea.thegrid.ai/", }, }; diff --git a/packages/ui/src/app/page.tsx b/packages/ui/src/app/page.tsx index f958125..9bc24b0 100644 --- a/packages/ui/src/app/page.tsx +++ b/packages/ui/src/app/page.tsx @@ -1,15 +1,24 @@ +import type { Metadata } from "next"; import Link from "next/link"; import { Suspense } from "react"; import { HomeAgentGridStatic } from "./home-agent-grid-static"; import { HomeLaunchFlow } from "./home-launch-flow"; import { THE_GRID_EXTERNAL_URL } from "./home-public-constants"; -import { homeAgentCloudAvailability, homeAgentsFromManifest, homeCloudOptionsFromManifest } from "./landing-from-manifest"; +import { + homeAgentCloudAvailability, + homeAgentsFromManifest, + homeCloudOptionsFromManifest, +} from "./landing-from-manifest"; import { SiteHeader } from "./site-header"; import styles from "./page.module.scss"; import { loadManifest } from "@agentsea/sdk/node"; +export const metadata: Metadata = { + alternates: { canonical: "https://agentsea.thegrid.ai/" }, +}; + export default async function HomePage() { const manifest = await loadManifest(false); const agents = homeAgentsFromManifest(manifest); @@ -24,9 +33,7 @@ export default async function HomePage() {

    Launch AI agents locally or on the cloud

    -

    - Any agent, on your infrastructure — wired to The Grid API. -

    +

    Any agent, on your infrastructure — wired to The Grid API.

    }> @@ -53,6 +60,14 @@ export default async function HomePage() { How it works · + + OpenClaw guide + + · + + Hermes guide + + · The Grid diff --git a/packages/ui/src/app/robots.ts b/packages/ui/src/app/robots.ts new file mode 100644 index 0000000..aaaac9e --- /dev/null +++ b/packages/ui/src/app/robots.ts @@ -0,0 +1,27 @@ +import type { MetadataRoute } from "next"; + +const PUBLIC_ORIGIN = "https://agentsea.thegrid.ai"; + +export default function robots(): MetadataRoute.Robots { + const allowedBots = [ + "*", + "Googlebot", + "Bingbot", + "Applebot", + "OAI-SearchBot", + "ChatGPT-User", + "Claude-SearchBot", + "Claude-User", + "PerplexityBot", + "Perplexity-User", + "ExaSearchBot", + "ShapBot", + "FirecrawlAgent", + ]; + + return { + rules: allowedBots.map((userAgent) => ({ userAgent, allow: "/" })), + sitemap: `${PUBLIC_ORIGIN}/sitemap.xml`, + host: PUBLIC_ORIGIN, + }; +} diff --git a/packages/ui/src/app/sitemap.ts b/packages/ui/src/app/sitemap.ts index 62565c5..d147470 100644 --- a/packages/ui/src/app/sitemap.ts +++ b/packages/ui/src/app/sitemap.ts @@ -5,23 +5,22 @@ import { implementedAgentCloudPairs, agentCloudPath } from "./landing-from-manif import { loadManifest } from "@agentsea/sdk/node"; function publicOriginBase(): string { - return process.env.NEXT_PUBLIC_AGENTSEA_PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "https://spawn.thegrid.ai"; + return process.env.NEXT_PUBLIC_AGENTSEA_PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "https://agentsea.thegrid.ai"; } export default async function sitemap(): Promise { const manifest = await loadManifest(false); const base = publicOriginBase(); const entries: MetadataRoute.Sitemap = [ - { url: base, lastModified: new Date() }, - { url: `${base}/cli`, lastModified: new Date() }, - { url: `${base}/why-agentsea`, lastModified: new Date() }, - { url: `${base}/how-it-works`, lastModified: new Date() }, + { url: `${base}/` }, + { url: `${base}/cli` }, + { url: `${base}/why-agentsea` }, + { url: `${base}/how-it-works` }, ]; for (const { agent, cloud } of implementedAgentCloudPairs(manifest)) { entries.push({ url: `${base}${agentCloudPath(agent, cloud)}`, - lastModified: new Date(), }); } diff --git a/packages/ui/src/app/why-agentsea/page.tsx b/packages/ui/src/app/why-agentsea/page.tsx index 6d70b1d..1209b8b 100644 --- a/packages/ui/src/app/why-agentsea/page.tsx +++ b/packages/ui/src/app/why-agentsea/page.tsx @@ -10,6 +10,7 @@ export const metadata: Metadata = { title: "Why AgentSea", description: "AgentSea is the fastest way to deploy Grid-backed AI agents on infrastructure you control — agent-agnostic, bring your own cloud, fully sandboxed.", + alternates: { canonical: "https://agentsea.thegrid.ai/why-agentsea" }, openGraph: { title: "Why AgentSea", description: @@ -33,8 +34,8 @@ export default function WhyAgentSeaPage() {

    Why AgentSea?

    - The fastest way to deploy Grid-backed agents on infrastructure you control. Pick an agent and - environment on the{" "} + The fastest way to deploy Grid-backed agents on infrastructure you control. Pick an agent and environment + on the{" "} homepage {" "} From 02c767798e35eb57ad5d1878c94c8532d5860f04 Mon Sep 17 00:00:00 2001 From: Cahl-Dee Date: Wed, 9 Sep 2026 16:15:07 -0500 Subject: [PATCH 2/2] fix: limit sitemap to public launch options --- packages/ui/src/app/landing-from-manifest.ts | 18 +++++++++++++++--- packages/ui/src/app/sitemap.ts | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/app/landing-from-manifest.ts b/packages/ui/src/app/landing-from-manifest.ts index 90071a4..df46f16 100644 --- a/packages/ui/src/app/landing-from-manifest.ts +++ b/packages/ui/src/app/landing-from-manifest.ts @@ -7,6 +7,7 @@ import { HOME_CLOUD_COMING_SOON, HOME_CLOUD_SLUGS, LINODE_PLACEHOLDER, + type HomeCloudSlug, } from "./home-public-constants"; const CHAT_VERIFIED_ORDER = new Map(CHAT_VERIFIED_AGENT_SLUGS.map((slug, i) => [slug, i])); @@ -34,8 +35,8 @@ export function isCloudImplementedForAgent(m: Manifest, cloud: string, agentSlug return matrixStatus(m, cloud, agentSlug) === "implemented"; } -/** Cloud slugs included in sitemap and static `/{agent}/{cloud}` routes. */ -export const INDEXED_CLOUD_SLUGS = ["local", "digitalocean", "hetzner", "aws", "gcp", "daytona", "sprite"] as const; +/** Cloud slugs supported by static `/{agent}/{cloud}` routes, including CLI-only providers. */ +export const ROUTABLE_CLOUD_SLUGS = ["local", "digitalocean", "hetzner", "aws", "gcp", "daytona", "sprite"] as const; export function agentCloudPath(agentSlug: string, cloudSlug: string): string { return `/${agentSlug}/${cloudSlug}`; @@ -51,7 +52,7 @@ export function displayCloudName(cloudSlug: string, cloudName: string): string { export function implementedAgentCloudPairs(m: Manifest): Array<{ agent: string; cloud: string }> { const pairs: Array<{ agent: string; cloud: string }> = []; for (const agentSlug of agentKeys(m)) { - for (const cloudSlug of INDEXED_CLOUD_SLUGS) { + for (const cloudSlug of ROUTABLE_CLOUD_SLUGS) { if (isCloudImplementedForAgent(m, cloudSlug, agentSlug)) { pairs.push({ agent: agentSlug, cloud: cloudSlug }); } @@ -60,6 +61,17 @@ export function implementedAgentCloudPairs(m: Manifest): Array<{ agent: string; return pairs; } +/** Implemented pairs exposed in the homepage UX and therefore appropriate for the public sitemap. */ +export function publiclyDiscoverableAgentCloudPairs(m: Manifest): Array<{ agent: string; cloud: string }> { + return implementedAgentCloudPairs(m).filter(({ agent, cloud }) => { + return ( + CHAT_VERIFIED_ORDER.has(agent) && + HOME_CLOUD_SLUGS.includes(cloud as HomeCloudSlug) && + !HOME_CLOUD_COMING_SOON.has(cloud) + ); + }); +} + function publicOriginBase(): string { return process.env.NEXT_PUBLIC_AGENTSEA_PUBLIC_ORIGIN?.replace(/\/+$/, "") ?? "https://agentsea.thegrid.ai"; } diff --git a/packages/ui/src/app/sitemap.ts b/packages/ui/src/app/sitemap.ts index d147470..e373721 100644 --- a/packages/ui/src/app/sitemap.ts +++ b/packages/ui/src/app/sitemap.ts @@ -1,6 +1,6 @@ import type { MetadataRoute } from "next"; -import { implementedAgentCloudPairs, agentCloudPath } from "./landing-from-manifest"; +import { agentCloudPath, publiclyDiscoverableAgentCloudPairs } from "./landing-from-manifest"; import { loadManifest } from "@agentsea/sdk/node"; @@ -18,7 +18,7 @@ export default async function sitemap(): Promise { { url: `${base}/how-it-works` }, ]; - for (const { agent, cloud } of implementedAgentCloudPairs(manifest)) { + for (const { agent, cloud } of publiclyDiscoverableAgentCloudPairs(manifest)) { entries.push({ url: `${base}${agentCloudPath(agent, cloud)}`, });