feat(web): AEO foundation — robots, JSON-LD, meta, llms.txt, security headers

Implements the high-signal, content-independent fixes flagged across the
multi-engine AEO audit:

- robots.txt (app/robots.ts): allow mainstream + AI crawlers (GPTBot,
  ClaudeBot, PerplexityBot, Google-Extended, …), disallow /api, link sitemap.
- Organization + WebSite JSON-LD on the root layout; BlogPosting JSON-LD on
  /blog/[slug].
- Richer metadata: descriptive default title, Open Graph + Twitter cards,
  canonical, icons, metadataBase.
- Per-route titles/descriptions for catch-all routes (docs, about, hire-us,
  agent-swarm, …) instead of the generic "LogicSRC".
- /llms.txt (llmstxt.org) and /skill.md capability manifest.
- /.well-known/security.txt (RFC 9116).
- Security headers via next.config: HSTS, X-Content-Type-Options,
  X-Frame-Options, Referrer-Policy, Permissions-Policy (CSP intentionally
  deferred to avoid breaking inline/stats/CoinPay scripts).

Verified in a running build: all routes serve correctly and headers are set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-06-08 12:38:27 +00:00
parent ce79f02211
commit 6518dfb4a9
8 changed files with 285 additions and 19 deletions

View file

@ -14,13 +14,16 @@ type PostRow = {
html: string;
featured_image: { url?: string } | null;
published_at: string;
updated_at: string;
};
const SITE_URL = (process.env.PUBLIC_URL ?? "https://logicsrc.com").replace(/\/$/, "");
async function loadPost(slug: string): Promise<PostRow | null> {
const supabase = publicClient();
const { data } = await supabase
.from("blog_posts")
.select("slug, title, excerpt, html, featured_image, published_at")
.select("slug, title, excerpt, html, featured_image, published_at, updated_at")
.eq("slug", slug)
.eq("status", "published")
.maybeSingle();
@ -65,8 +68,25 @@ export default async function BlogPostPage({
const post = await loadPost(slug);
if (!post) notFound();
const jsonLd = {
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: post.title,
description: post.excerpt ?? undefined,
image: post.featured_image?.url ? [post.featured_image.url] : undefined,
datePublished: post.published_at,
dateModified: post.updated_at,
url: `${SITE_URL}/blog/${post.slug}`,
mainEntityOfPage: `${SITE_URL}/blog/${post.slug}`,
publisher: { "@id": `${SITE_URL}/#organization` },
};
return (
<SiteShell active="Blog">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<article className="band" style={{ maxWidth: "48rem" }}>
<p style={{ marginBottom: "1.5rem" }}>
<Link href="/blog" style={{ color: "#5b6b7a", textDecoration: "none" }}>