SEO & AI Visibility
Files: src/config/config.toml, src/i18n/<language>.json, page frontmatter · Skill level: Beginner
Margo does the technical SEO for you: page titles and descriptions, canonical links, a sitemap, robots.txt, structured data, social preview cards, an RSS feed for the journal, and files for AI assistants. Your job is to set your address and identity, and to write good titles and descriptions.
First, Set Your Address
[site] baseUrl = "https://www.your-domain.com" # ships as "https://example.com"Canonical links, the sitemap, robots.txt, RSS feeds, llms.txt, and social preview URLs all use it. Until you change it, npm run build prints a warning at the end. Don’t deploy while you see it: every page would point search engines at example.com.
A SITE_URL environment variable on the build takes priority over baseUrl. On Vercel, the included vercel.sh sets one for you. npm run generate-og-image reads only baseUrl.
Site Title, Tagline, And Description
[site] title = "Margo" # your name or studio name description = "Editorial portfolio theme for designers, studios, and photographers, ..." tagline = "Creative Portfolio Astro & Tailwind CSS Theme" taglineSeparator = "" # default is " - "Page titles get your tagline added: “About - Your tagline”. description is the default meta description for pages that have none. A language can use its own tagline and description with site.tagline and site.description in src/i18n/<language>.json: French and Arabic ship with their own, so replace them too (see Internationalization). Keep the tagline under about 55 characters.
[seo] author = "Getastrothemes" # put your own name or studio here keywords = ["portfolio astro theme", "..."] # default keywords for pages without their own robots = "index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"Replace author and the sample keywords before launch. The robots value lets search and AI answers quote your pages and show their images in full.
Who Runs The Site
[seo.identity] type = "Organization" # Organization | Person name = "" # empty uses [site] title jobTitle = "" # Person only, for example "Brand designer" image = "" # a logo (Organization) or a photo (Person)Set type = "Person" if the site is one named designer or photographer, and "Organization" for a studio or business. Search engines read this as the publisher of the site, the creator of your projects, the provider of your services, and the author of journal posts that have no author of their own. An empty image uses [site] logo, and without a logo the theme’s built-in mark. The profile links come from src/config/social.json: links to a bare domain such as https://www.instagram.com are skipped, so add your real profile addresses.
Titles And Descriptions
Every page and entry accepts these frontmatter fields:
---title: "Brand identity" # shown on the pagemetaTitle: "Brand identity for small companies" # search result title (optional)description: "Marks, type, and colour for..." # page summarymetaDescription: "A brand identity built in..." # 140–160 characters (optional)image: "/images/services/brand-identity.jpg" # social preview image (optional)canonical: "" # only if the page is a copy of another URLrobots: "" # for example "noindex, follow"keywords: ["brand identity", "logo design"]disableTagline: false # true: no tagline after this page's title---Structured Data (JSON-LD)
Margo writes structured data on every page from your content, so it matches what visitors see:
| Page | Structured data |
|---|---|
| Every page | The website and who runs it ([seo.identity]) |
| Project pages | A CreativeWork with the client, year, location, and categories |
| Service pages | A Service provided by you |
| Journal posts | A BlogPosting with the author from the author collection |
| Pages with breadcrumbs | A BreadcrumbList |
/faq/ | FAQPage with the questions on the page |
The FAQ markup is switched with structuredData in the FAQ block’s options: true in src/content/faq/<language>/-index.md, and false on the pricing page and in the section defaults, so the same questions are marked up once. After launch, test a page with Google’s Rich Results Test.
Social Preview Cards
[opengraph] image = "/images/og-image.jpg" # fallback image, public/images/og-image.jpg generateImages = true # a 1200×630 card for every page without its own image theme = "light" # light | dark twitter = "" # your X (Twitter) handle- A page with its own
imageuses that image. - Every other page gets a card generated during
npm run build, with your logo, the section name, the page title, and the description, in your fonts and colours. - Arabic pages use the fallback
image, because the card generator can’t lay out Arabic text. - After you change your name, tagline, colours, or fonts (and after setting
baseUrl), runnpm run generate-og-imageto redraw the fallback image in your branding.
Sitemap, Robots, And Hidden Pages
/sitemap-index.xmllists your pages. Leave a page out withexcludeFromSitemap: true, or every page in a folder with[seo.sitemap] exclude. Draft pages are removed automatically./robots.txtis built from[seo.robotsTxt]. Add paths crawlers must skip todisallow./elements/, the layout gallery, ships hidden from search engines (robots: "noindex, nofollow"), out of the sitemap and out of site search. The 404 pages arenoindextoo.
AI Search And AI Assistants
[seo.robotsTxt] aiSearch = true # AI search and answer engines that fetch pages to cite them aiTraining = true # crawlers that collect content to train AI modelsaiSearch = false asks AI answer engines to stay away; aiTraining = false opts out of training only. Neither affects Google Search or AI Overviews, which use the normal Googlebot. The crawler lists are in src/lib/utils/aiCrawlers.ts.
Margo also builds /llms.txt, /llms-full.txt, and a Markdown copy of your projects, services, journal posts, team members, and legal, pricing, and FAQ pages, and adds “Ask AI” links. All of that is explained in AI Links & llms Files.
IndexNow (Bing And Others)
IndexNow tells Bing, Yandex, Seznam, and Naver which pages changed, so they update faster. It ships off.
- Set a key of 8 to 128 letters, numbers, or dashes in
config.toml:indexNowKey = "your-key"under[seo.ai]. The build publishes it at/<key>.txt. - Deploy.
- After each deploy, run
npm run indexnow. It sends the pages whose sitemap date changed in the last 7 days.npm run indexnow -- --allsends every page (use it at first launch),--days=30a longer period, and--dry-runlists the pages without sending them.
Do It With AI
Improve SEO for my portfolio. For every content file with a title in src/content/**/english/,write a metaDescription of 140–160 characters from the page content, and a metaTitle under 60characters where the title is vague. Don't change other fields. Then do the same in every otherlanguage. Set [site] title, tagline, and description, [seo] author and keywords, and[seo.identity] in src/config/config.toml for [MY NAME OR STUDIO, WHAT I DO, WHERE], updatesite.tagline and site.description in src/i18n/fr.json and src/i18n/ar.json, and check that[site] baseUrl is "[MY URL]".