Jamdesk Documentation logo

SEO Optimization

Control titles, descriptions, and meta tags for search engines and social previews. Jamdesk auto-generates sitemaps and Open Graph images.

Set titles, descriptions, and metadata in frontmatter to control how your docs show up in search engines and social previews.

What Jamdesk Does Automatically

Meta Tags

Title and description from frontmatter become meta tags.

Open Graph

Social sharing images generated for each page.

Sitemap & Robots

XML sitemap and robots.txt generated on every build.

JSON-LD

Schema.org structured data on every page for rich search results.

IndexNow

Changed URLs submitted to search engines after each build.

AI Endpoints

llms.txt and MCP server for AI tools to read your docs.

Optimizing Your Content

Write Effective Frontmatter

---
title: User Authentication    # Under 60 characters
description: Set up OAuth, JWT, and session-based authentication  # 120-160 characters
---

Front-load keywords. "Authentication setup" is better than "How to set up authentication."

Page Titles

  • Keep under 60 characters, counting the site name your title format adds. Longer titles get truncated in search results
  • Include your primary keyword near the beginning
  • Make each title unique across your docs

By default, the browser tab and search result title is Page title — Site name. Change it with seo.titleTemplate in docs.json. Put %s where the page title goes:

{
  "seo": {
    "titleTemplate": "%s | Acme"
  }
}

A page titled Getting started then shows Getting started | Acme. Use "%s" alone to leave the site name out. A template without %s fails the build. jamdesk validate shows the error. Link previews (og:title and twitter:title) still show the page title alone.

Some pages skip the template. A page with no title shows your name followed by "Documentation", such as Acme Documentation, or only your name if it already ends in "Docs" or "Documentation". A page whose title is the same as your name shows that title alone.

jamdesk validate and jamdesk dev accept seo.titleTemplate from CLI version 1.1.220. Upgrade with npm i -g jamdesk@latest.

Descriptions

  • Aim for 120-160 characters
  • Summarize what the reader will learn
  • Include relevant keywords naturally

Auto-generated fallback. Jamdesk extracts the first prose paragraph from your page content (up to 155 characters) when description is missing from frontmatter. Headings, code blocks, images, and MDX components are skipped. That text fills <meta name="description">, Open Graph, and Twitter cards. An explicit description still gives the best results.

Controlling Indexing

Site-Wide Settings

Set default robot behavior in docs.json:

docs.json
{
  "seo": {
    "metatags": {
      "robots": "index, follow"
    }
  }
}

Per-Page Control

Override indexing for specific pages in frontmatter:

---
title: Internal Notes
noindex: true
---

Use noindex for:

  • Draft or work-in-progress pages
  • Internal documentation
  • Deprecated content you're keeping for reference

Search Indexing vs. AI Ingestion

robots metadata and noindex control search engines: whether a page appears in Google and your sitemap.xml. They have no effect on the llms.txt and llms-full.txt files that AI tools read. Set seo.ai.llmsTxt to false to stop publishing those (see Turning Off llms.txt). The two controls are independent: a page can be indexed by search engines but excluded from AI ingestion, or the reverse.

Canonical URLs

Set a canonical if your docs are reachable at multiple URLs:

---
title: Getting Started
canonical: https://docs.example.com/getting-started
---

You can also set a site-wide canonical base in docs.json. Jamdesk appends each page's path to it:

docs.json
{
  "seo": {
    "metatags": {
      "canonical": "https://docs.acme.com"
    }
  }
}

Social Previews & Open Graph

Jamdesk generates a branded 1200×630 social card for every page. Override any social tag in frontmatter with flat top-level keys or a nested seo: block. The flat top-level value wins when the same key is set both ways.

OpenGraph Preview

Preview any page's card on X, Facebook, LinkedIn, and more. Validate its Open Graph tags.

---
title: API Reference
description: REST API endpoints and authentication
"og:title": API Reference — Acme
"og:description": Everything you need to call the Acme API
"og:image": /images/api-social-card.png
"twitter:card": summary_large_image
"twitter:creator": "@acme"
keywords: ["api", "rest", "authentication"]
canonical: https://docs.acme.com/api-reference
---

Supported tags

GroupTags
Open Graphog:title, og:description, og:image, og:image:width, og:image:height, og:image:alt, og:url, og:type, og:site_name, og:locale, og:video, og:audio
Articleog:type: article with article:published_time, article:modified_time, article:author, article:section, article:tag
Twitter / Xtwitter:card, twitter:title, twitter:description, twitter:image, twitter:image:alt, twitter:site, twitter:creator, twitter:player, app-card tags
Otherkeywords, author, robots, googlebot, google-site-verification, theme-color, plus any custom tag (place custom tags under seo:)

Custom OG image dimensions. og:image:width and og:image:height only apply when customImage is "replace". Set them in the same place as the og:image they describe, either the page frontmatter or seo.metatags. The generated card is always 1200×630.

Custom tags. Arbitrary meta tags (e.g. x-pinterest) are emitted as <meta name="...">. Put them under the seo: block. Only recognized SEO keys are picked up when placed flat.

Twitter / X card type

The twitter:card tag controls which layout X (and other platforms) use when your link is shared:

ValueWhat it looks like
summarySmall square thumbnail on the left, title + description beside it. Compact.
summary_large_imageLarge full-width image on top, title + description below.

