app/llms.txt/route.ts で llms.txt を動的生成
`app/llms.txt/route.ts` を作り、`GET` ハンドラから `new NextResponse(body, { headers: { 'Content-Type': 'text/plain' } })` を返します。body は `# サイト名` + blockquote + `## カテゴリ別セクション` + markdown リンクのテンプレート。コンテンツは Markdown ファイルから動的にビルドするか、静的に文字列で書く。`force-static` を付ければビルド時に静的化されます。
app/sitemap.ts で lastmod 付き sitemap.xml
Next.js は `app/sitemap.ts` を作るだけで `/sitemap.xml` を自動配信します。各 URL に `lastModified` フィールドを Date オブジェクトで返せば `<lastmod>` も自動付与され、S8 / S9 が同時に pass します。
Layout.tsx に JSON-LD を inline で埋め込む
`app/layout.tsx` の `<head>` 内に `<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />` を追加します (next/script ではなく素の <script> タグであることが重要 — script コンポーネントは afterInteractive 等のデフォルトでクライアント側に移動するため、初期 HTML に出ない)。YomuScore 自身もこのパターンで P10 / P11 を pass しています。
Markdown ミラー + content negotiation
実装は (1) `app/[...slug]/page.tsx` の隣に `app/[...slug]/route.ts` を置き、Accept ヘッダで切り分ける、(2) リバースプロキシ (Caddy/Nginx) 側で `Accept: text/markdown` のとき `/{path}.md` にリライトする、の2択。簡単なのは後者。YomuScore は Caddy で `@accept-md header Accept *text/markdown* → rewrite path /{path}.md` を使っています。
<link rel='alternate'> を全ページで出す
`app/layout.tsx` の `metadata.alternates.types['text/markdown']` を設定するだけで、Next.js が自動で `<link rel="alternate" type="text/markdown" href="...">` を出力します。