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
[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). npm run generate-og-image reads only baseUrl.
Titles And Descriptions
Every page and entry accepts these frontmatter fields:
---title: "Simple plans for *every* team" # shown on the pagemetaTitle: "Pricing" # browser tab and search result title (optional)description: "..." # page summarymetaDescription: "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 URLrobots: "" # 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.xmllists every page. Leave pages out withexcludeFromSitemap: true, or whole folders with[seo.sitemap] exclude. Drafts, the 404 pages, and/elements/are left out automatically./robots.txtis built from[seo.robotsTxt]. Add paths crawlers must skip todisallow.- The auth screens ship with
robots: "noindex, nofollow"andexcludeFromSitemap: 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.
Social Previews
See Site Identity & Logo: 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
- Set a key of 8 to 128 letters, numbers, or dashes:
[seo.ai] indexNowKey = "your-key-1234". - Deploy. The build publishes the key file at
/<key>.txt. - After the deploy is live, run
npm run indexnow -- --allonce. - After later deploys, run
npm run indexnow(pages changed in the last 7 days).--days=30widens the window and--dry-runonly lists the URLs.
Do It With AI
Write SEO titles and descriptions for every page content file in src/content/*/english/-index.mdand 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 Frenchfiles.