Use summary_large_image for a branded 1200×630 card. It renders the image at full width.

Site-wide default image

Set a fallback social image for every page in docs.json. Any page that sets its own og:image overrides it:

docs.json
{
  "seo": {
    "metatags": {
      "og:image": "https://docs.acme.com/images/default-card.png"
    }
  }
}

Preview before you publish. Paste the page URL into the OpenGraph Preview tool after a build. It shows how the card renders on each platform and validates the Open Graph tags. It also checks image dimensions and explains how to fix problems.

Customize the social card

Your generated card keeps its current look unless you add seo.socialCard to docs.json. Set only the keys you want to change:

docs.json
{
  "seo": {
    "socialCard": {
      "theme": "dark",
      "brandColor": true,
      "accentBar": false,
      "siteName": false,
      "customImage": "replace"
    }
  }
}
KeyDefaultEffect
theme"light""dark" uses light text on a dark background and your logo.dark image.
brandColorfalsetrue colors the bottom bar and the section badge with colors.primary. A dark card uses colors.light if you set it. If you have no colors, the card uses your theme's accent color. false keeps the default red.
accentBartruefalse removes the colored bar along the bottom of the card.
siteNametruefalse hides the site name under the logo. Use it when your logo already shows the name.
customImage"background""background" draws the page title on top of your og:image. "replace" uses your og:image as the whole card.

The card can only draw SVG, PNG and JPG logos. Jamdesk converts PNG and JPG logo files in your repository to WebP at build time. The card then usually shows your favicon instead and keeps the site name, even with siteName: false. Use an SVG logo to show your full logo on the card. Use an SVG logo.dark for a dark card.

The card can't draw text inside an SVG logo. That text comes out blank. Convert the text to outlines (paths) in your design tool and export the SVG again. In Figma, select the text and use Flatten. In Illustrator, use Type > Create Outlines. The build shows a suggestion when it finds text in the card's SVG logo. Logos set to a full URL (https://...) aren't checked.

The badge text falls back to the normal text color when your brand color doesn't stand out against the card. The bar keeps your brand color unless that color nearly matches the card background. Then the bar is gray.

By default, Jamdesk draws the page title on top of your og:image. Set "customImage": "replace" to show an image that has its own text or design as it is.

Pick the theme that matches an og:image used as the card background: dark for a dark image, light for a light one.

In replace mode, Jamdesk draws no title on the image. An og:image in seo.metatags applies to every page. A page that sets its own og:image uses that one instead. Only pages with neither get a generated card. Use a 1200×630 PNG or JPG. Some platforms don't show WebP or SVG images.

Social sites cache link previews. A link that was already shared can keep the old card for a while after you change these settings. Check the new card with the OpenGraph Preview tool.

Older versions of the Jamdesk CLI reject seo.socialCard and seo.titleTemplate in jamdesk validate and jamdesk dev. Upgrade with npm i -g jamdesk@latest.

Sitemap & Robots.txt

Jamdesk generates sitemap.xml and robots.txt on every build.

FilePurpose
sitemap.xmlLists all pages with last-modified dates for search engines
robots.txtAllows all crawlers and points them to the sitemap

Where to find them

The URLs depend on whether your docs live at a root domain or under a /docs subpath:

If your docs are at the root of your domain (e.g., docs.acme.com or acme.jamdesk.app):

https://docs.acme.com/sitemap.xml
https://docs.acme.com/robots.txt

What's included in the sitemap

  • All published pages (excluding those with noindex or hidden frontmatter)
  • Last-modified dates from frontmatter when available
  • Weekly change frequency

Excluding pages from the sitemap

Add noindex to frontmatter to keep a page out of the sitemap and search engines:

---
title: Internal Notes
noindex: true
---

Pages with hidden: true are excluded too.

JSON-LD Structured Data

Every page includes schema.org structured data as a <script type="application/ld+json"> tag with two schemas:

  • WebSite: your site name, URL, and description (from docs.json).
  • BreadcrumbList: navigation path from Home to the current page, derived from your navigation config.

No configuration needed. Search engines use this for rich results like breadcrumb trails in search listings.

Verify your markup. Paste any page URL into Google's Rich Results Test to confirm the structured data is detected.

IndexNow

Jamdesk submits changed page URLs to IndexNow after each build. Bing, Yandex, and other participating search engines learn about the changes without waiting for their next crawl cycle.

  • Fires after every successful build
  • Submits only pages that changed
  • Non-blocking. It never delays your build
  • No configuration required

Best Practices

Run through this checklist before you publish:

Pre-publish checklist

  • Unique titles: every page has a distinct, descriptive title under 60 characters.
  • Accurate descriptions: descriptions summarize the page in 120-160 characters.
  • Logical headings: headings follow a clean hierarchy: one H1, then H2 → H3.
  • Descriptive links: internal links use meaningful anchor text, never "click here."
  • Image alt text: every image has alt text for accessibility and image search.
  • Social image: set a custom og:image on key pages, or rely on the auto-generated card. Verify it with the OpenGraph Preview tool.
Frontmatter Reference

All available frontmatter options

docs.json Reference

Site-wide configuration options

OpenGraph Preview Tool

Preview and validate your social cards across every platform