# SEO & AI Visibility

## SEO & AI Visibility

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

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

### First, Set Your Address
```toml
[site]
  baseUrl = "https://www.acme.com"   # 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. Until you change it, `npm run build` prints a yellow `[site]` warning when the Astro build finishes. 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.com npm run build`, or a variable in your host's settings. On Vercel, the included `vercel.sh` sets it for you (see [Deployment](/taskly/deployment/)). `npm run generate-og-image` reads only `baseUrl`.

### Titles And Descriptions
Every page and entry accepts these frontmatter fields:

```yaml
---
title: "Simple plans for *every* team"  # shown on the page
metaTitle: "Pricing"                    # browser tab and 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"]
disableTagline: false                   # true leaves the tagline off this page's title
---
```

Titles get your tagline added ("Pricing - Task management for remote teams"); `disableTagline: true` in a page's frontmatter turns it off for that page. The tagline is translated per language through `site.tagline` in `src/i18n/en.json` and `fr.json`, which wins over `[site] tagline` in `config.toml`. Site-wide defaults are in `[site]` and `[seo]`.

The main homepage (`src/content/homepage/english/-index.md` and `french/`) ships with `disableTagline: true`, because its `metaTitle` already says what the tagline says, so the browser tab shows the title once instead of repeating it. `/home-2/` and `/home-3/` keep the tagline. If you write a homepage `metaTitle` that doesn't include your tagline, set `disableTagline: false` (or delete the line) to add it back.

The homepage files ship with `metaTitle` and `metaDescription` that name the theme: write your own.

### Sitemap And Robots
- `/sitemap-index.xml` lists every page. Leave pages out with `excludeFromSitemap: true`, or whole folders with `[seo.sitemap] exclude`. Drafts, the 404 pages, and `/elements/` are left out automatically.
- `/robots.txt` is built from `[seo.robotsTxt]`. Add paths crawlers must skip to `disallow`.
- The auth screens ship with `robots: "noindex, nofollow"` and `excludeFromSitemap: true`.

### Structured Data
Taskly adds structured data (JSON-LD) that describes your pages to search engines: your organization and website on every page, `WebPage` for pages, `BlogPosting` (with the author) on posts, `JobPosting` on role pages (from the careers fields, including salary and location), and `FAQPage` where an FAQ section has `jsonLd: true` (the `/faq/` page). It is built from your content, so there is nothing else to fill in. After launch, check a page with Google's [Rich Results Test](https://search.google.com/test/rich-results).

### Social Previews
See [Site Identity & Logo](/taskly/customization/site-identity-logo/#social-sharing-image): a page's `image`, the generated cards (`[opengraph] generateImages`), and the shared image from `npm run generate-og-image`.

### RSS
`/blog/rss.xml` and `/changelog/rss.xml`, one feed per language (`/fr/blog/rss.xml`).

### AI Visibility
AI assistants and AI search engines read websites too. Taskly makes yours easy for them to read and quote:

| Feature                    | Setting                       | What visitors and AI tools get                       |
| -------------------------- | ----------------------------- | ---------------------------------------------------- |
| `llms.txt`                 | `[seo.ai] llmsTxt = true`     | `/llms.txt`, a Markdown map of your site, and `/llms-full.txt` with the text of every page, one pair per language |
| Markdown copies            | `[seo.ai] markdownPages = true` | A clean Markdown copy of posts, releases, integrations, templates, solutions, roles, pricing, and other pages at the same URL plus `.md` (`/blog/my-post.md`) |
| "Copy page" menu           | `[settings.pageActions] enable = true` | On blog posts, releases, integrations, and role pages: copy the page as Markdown, open the Markdown copy, or ask an AI assistant about the page |
| Footer AI row              | `[settings.pageActions] footer = true` | On every page: "Ask AI" links for the current page, the page in Markdown, `llms.txt`, and `llms-full.txt` |
| AI assistants in the links | `[settings.pageActions] providers` | Any of `chatgpt`, `claude`, `perplexity`, `grok`. Empty hides the "Ask" links |
| AI crawlers                | `[seo.robotsTxt] aiSearch`, `aiTraining` | `aiSearch = false` keeps AI search engines out; `aiTraining = false` opts out of AI training only |
| IndexNow                   | `[seo.ai] indexNowKey`        | Faster indexing on Bing (which also feeds ChatGPT search and Copilot), Yandex, Seznam, and Naver |

Leave a page out of `llms.txt` and the Markdown copies with `excludeFromAi: true` in its frontmatter. The Markdown copies are sent with `noindex` on Vercel (and Netlify and Cloudflare through `public/_headers`), so they don't compete with your pages in search results.

### IndexNow
<Steps>

1. Set a key of 8 to 128 letters, numbers, or dashes: `[seo.ai] indexNowKey = "your-key-1234"`.
2. Deploy. The build publishes the key file at `/<key>.txt`.
3. After the deploy is live, run `npm run indexnow -- --all` once.
4. After later deploys, run `npm run indexnow` (pages changed in the last 7 days). `--days=30` widens the window and `--dry-run` only lists the URLs.

</Steps>

<Aside type="tip">
  Submit `https://your-domain/sitemap-index.xml` in Google Search Console and
  Bing Webmaster Tools after launch. See [Deployment](/taskly/deployment/).
</Aside>

### Do It With AI
```text
Write SEO titles and descriptions for every page content file in src/content/*/english/-index.md
and the homepage files: metaTitle under 60 characters, metaDescription of 140–160 characters,
based on my product: [DESCRIPTION]. Don't change title fields shown on the page. Then the French
files.
```