# AI search visibility (GEO)

AI assistants increasingly answer questions by reading and citing pages
directly — ChatGPT, Claude, Gemini and Perplexity all crawl, and all of them
prefer content they can parse without guessing. "GEO" (generative engine
optimization) is the practice of making your content legible to them. baas
does not treat it as a marketing claim: every post you publish ships a
concrete, verifiable machine-readable surface, and this page lists exactly
what that is and how to check it.

## What every published post ships

| Surface | Where | What it gives an AI crawler |
|---|---|---|
| `llms.txt` | `{base_path}/llms.txt` | A per-blog index of every published article: title, canonical URL, one-line summary |
| JSON-LD | inline on every post page | A schema.org `BlogPosting`: headline, description, keywords, author/publisher, dates, language, hero image |
| Sitemap | `https://api.dailysmith.com/v1/delivery/{publicKey}/sitemap.xml` | Every canonical URL with last-modified dates and image entries |
| RSS | `https://api.dailysmith.com/v1/delivery/{publicKey}/rss.xml` | The 50 newest posts with summaries and hero enclosures |
| Clean SSR | every install mode | Full, semantic HTML with no client-side rendering required to read the article |

Rich MD2 content helps too: steps, comparisons and callouts compile to
semantic HTML structures, which is what lets a model quote your worked
example instead of paraphrasing a wall of text.

## llms.txt — the blog's index for AI crawlers

[llms.txt](https://llmstxt.org) is a convention AI crawlers use to learn
what a site offers without crawling all of it: a markdown file listing what
is worth reading. baas serves one per blog, next to your articles:

```
https://example.com/blog/llms.txt
```

It lists every **published** post with its title, canonical URL on your
domain, and a one-line description. It updates the moment you publish or
take down a post (subject to the same short CDN cache as your pages), and
it is served in your blog's own language.

The file rides the render path, so proxy and prerender installs serve it on
your domain automatically. It is also always available directly from the
API, whatever your install mode:

```bash
curl https://api.dailysmith.com/v1/render/{publicKey}/blog/llms.txt
```

:::callout{severity=info title="SDK installs"}
The JS SDK injects articles into your existing pages and cannot create new
URLs on your domain, so `{base_path}/llms.txt` only resolves there if you
add a rewrite for it — the same one-rule shape the [edge
proxy](/docs/install-proxy) uses. The API URL above works regardless, and
the sitemap and RSS feeds are unaffected.
:::

## JSON-LD structured data

Every post page carries a schema.org `BlogPosting` document in an inline
`<script type="application/ld+json">` block — the format Google documents
for article rich results and the one most crawlers parse first.

Half of it is editorial and written at generation time: `headline`,
`description`, `keywords`, `wordCount`. The other half is derived fresh at
serve time, so it is never stale: `datePublished` and `dateModified` from
the post's real lifecycle, `author` and `publisher` from your site,
`inLanguage` from the post, `mainEntityOfPage` from the canonical URL, and
`image` whenever the post has a [featured image](/docs/content-pipeline) —
including after you regenerate it.

Editing a post updates the document; renaming your site or changing a slug
is reflected on the next request. You never maintain any of it by hand.

## Verify it yourself

Replace the key and slug with yours (both are on your site and post pages):

```bash
# The blog's AI index — expect your published titles and URLs
curl https://api.dailysmith.com/v1/render/{publicKey}/blog/llms.txt

# A post's structured data — expect one BlogPosting JSON document
curl -s https://api.dailysmith.com/v1/render/{publicKey}/blog/{slug} \
  | grep -o '<script type="application/ld+json">.*</script>'

# The sitemap — expect every published canonical URL
curl https://api.dailysmith.com/v1/delivery/{publicKey}/sitemap.xml
```

Google's [Rich Results Test](https://search.google.com/test/rich-results)
against a published URL validates the JSON-LD end to end.

## The checklist in the dashboard

Every post page in the dashboard shows an **AI & search visibility** card:
which JSON-LD fields this exact post ships, whether it is listed in
llms.txt and the sitemap (and why not, if not — an unverified site or an
unpublished post), its published translations, and the MD2 semantic
components it uses. The card is computed from the same code that serves the
public surfaces, so it cannot claim anything a crawler would not see.

:::callout{severity=info title="Takedowns propagate everywhere"}
Taking a post down removes it from the rendered page, the delivery API, the
sitemap, RSS **and** llms.txt in one action — no surface keeps advertising
a URL that stopped resolving.
:::
