-
Notifications
You must be signed in to change notification settings - Fork 7
Add SEO & GEO overview page and expand SEO metadata best practices #3725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c23e89e
6ab2a73
a59f887
be79a9d
3a8d974
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,3 +104,4 @@ exceptions: | |
| - MDN | ||
| - UUID | ||
| - WSS | ||
| - GEO | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,3 +84,4 @@ exceptions: | |
| - LaTeX | ||
| - MDN | ||
| - WSS | ||
| - GEO | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,10 @@ | ||
| --- | ||
| title: Configure SEO metadata | ||
| description: Configure SEO metadata in Fern docs with page-level frontmatter and site-wide settings. Control titles, descriptions, and social media previews. | ||
| max-toc-depth: 2 | ||
| max-toc-depth: 3 | ||
| --- | ||
|
|
||
| Fern automatically generates all SEO metadata for every page in your documentation site. Search engines and social media previews work out of the box with no configuration required. | ||
|
|
||
| When you do want to customize SEO settings, you can set defaults [at the site level](#website-metadata) or override them on [individual pages](#page-level-configuration). Keep titles between 50-60 characters and descriptions between 150-160 characters for optimal display. | ||
| When you want to customize how your pages appear in search results or social previews, you can set defaults [at the site level](#site-wide-defaults) or override them on [individual pages](#page-level-overrides). | ||
|
|
||
| <Note> | ||
| The metadata configurations on this page are for SEO and social tags that aren't visible to users. For visible footer links, see [footer links configuration](/learn/docs/configuration/site-level-settings#footer-links-configuration). | ||
|
|
@@ -16,50 +14,243 @@ When you do want to customize SEO settings, you can set defaults [at the site le | |
|
|
||
| Fern looks for metadata values in this order: | ||
|
|
||
| 1. **Page frontmatter** - Custom SEO values for a specific page | ||
| 2. **Site-level `docs.yml`** - Default SEO values for all pages | ||
| 3. **Automatic defaults** - Generated from your page's existing title, description, etc. | ||
| 1. **Page frontmatter** — Custom SEO values for a specific page | ||
| 2. **Site-level `docs.yml`** — Default SEO values for all pages | ||
| 3. **Automatic defaults** — Generated from your page's existing `title`, `description`, `subtitle`, or `excerpt` fields | ||
|
|
||
| <Info title="Example"> | ||
| <Info title="Example"> | ||
| `og:image` is the image that appears in social media previews. If you don't set `og:image` in a page's frontmatter, Fern uses the site-wide `og:image` from `docs.yml`. If neither is configured, the tag is omitted entirely. | ||
| </Info> | ||
|
|
||
| ## Site-wide defaults | ||
|
|
||
| Set default SEO metadata for your entire site in `docs.yml`. These apply to all pages unless overridden by page-specific metadata. | ||
|
|
||
| ```yaml docs.yml | ||
| metadata: | ||
| # Core metadata | ||
| og:site_name: "Square Developer Documentation" | ||
| og:title: "Square Developer Platform | Payments, Commerce & Banking APIs" | ||
| og:description: "Build with Square's suite of APIs and SDKs. Accept payments, manage inventory, create loyalty programs, and access financial services." | ||
| og:url: "https://developer.squareup.com/docs" | ||
| og:locale: "en_US" | ||
| canonical-host: "developer.squareup.com" | ||
|
|
||
| # Social image | ||
| og:image: "https://developer.squareup.com/images/docs-social-card.png" | ||
| og:image:width: 1200 | ||
| og:image:height: 630 | ||
| og:logo: "https://developer.squareup.com/images/square-logo.png" | ||
|
|
||
| # Twitter / X | ||
| twitter:title: "Square Developer Platform Documentation" | ||
| twitter:description: "Integrate payments, point-of-sale, inventory, and financial services into your applications with Square's developer platform." | ||
| twitter:handle: "@SquareDev" | ||
| twitter:image: "https://developer.squareup.com/images/twitter-card.png" | ||
| twitter:site: "@Square" | ||
| twitter:card: "summary_large_image" | ||
| ``` | ||
|
|
||
| ### Core metadata | ||
|
|
||
| Identity and descriptive fields used by search engines and shared across social platforms. Keep titles between 50–60 characters and descriptions between 150–160 characters for optimal display. Set `canonical-host` if your docs are accessible at multiple URLs (e.g., a custom domain and a `buildwithfern.com` subdomain) to tell search engines which URL is authoritative. | ||
|
|
||
| <ParamField path="metadata.og:site_name" type="string" required={false} toc={true}> | ||
| The name of your website for Open Graph tags. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:title" type="string" required={false} toc={true}> | ||
| The title shown in social media previews. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:description" type="string" required={false} toc={true}> | ||
| The description shown in social media previews. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:url" type="string" required={false} toc={true}> | ||
| The canonical URL of your documentation. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:locale" type="string" required={false} toc={true}> | ||
| The locale of your content (e.g., `en_US`). | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.canonical-host" type="string" required={false} toc={true}> | ||
| The host of your documentation website. Used to set the canonical URL for metadata tags and documents like the sitemap. Defaults to the URL defined in `instances`. | ||
| </ParamField> | ||
|
|
||
| ### Social image | ||
|
|
||
| The image displayed when your docs are shared on LinkedIn, Slack, Discord, and other platforms. Use a 1200x630px image for the best display across platforms — this is the standard Open Graph size and will render correctly in most previews. Avoid embedding text in the image since it may be cropped on some platforms. | ||
|
|
||
| <ParamField path="metadata.og:image" type="string" required={false} toc={true}> | ||
| The image shown in social media previews. Recommended size is 1200x630 pixels. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:image:width" type="number" required={false} toc={true}> | ||
| The width of your Open Graph image in pixels. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [vale] reported by reviewdog 🐶 |
||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:image:height" type="number" required={false} toc={true}> | ||
| The height of your Open Graph image in pixels. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [vale] reported by reviewdog 🐶 |
||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.og:logo" type="string" required={false} toc={true}> | ||
| URL to your company logo. | ||
| </ParamField> | ||
|
|
||
| ### Twitter / X | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 [vale] reported by reviewdog 🐶 |
||
|
|
||
| Controls how your docs appear in Twitter Card previews when shared on X. | ||
|
|
||
| <ParamField path="metadata.twitter:title" type="string" required={false} toc={true}> | ||
| The title shown in Twitter Card previews. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.twitter:description" type="string" required={false} toc={true}> | ||
| The description shown in Twitter Card previews. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.twitter:handle" type="string" required={false} toc={true}> | ||
| Your company's Twitter handle. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.twitter:image" type="string" required={false} toc={true}> | ||
| The image shown in Twitter Card previews. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.twitter:site" type="string" required={false} toc={true}> | ||
| The Twitter handle for your website. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="metadata.twitter:card" type="string" required={false} toc={true}> | ||
| The Twitter Card type. Options are `summary`, `summary_large_image`, `app`, or `player`. | ||
| </ParamField> | ||
|
|
||
| ## Page-level overrides | ||
|
|
||
| Configure SEO metadata in your page's frontmatter to control how individual pages appear in search results and social shares. These settings override site-wide defaults. | ||
|
|
||
| <Info> | ||
| Only the documented SEO fields are added to the HTML `<head>` as meta tags. Custom frontmatter fields won't automatically appear in your page metadata. To add custom metadata, use [custom JavaScript](/learn/docs/customization/custom-css-js#custom-javascript). | ||
| </Info> | ||
|
|
||
| <CodeBlock title="plantstore-quickstart.mdx"> | ||
| ```mdx | ||
| --- | ||
| title: PlantStore API Quick Start | ||
| headline: "Get Started with PlantStore API | Developer Documentation" | ||
| keywords: plants, garden, nursery | ||
| canonical-url: https://docs.plantstore.dev/welcome | ||
| og:image: https://plantstore.dev/images/api-docs-banner.png | ||
| og:image:width: 1200 | ||
| og:image:height: 630 | ||
| twitter:card: summary_large_image | ||
| twitter:site: "@PlantStoreAPI" | ||
| noindex: false | ||
| nofollow: false | ||
| --- | ||
| ``` | ||
| </CodeBlock> | ||
|
|
||
| ### Basic metadata | ||
|
|
||
| Page title, URL, and keyword fields used by search engines. Use `headline` when you need a different title for search engines than what appears as the visible page heading. | ||
|
|
||
| <ParamField path="headline" type="string" required={false} toc={true}> | ||
| When set, the `<title />` tag in the document head will use this value rather than the `title` property. For example, your `title` might be "Quickstart" (shown in the sidebar and as the H1), while `headline` could be "Quickstart | PlantStore API Docs" to give search engines more context. If not set, Fern uses `title` with your site name appended. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="canonical-url" type="string" required={false} toc={true}> | ||
| Overrides the canonical URL for this page. Must be a full URL including the protocol (e.g., `https://buildwithfern.com/learn/docs/content/frontmatter`). | ||
| </ParamField> | ||
|
|
||
| <ParamField path="keywords" type="string" required={false} toc={true}> | ||
| Comma-separated keywords relevant to the page (e.g., `plants, garden, nursery`). Accepts only comma-separated strings, not arrays. | ||
| </ParamField> | ||
|
|
||
| ### Open Graph | ||
|
|
||
| Controls how this page appears when shared on LinkedIn, Slack, Discord, and other platforms that support Open Graph. Keep titles between 50–60 characters and descriptions between 150–160 characters for optimal display. | ||
|
|
||
| <ParamField path="og:site_name" type="string" required={false} toc={true}> | ||
| The name of your website as it should appear when your content is shared. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:title" type="string" required={false} toc={true}> | ||
| The title of your page as it should appear when your content is shared. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:description" type="string" required={false} toc={true}> | ||
| The description of your page as it should appear when your content is shared. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:url" type="string" required={false} toc={true}> | ||
| The URL of your page. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:image" type="string" required={false} toc={true}> | ||
| The URL of the image displayed when your content is shared. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:image:width" type="number" required={false} toc={true}> | ||
| The width of the image in pixels. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:image:height" type="number" required={false} toc={true}> | ||
| The height of the image in pixels. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:locale" type="string" required={false} toc={true}> | ||
| The locale of the page, typically in the format `language_TERRITORY` (e.g., `en_US`). | ||
| </ParamField> | ||
|
|
||
| <ParamField path="og:logo" type="string" required={false} toc={true}> | ||
| The URL of your logo image displayed when your content is shared. | ||
| </ParamField> | ||
|
|
||
| ### Twitter / X | ||
|
|
||
| Controls how this page appears in Twitter Card previews when shared on X. | ||
|
|
||
| <ParamField path="twitter:title" type="string" required={false} toc={true}> | ||
| The title of your page as it should appear in a tweet. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="twitter:description" type="string" required={false} toc={true}> | ||
| The description of your page as it should appear in a tweet. | ||
| </ParamField> | ||
|
|
||
| <ParamField path="twitter:handle" type="string" required={false} toc={true}> | ||
| The Twitter handle of the page creator or site. | ||
| </ParamField> | ||
|
|
||
| ## What Fern automatically generates | ||
| <ParamField path="twitter:image" type="string" required={false} toc={true}> | ||
| The URL of the image displayed in a tweet. | ||
| </ParamField> | ||
|
|
||
| For every page, Fern creates these SEO tags in your HTML: | ||
| <ParamField path="twitter:site" type="string" required={false} toc={true}> | ||
| The Twitter handle for your website. | ||
| </ParamField> | ||
|
|
||
| <AccordionGroup> | ||
| <Accordion title="HTML meta tags"> | ||
| - `<title>` tag with site-wide suffix (e.g., "Page Title | Your Site Name") | ||
| - Meta description (pulled from your `description`, `subtitle`, or `excerpt` fields) | ||
| - Meta keywords (when you provide them) | ||
| - Canonical URL (from your page slug or `canonical-url` override) | ||
| - Robots meta tags (`noindex`/`nofollow` when configured) | ||
| - Favicon link tag | ||
| </Accordion> | ||
| <Accordion title="Open Graph tags (for LinkedIn, Slack, Discord, etc.)"> | ||
| - `og:title`, `og:description`, `og:image` - What appears in social previews | ||
| - `og:url` - Canonical URL of the page | ||
| - `og:site_name` - Your website name | ||
| - `og:locale` - Content language (e.g., "en_US") | ||
| - `og:image:width`, `og:image:height` - Image dimensions | ||
| </Accordion> | ||
| <Accordion title="Twitter Card tags"> | ||
| - `twitter:title`, `twitter:description`, `twitter:image` - What appears in Twitter/X previews | ||
| - `twitter:site`, `twitter:creator` - Your Twitter handles | ||
| - `twitter:card` - Card type (e.g., "summary_large_image") | ||
| </Accordion> | ||
| </AccordionGroup> | ||
| <ParamField path="twitter:url" type="string" required={false} toc={true}> | ||
| The URL of your page. | ||
| </ParamField> | ||
|
|
||
| ## Website metadata | ||
| <ParamField path="twitter:card" type="string" required={false} toc={true}> | ||
| The type of card used for sharing on Twitter. Options: `summary`, `summary_large_image`, `app`, `player`. | ||
| </ParamField> | ||
|
|
||
| Set default SEO metadata for your entire documentation site in [`docs.yml`](/docs/configuration/site-level-settings). These settings apply to all pages unless overridden by page-specific metadata. | ||
| ### Indexing | ||
|
|
||
| <Markdown src="/snippets/seo-metadata-site.mdx" /> | ||
| Control whether search engines index this page or follow its links. These are distinct: `noindex` removes the page from search results entirely, while `nofollow` keeps the page in results but tells search engines not to pass ranking credit through its links. | ||
|
|
||
| ## Page-level configuration | ||
| Use `noindex` for internal-only pages, staging content, or pages you don't want surfaced in search. Use `nofollow` sparingly — it's rarely needed for documentation. | ||
|
|
||
| Configure SEO metadata in your page's [frontmatter](/docs/configuration/page-level-settings) to control how individual pages appear in search results and social media shares. These settings override site-wide settings. | ||
| <ParamField path="noindex" type="boolean" required={false} default={false} toc={true}> | ||
| If `true`, the page won't be indexed by search engines and will be excluded from [`llms.txt`](/learn/docs/ai-features/llms-txt) endpoints. | ||
| </ParamField> | ||
|
|
||
| <Markdown src="/snippets/seo-metadata-page.mdx" /> | ||
| <ParamField path="nofollow" type="boolean" required={false} default={false} toc={true}> | ||
| If `true`, search engines won't follow any links on the page. | ||
| </ParamField> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| --- | ||
| title: Overview of SEO & GEO | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 [vale] reported by reviewdog 🐶 |
||
| description: Understand Fern's built-in features for search engine optimization (SEO) and generative engine optimization (GEO) to maximize the reach and discoverability of your documentation. | ||
| --- | ||
|
|
||
| Fern optimizes your documentation for both traditional search engines and AI-powered tools out of the box. SEO ensures your pages rank well in Google, Bing, and other search engines, while GEO (Generative Engine Optimization) ensures AI tools like ChatGPT, Claude, and Cursor can efficiently consume and reference your content. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 [vale] reported by reviewdog 🐶 |
||
|
|
||
| Out of the box, Fern generates meta tags, social previews, canonical URLs, and clean slugs for every page — including AI-optimized content via [`llms.txt`](/learn/docs/ai-features/llms-txt). When you want more control, you can customize: | ||
|
|
||
| <CardGroup cols={3}> | ||
| <Card title="SEO metadata" icon="fa-duotone fa-tags" href="/learn/docs/seo/setting-seo-metadata"> | ||
| Configure titles, descriptions, and social previews for search engines | ||
| </Card> | ||
| <Card title="Slugs" icon="fa-duotone fa-link" href="/learn/docs/seo/configuring-slugs"> | ||
| Customize URL paths for clean, meaningful page addresses | ||
| </Card> | ||
| <Card title="Redirects" icon="fa-duotone fa-arrow-right-arrow-left" href="/learn/docs/seo/redirects"> | ||
| Set up redirects to preserve SEO equity when pages move | ||
| </Card> | ||
| </CardGroup> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,26 +1,11 @@ | ||
| --- | ||
| title: Configure links and redirects for your site | ||
| subtitle: Learn how to configure redirects and external links in Fern Docs. Set up exact path redirects, regex patterns, and navigation links for your documentation site. | ||
| title: Configure redirects | ||
| subtitle: Learn how to configure redirects in Fern Docs. Set up exact path redirects and regex patterns to preserve SEO equity when pages move. | ||
| --- | ||
|
|
||
| ## Redirects | ||
|
|
||
| <Markdown src="/snippets/redirects.mdx" /> | ||
|
|
||
| ## Links | ||
|
|
||
| You can add a link to an external page within your sidebar navigation with the following configuration: | ||
|
|
||
| ```yaml title="docs.yml" | ||
| navigation: | ||
| - section: Home | ||
| contents: | ||
| - page: Introduction | ||
| path: ./intro.mdx | ||
| - link: Our YouTube Channel | ||
| href: https://www.youtube.com/ | ||
| ``` | ||
| <Tip> | ||
| To add external links to your sidebar navigation, see [Navigation](/learn/docs/configuration/navigation#links). | ||
| </Tip> | ||
|
|
||
| <Frame> | ||
| <img src="external-link.png" alt="An external link within navigation" /> | ||
| </Frame> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 [vale] reported by reviewdog 🐶
[Microsoft.URLFormat] Use 'of' (not 'for') to describe the relationship of the word URL to a resource.