Skip to content
Type something to search...
Kivo Theme Documentation

SEO & AI Visibility

Files: src/config/config.toml, page frontmatter · Skill level: Beginner

Kivo does the technical SEO for you: titles, descriptions, canonical links, a sitemap, robots.txt, structured data, social preview images, RSS feeds, and optional files for AI tools. Your job is to set your address and write good titles and descriptions.

First, Set Your Address

[site]
baseUrl = "https://www.acme.dev" # ships as "https://example.com"

Canonical links, the sitemap, the sitemap line in robots.txt, RSS feeds, social previews, and the AI files all use it. The theme ships with the placeholder https://example.com, and npm run build prints a yellow [site] warning (when the Astro build finishes, before the search index output) until you change it. Don’t deploy while you see that warning: every page would point search engines at example.com.

A SITE_URL environment variable on the build takes priority over baseUrl, for example SITE_URL=https://www.acme.dev npm run build, or a variable in your host’s settings. On Vercel, the included vercel.sh sets it for you: production builds keep a SITE_URL you set in the Vercel project, or use your Vercel production domain, and preview builds use https://staging.<production domain>. npm run generate-og-image reads only baseUrl.

Titles And Descriptions

Every page and entry accepts these frontmatter fields:

---
title: "Pricing" # shown on the page
metaTitle: "Pricing and plans" # search result title (optional)
description: "..." # page summary
metaDescription: "Start free and..." # search result description, 140–160 characters (optional)
image: "/images/pricing-preview.jpg" # social preview image (optional)
canonical: "" # only if the page is a copy of another URL
robots: "" # for example "noindex, nofollow"
keywords: ["pricing", "plans"]
---

Titles get your tagline added (“Pricing - Your tagline”); disableTagline: true turns it off for a page. Site-wide defaults are in [site] and [seo].

Sitemap And Robots

  • /sitemap-index.xml lists every page. Leave pages out with excludeFromSitemap: true, or whole folders with [seo.sitemap] exclude. Draft pages are removed automatically.
  • /robots.txt is built from [seo.robotsTxt]. Add paths crawlers must skip to disallow.

Structured Data

Kivo adds structured data (JSON-LD) that describes your pages to search engines: your organization and website on every page, BlogPosting on posts, JobPosting on careers pages, FAQPage on the FAQ, your plans and prices (SoftwareApplication offers) on the pricing page, and breadcrumbs. It is built from your content, so there is nothing to fill in. After launch, check a page for errors with Google’s Rich Results Test.

Structured data doesn’t guarantee rich results, and Google no longer shows FAQ rich results. Keep the data true:

  • The job posting data on careers pages is for real openings only. Replace or delete the sample roles before launch.
  • The pricing offers come from your plans, so keep plans-section.md up to date.

Social Preview Images

[opengraph]
image = "/images/og-image.jpg" # fallback image
generateImages = true # draw a card for each page without an image
theme = "light" # light | dark

With generateImages = true, npm run build draws a 1200×630 card for every page that has no image, using your logo, colors, font, the page title, and its description. Run npm run generate-og-image to redraw the fallback image after a rebrand.

RSS Feeds

/blog/rss.xml and /changelog/rss.xml are built automatically, one per language (/fr/blog/rss.xml).

AI Search And AI Assistants

Google says no special files or markup are needed to appear in its AI features (AI Overviews and AI Mode): a page that is indexed and can show a snippet in Search is eligible. The settings below control which AI crawlers may visit, and add optional files and links for AI tools. Kivo has four of them:

1. Choose which AI crawlers may visit

[seo.robotsTxt]
aiSearch = true # AI answer engines that cite pages (ChatGPT search, Claude, Perplexity, ...)
aiTraining = true # crawlers that collect content to train AI models

Each switch writes robots.txt rules for a list of crawlers, in src/lib/utils/aiCrawlers.ts:

  • aiSearch = false asks the crawlers of AI answer engines (ChatGPT search, Claude, Perplexity, DuckDuckGo AI answers) not to fetch your pages, which can keep your pages out of their answers. The list also includes the fetchers that open a page when a user asks about it, and some of them (ChatGPT-User, Perplexity-User) say they may not follow robots.txt.
  • aiTraining = false asks the training crawlers (GPTBot, ClaudeBot, Google-Extended, Applebot-Extended, CCBot, and meta-externalagent) to stay away. Google also uses Google-Extended for grounding in Gemini apps, so this can reduce how often your pages appear in Gemini answers.

Both switches also set the Content-Signal line under User-agent: *, which applies to every crawler: ai-input follows aiSearch and ai-train follows aiTraining. Content signals are a proposed format (contentsignals.org) that Google does not document using.

Neither switch affects Google Search or AI Overviews, which use the normal Googlebot and follow your regular search rules.

2. llms.txt and Markdown copies

[seo.ai]
llmsTxt = true # /llms.txt (an index of the site) and /llms-full.txt (all page text)
markdownPages = true # a Markdown copy of posts, releases, features, and more at <page>.md

/llms.txt follows a proposed convention: a Markdown map of your site that some AI tools and coding agents can read. /llms-full.txt holds the text of every page. Search engines don’t document using these files, so treat them as a convenience for tools that look for them, not as an SEO setting. Each language gets its own (/fr/llms.txt). With markdownPages, a post at /blog/my-post/ is also available as /blog/my-post.md. Leave a page out of all of these with excludeFromAi: true; pages marked noindex are left out automatically.

3. The Copy page menu and Ask AI links

[settings.pageActions]
enable = true # "Copy page" menu on posts and entries
footer = true # "Ask AI about this page" row in the footer
providers = ["chatgpt", "claude", "perplexity", "grok"] # [] hides the "Ask" links

Visitors can copy a page as Markdown or open it in an AI assistant with one click.

4. IndexNow

IndexNow tells the search engines that support it (Bing, Yandex, Seznam, and Naver) which pages changed, so they can update them sooner. Microsoft Copilot uses Bing.

  1. Set a key of 8–128 letters, numbers, or dashes: [seo.ai] indexNowKey = "a1b2c3d4e5f6g7h8".
  2. Build and deploy. The key file is published at /<key>.txt.
  3. After each deploy, run npm run indexnow. Use npm run indexnow -- --all the first time to send every page.

Do It With AI

Improve SEO for my site. For every content file with a title (src/content/**/english/), write a
metaDescription of 140–160 characters based on the page content, and a metaTitle under 60
characters where the title is vague. Don't change other fields. Then do the same in French.
Finally, check that [site] baseUrl in src/config/config.toml is "[MY URL]".