claude-start-cf

LLMO

LLM Optimization (LLMO) structures your content so AI assistants — ChatGPT, Claude, Perplexity — can accurately understand, cite, and recommend it. Complements traditional SEO.

SEO vs LLMO

Different audiences, overlapping techniques

SEO optimizes for search engine crawlers and ranking algorithms. LLMO optimizes for LLM training data pipelines and retrieval-augmented generation (RAG) systems.

AspectSEOLLMO
GoalRank in search resultsBe cited by AI assistants
AudienceGooglebot, BingbotLLM training & retrieval systems
Key signalsLinks, keywords, page speedStructured data, clarity, authority
Content formatOptimized for snippetsOptimized for extraction & synthesis

The good news: clear structure, authoritative content, and good metadata help both. Most LLMO work builds on your existing SEO foundation.

WebSite + Organization schema

src/routes/__root.tsx → head() → scripts

Site-wide structured data in the root route tells AI systems what your site is, who publishes it, and where to find more. Applied to every page.

// src/routes/__root.tsx
export const Route = createRootRoute({
  head: () => ({
    // ...meta and links...
    scripts: [
      {
        type: 'application/ld+json',
        children: JSON.stringify({
          '@context': 'https://schema.org',
          '@type': 'WebSite',
          name: 'claude-start-cf',
          url: SITE_URL,
          description: 'A base template for...',
          publisher: {
            '@type': 'Organization',
            name: 'claude-start-cf',
            url: SITE_URL,
          },
        }),
      },
    ],
  }),
})

Live: This app's root route includes WebSite JSON-LD on every page. View source on any page to see it in the <head>.

Article structured data

src/routes/blog/$slug.tsx → head()

Per-page Article schema with headline, author, and publication date. AI systems use this to attribute content and understand authorship.

head: ({ loaderData }) => {
  const post = loaderData?.post
  if (!post) return {}
  return {
    meta: [
      { title: `${post.title} — claude-start-cf Blog` },
      { name: 'description', content: post.description },
      { property: 'og:type', content: 'article' },
    ],
    scripts: [
      {
        type: 'application/ld+json',
        children: JSON.stringify({
          '@context': 'https://schema.org',
          '@type': 'Article',
          headline: post.title,
          description: post.description,
          author: post.authors.map((name) => ({
            '@type': 'Person',
            name,
          })),
          datePublished: post.published,
        }),
      },
    ],
  }
}

Live example: /blog/hello-world includes Article JSON-LD. Use the SEO Head Inspector to verify.

FAQ schema

head() → FAQPage JSON-LD

FAQ structured data is particularly effective for LLMO — AI systems frequently extract Q&A pairs when answering user questions.

export const Route = createFileRoute('/faq')({
  loader: async () => {
    const faqs = await fetchFAQs()
    return { faqs }
  },
  head: ({ loaderData }) => ({
    meta: [{ title: 'FAQ' }],
    scripts: [
      {
        type: 'application/ld+json',
        children: JSON.stringify({
          '@context': 'https://schema.org',
          '@type': 'FAQPage',
          mainEntity: loaderData.faqs.map((faq) => ({
            '@type': 'Question',
            name: faq.question,
            acceptedAnswer: {
              '@type': 'Answer',
              text: faq.answer,
            },
          })),
        }),
      },
    ],
  }),
})

Other useful schema types: Product (e-commerce), HowTo (tutorials), SoftwareApplication (tools), and Course (education). See schema.org for the full vocabulary.

llms.txt

src/routes/llms[.]txt.ts

A plain-text file that gives AI systems a structured summary of your site: what it is, what content exists, key facts, and links. Similar to robots.txt but for LLMs.

// src/routes/llms[.]txt.ts
export const Route = createFileRoute('/llms.txt')({
  server: {
    handlers: {
      GET: async () => {
        const content = `# claude-start-cf

> A base template for building full-stack apps on the edge.

## About
claude-start-cf is a starter template designed for AI-assisted development...

## Feature Demos
- [Home](${SITE_URL}/): Landing page
- [D1 Database](${SITE_URL}/d1): SQLite at the edge
- [R2 Storage](${SITE_URL}/r2): Object storage
...

## Blog
${allPosts.map(p => `- [${p.title}](${SITE_URL}/blog/${p.slug})`).join('\n')}

## Tech Stack
- TanStack Start (React SSR framework)
- Cloudflare Workers (edge runtime)
...`

        return new Response(content, {
          headers: { 'Content-Type': 'text/plain; charset=utf-8' },
        })
      },
    },
  },
})

This app generates llms.txt dynamically from content-collections, keeping the blog list always in sync. For static sites, a file in public/ works too.

Content best practices

Structure for extraction

Beyond technical markup, how you write content affects how well AI systems can extract and cite it.

Clear, factual statements

AI systems extract factual claims. Make key information explicit and self-contained — don't rely on surrounding context.

// Good: clear, extractable facts
<p>
  claude-start-cf is a TanStack Start template that runs on Cloudflare Workers.
  It includes D1 (SQLite), R2 (object storage), and shadcn/ui components.
</p>

// Avoid: vague, context-dependent
<p>
  Our product works great with all the latest technologies.
  It has everything you need to get started.
</p>

Hierarchical heading structure

Proper h1 → h2 → h3 hierarchy helps AI systems understand content organization. Each section should be independently understandable.

Author attribution

Include author metadata — AI systems consider authority signals when deciding what to cite.

head: ({ loaderData }) => ({
  meta: [
    { name: 'author', content: loaderData.post.author.name },
    { property: 'article:author', content: loaderData.post.author.url },
    { property: 'article:published_time', content: loaderData.post.published },
  ],
})

Machine-readable API endpoints

JSON endpoints with schema.org context let AI systems consume your data directly without HTML parsing.

// src/routes/api/products.ts
GET: async () => {
  const products = await fetchProducts()
  return Response.json({
    '@context': 'https://schema.org',
    '@type': 'ItemList',
    itemListElement: products.map((p, i) => ({
      '@type': 'ListItem',
      position: i + 1,
      item: {
        '@type': 'Product',
        name: p.name,
        description: p.description,
        url: `${SITE_URL}/products/${p.id}`,
      },
    })),
  })
}

LLMO checklist

Implementation guide

Steps to optimize your TanStack Start app for AI discoverability.

  1. Add WebSite JSON-LD to root route

    Site name, URL, description, publisher Organization. Applied to every page.

  2. Add Article/Product JSON-LD to content pages

    Dynamic from loaderData: headline, author, dates, description.

  3. Create llms.txt

    Plain-text overview: what your site is, key pages, facts, and links. Server route or static file.

  4. Write clear, factual content

    Self-contained paragraphs, proper heading hierarchy, explicit facts, author attribution.

  5. Add FAQ schema where relevant

    Q&A pairs are frequently extracted by AI systems.

  6. Test with AI assistants

    Ask ChatGPT, Claude, and Perplexity about your product. Validate structured data with Schema.org Validator.

TechniqueFileImpact
WebSite JSON-LD__root.tsxSite identity for all pages
Article JSON-LDblog/$slug.tsxContent attribution & authorship
llms.txtserver routeSite summary for AI crawlers
FAQ schemahead() → scriptsQ&A extraction by AI
SSRdefault onAI crawlers see rendered content