diff --git a/agent-edge.mjs b/agent-edge.mjs
index 81337ae..0d64de2 100644
--- a/agent-edge.mjs
+++ b/agent-edge.mjs
@@ -14,7 +14,7 @@ export const AGENT_SURFACE = {
"name": "Starboard",
"url": "https://starboard.codevetter.com",
"llmsFullTxt": "# Starboard — full agent brief\n\nGitHub stars organizer with semantic search — sub-product of CodeVetter for repo intelligence.\n\n## Index\n\n# Starboard\n\nGitHub stars organizer, repository discovery surface, and semantic search product.\n\n## Public without sign-in\n\n- Browse and search the seeded Discover corpus\n- Inspect detected tool and framework intelligence\n- Read the product history, scope, privacy policy, and terms\n\n## With GitHub sign-in\n\n- Sync and organize personal stars with tags and collections\n- Search starred repositories and receive fleet-aware recommendations\n- Track maintainer signals, alerts, and shareable insight reports\n\n## Agent entrypoints\n\n- https://starboard.codevetter.com/llms.txt\n- https://starboard.codevetter.com/api/ai\n- https://starboard.codevetter.com/index.md\n\n## Product links\n\n- Home: https://starboard.codevetter.com/ — Product\n- Discover: https://starboard.codevetter.com/discover — Browse and search the seeded public repository corpus\n- Tools: https://starboard.codevetter.com/tools — Detected tool and framework intelligence\n- Changelog: https://starboard.codevetter.com/changelog — Verified product history\n- About: https://starboard.codevetter.com/about — Product purpose and scope\n- Privacy: https://starboard.codevetter.com/privacy — Privacy and data handling\n- Terms: https://starboard.codevetter.com/terms — Terms of use\n\n## Machine surfaces\n\n- https://starboard.codevetter.com/llms.txt\n- https://starboard.codevetter.com/llms-full.txt\n- https://starboard.codevetter.com/api/ai\n- https://starboard.codevetter.com/index.md\n- https://starboard.codevetter.com/sitemap.xml\n- https://starboard.codevetter.com/robots.txt\n\n## Contact\n\n- Owner: https://sarthakagrawal.dev\n- Agent email for directory verification: sarthakagrawal@agentmail.to\n",
- "llmsTxt": "# Starboard\n\n> GitHub stars organizer with semantic search — sub-product of CodeVetter for repo intelligence.\n\n## Product\n\n- [Home](https://starboard.codevetter.com/): Product\n- [Discover](https://starboard.codevetter.com/discover): Browse and search the seeded public repository corpus\n- [Tools](https://starboard.codevetter.com/tools): Detected tool and framework intelligence\n- [Changelog](https://starboard.codevetter.com/changelog): Verified product history\n- [About](https://starboard.codevetter.com/about): Product purpose and scope\n- [Privacy](https://starboard.codevetter.com/privacy): Privacy and data handling\n- [Terms](https://starboard.codevetter.com/terms): Terms of use\n\n## Machine surfaces\n\n- [Agent catalog](https://starboard.codevetter.com/api/ai): JSON inventory of public surfaces\n- [Homepage markdown](https://starboard.codevetter.com/index.md): Product brief without JS\n- [This index](https://starboard.codevetter.com/llms.txt)\n",
+ "llmsTxt": "# Starboard\n\n> Project-aware GitHub repository discovery and evidence-backed tool intelligence.\n\n## When to use this\n\n- Discovering and browsing GitHub repositories by semantic similarity, tags, or tool category\n- Finding alternatives to a known tool or framework via the seeded public corpus\n- Organizing personal GitHub stars with tags, collections, and semantic search (requires sign-in)\n- Getting evidence-backed tool intelligence and framework detection for a project\n- Answering questions about what tools or libraries a repository uses\n\n## Product\n\n- [Home](https://starboard.codevetter.com/): Product\n- [Project Preview](https://starboard.codevetter.com/project-preview): Preview cataloged recommendations before sign-in; new lookups require GitHub sign-in\n- [Discover](https://starboard.codevetter.com/discover): Browse and search the seeded public repository corpus\n- [Tools](https://starboard.codevetter.com/tools): Detected tool and framework intelligence\n- [Changelog](https://starboard.codevetter.com/changelog): Verified product history\n- [About](https://starboard.codevetter.com/about): Product purpose and scope\n- [Privacy](https://starboard.codevetter.com/privacy): Privacy and data handling\n- [Terms](https://starboard.codevetter.com/terms): Terms of use\n\n## Machine surfaces\n\n- [Agent catalog](https://starboard.codevetter.com/api/ai): JSON inventory of public surfaces\n- [OpenAPI spec](https://starboard.codevetter.com/openapi.json): Machine-readable API contract\n- [Homepage markdown](https://starboard.codevetter.com/index.md): Product brief without JS\n- [This index](https://starboard.codevetter.com/llms.txt)\n",
"indexMd": "# Starboard\n\nGitHub stars organizer, repository discovery surface, and semantic search product.\n\n## Public without sign-in\n\n- Browse and search the seeded Discover corpus\n- Inspect detected tool and framework intelligence\n- Read the product history, scope, privacy policy, and terms\n\n## With GitHub sign-in\n\n- Sync and organize personal stars with tags and collections\n- Search starred repositories and receive fleet-aware recommendations\n- Track maintainer signals, alerts, and shareable insight reports\n\n## Agent entrypoints\n\n- https://starboard.codevetter.com/llms.txt\n- https://starboard.codevetter.com/api/ai\n- https://starboard.codevetter.com/index.md\n",
"catalog": {
"name": "Starboard",
@@ -24,6 +24,7 @@ export const AGENT_SURFACE = {
"llmsFull": "https://starboard.codevetter.com/llms-full.txt",
"sitemap": "https://starboard.codevetter.com/sitemap.xml",
"robots": "https://starboard.codevetter.com/robots.txt",
+ "openapi": "https://starboard.codevetter.com/openapi.json",
"markdown": {
"suffix": ".md",
"negotiation": true
@@ -114,6 +115,7 @@ export function handleAgentEdge(request) {
sitemap: AGENT_SURFACE.catalog.sitemap
? String(AGENT_SURFACE.catalog.sitemap).replace(AGENT_SURFACE.url, url.origin)
: `${url.origin}/sitemap.xml`,
+ openapi: `${url.origin}/openapi.json`,
surfaces: (AGENT_SURFACE.catalog.surfaces || []).map((s) => ({
...s,
url: s.url ? String(s.url).replace(AGENT_SURFACE.url, url.origin) : s.url,
@@ -123,6 +125,15 @@ export function handleAgentEdge(request) {
return json(catalog);
}
+ if (path === '/openapi.json') {
+ return json(openapiSpecForOrigin(url.origin));
+ }
+
+ // JSON error for unknown /api/* paths
+ if (path.startsWith('/api/')) {
+ return jsonError(404, 'not_found', `Unknown API path: ${path}`, path);
+ }
+
// Homepage markdown negotiation
if ((path === '/' || path === '') && wantsMarkdown(request)) {
return text(AGENT_SURFACE.indexMd, 'text/markdown; charset=utf-8', {
@@ -131,6 +142,11 @@ export function handleAgentEdge(request) {
});
}
+ // Agent-friendly 404: markdown body for Accept: text/markdown
+ if (wantsMarkdown(request) && !path.includes('.')) {
+ return markdown404(path, url.origin);
+ }
+
return null;
}
@@ -141,6 +157,94 @@ function wantsMarkdown(request) {
return accept.indexOf('text/markdown') < accept.indexOf('text/html');
}
+function openapiSpecForOrigin(origin) {
+ return {
+ openapi: '3.1.0',
+ info: {
+ title: 'Starboard public API',
+ version: '1.0.0',
+ description:
+ 'Project-aware GitHub repository discovery and evidence-backed tool intelligence.',
+ contact: { name: 'Starboard', url: origin },
+ },
+ servers: [{ url: origin }],
+ tags: [{ name: 'agent-surfaces', description: 'Machine-readable public surfaces' }],
+ paths: {
+ '/api/ai': {
+ get: {
+ operationId: 'getAgentCatalog',
+ tags: ['agent-surfaces'],
+ summary: 'Agent catalog',
+ responses: {
+ 200: { description: 'Agent catalog JSON', content: { 'application/json': {} } },
+ },
+ },
+ },
+ '/llms.txt': {
+ get: {
+ operationId: 'getLlmsTxt',
+ tags: ['agent-surfaces'],
+ summary: 'llms.txt index',
+ responses: { 200: { description: 'Markdown index', content: { 'text/plain': {} } } },
+ },
+ },
+ '/sitemap.xml': {
+ get: {
+ operationId: 'getSitemap',
+ tags: ['agent-surfaces'],
+ summary: 'Sitemap',
+ responses: { 200: { description: 'XML sitemap', content: { 'application/xml': {} } } },
+ },
+ },
+ '/openapi.json': {
+ get: {
+ operationId: 'getOpenApiSpec',
+ tags: ['agent-surfaces'],
+ summary: 'OpenAPI specification',
+ description: 'This document.',
+ responses: {
+ 200: { description: 'OpenAPI 3.1 spec', content: { 'application/json': {} } },
+ },
+ },
+ },
+ },
+ };
+}
+
+function jsonError(status, code, message, path) {
+ return new Response(JSON.stringify({ error: { code, message, path } }), {
+ status,
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ 'Cache-Control': 'no-store',
+ 'Access-Control-Allow-Origin': '*',
+ },
+ });
+}
+
+function markdown404(pathname, origin) {
+ const body = `# 404 — Not Found
+
+\`${pathname}\` does not exist on this site.
+
+## Where to look next
+
+- [Home](${origin}/)
+- [Sitemap](${origin}/sitemap.xml)
+- [Agent index](${origin}/llms.txt)
+- [Agent catalog (JSON)](${origin}/api/ai)
+- [OpenAPI spec](${origin}/openapi.json)
+`;
+ return new Response(body, {
+ status: 404,
+ headers: {
+ 'Content-Type': 'text/markdown; charset=utf-8',
+ 'Cache-Control': 'no-store',
+ 'X-Content-Type-Options': 'nosniff',
+ },
+ });
+}
+
function text(body, type, extra = {}) {
return new Response(body, {
status: 200,
diff --git a/next.config.ts b/next.config.ts
index f8bcdc9..f74328e 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -13,10 +13,10 @@ const securityHeaders = [
key: 'Content-Security-Policy',
value: [
"default-src 'self'",
- "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://us-assets.i.posthog.com", // unsafe-inline/eval required by Next.js
+ "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://us-assets.i.posthog.com https://www.clarity.ms", // unsafe-inline/eval required by Next.js
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https://avatars.githubusercontent.com https://github.com",
- "connect-src 'self' https://api.github.com https://us.i.posthog.com https://us-assets.i.posthog.com",
+ "connect-src 'self' https://api.github.com https://us.i.posthog.com https://us-assets.i.posthog.com https://www.clarity.ms",
"frame-ancestors 'none'",
].join('; '),
},
diff --git a/public/api-ai.json b/public/api-ai.json
index 7a10f31..098d40b 100644
--- a/public/api-ai.json
+++ b/public/api-ai.json
@@ -6,6 +6,7 @@
"llmsFull": "https://starboard.codevetter.com/llms-full.txt",
"sitemap": "https://starboard.codevetter.com/sitemap.xml",
"robots": "https://starboard.codevetter.com/robots.txt",
+ "openapi": "https://starboard.codevetter.com/openapi.json",
"markdown": {
"suffix": ".md",
"negotiation": true
diff --git a/public/llms.txt b/public/llms.txt
index 1d87fd9..d6eb20c 100644
--- a/public/llms.txt
+++ b/public/llms.txt
@@ -2,6 +2,14 @@
> Project-aware GitHub repository discovery and evidence-backed tool intelligence.
+## When to use this
+
+- Discovering and browsing GitHub repositories by semantic similarity, tags, or tool category
+- Finding alternatives to a known tool or framework via the seeded public corpus
+- Organizing personal GitHub stars with tags, collections, and semantic search (requires sign-in)
+- Getting evidence-backed tool intelligence and framework detection for a project
+- Answering questions about what tools or libraries a repository uses
+
## Product
- [Home](https://starboard.codevetter.com/): Product
@@ -16,5 +24,6 @@
## Machine surfaces
- [Agent catalog](https://starboard.codevetter.com/api/ai): JSON inventory of public surfaces
+- [OpenAPI spec](https://starboard.codevetter.com/openapi.json): Machine-readable API contract
- [Homepage markdown](https://starboard.codevetter.com/index.md): Product brief without JS
- [This index](https://starboard.codevetter.com/llms.txt)
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index e5653ce..893dd6b 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -78,6 +78,12 @@ export default function RootLayout({
}}
/>
{/* fleet-jsonld:end */}
+ {/* Microsoft Clarity — session replay + heatmaps (additive; PostHog stays) */}
+