Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 103 additions & 1 deletion fern/products/docs/pages/navigation/profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,108 @@ description: Write a page once and publish it in several editions. Profiles swap

A profile is a named set of values, such as a product name or CLI command. Write `${NAME}` in a page, and Fern swaps in the value from the profile. Give each product, version, or tab its own profile, and one page shows the right values in every edition, with no copies to maintain.

## See it in action

This site has two products, Community and Enterprise, that share one install page.

<Steps>
<Step title="Define a profile for each product">

```yaml docs.yml
profiles:
community:
vars:
PRODUCT: Acme
CLI: acme
enterprise:
vars:
PRODUCT: Acme Enterprise
CLI: acme-ent

profile: community

products:
- display-name: Community
slug: community
path: ./products/community.yml
- display-name: Enterprise
slug: enterprise
path: ./products/enterprise.yml
profile: enterprise
```

</Step>
<Step title="Write the page and its navigation once">

Both product files list the same pages, with placeholders in the sidebar titles.

<CodeBlocks>
````mdx pages/install.mdx
---
title: Install ${PRODUCT}
subtitle: Get ${PRODUCT} running in under a minute
---

Install the `${CLI}` command-line tool, then sign in.

```bash
npm install -g ${CLI}
${CLI} login
```

Check that ${PRODUCT} is installed:

```bash
${CLI} --version
```
````

```yaml products/community.yml
navigation:
- section: Get started
contents:
- page: Install ${PRODUCT}
path: ../pages/install.mdx
- page: Configure ${CLI}
path: ../pages/configure.mdx
```
</CodeBlocks>

</Step>
<Step title="Each product gets its own edition">

Fern builds the install page once per product. The title, subtitle, commands, and sidebar titles change with the profile.

<Tabs>
<Tab title="Community">
<div className="dark:hidden">
<Frame>
<img src="./assets/profiles-community-light.png" alt="The install page in the Community product, filled from the community profile" />
</Frame>
</div>
<div className="hidden dark:block">
<Frame>
<img src="./assets/profiles-community-dark.png" alt="The install page in the Community product, filled from the community profile" />
</Frame>
</div>
</Tab>
<Tab title="Enterprise">
<div className="dark:hidden">
<Frame>
<img src="./assets/profiles-enterprise-light.png" alt="The install page in the Enterprise product, filled from the enterprise profile" />
</Frame>
</div>
<div className="hidden dark:block">
<Frame>
<img src="./assets/profiles-enterprise-dark.png" alt="The install page in the Enterprise product, filled from the enterprise profile" />
</Frame>
</div>
</Tab>
</Tabs>

</Step>
</Steps>

## Define profiles

Add profiles to `docs.yml`, then select one with `profile`:
Expand Down Expand Up @@ -65,7 +167,7 @@ title: Install ${PRODUCT}
Run `${CLI} install`.
```

When both product files list `install.mdx`, Fern builds one page per product, each at its own URL. Under Enterprise, the page reads "Install Acme Enterprise" and "Run `acme-ent install`".
When both product files list `install.mdx`, Fern builds one page per product, each at its own URL. Each edition also gets its own canonical URL and sitemap entry, so search engines index every edition. Copies of a page with identical values (or no values) share one canonical URL. Under Enterprise, the page reads "Install Acme Enterprise" and "Run `acme-ent install`".

Values fill page content and frontmatter, navigation titles, navbar links, the announcement banner, and footer text. Search, Markdown output, and [`llms.txt`](/learn/docs/ai-features/llms-txt) get the same filled text. Endpoint and webhook descriptions from an API definition aren't filled.

Expand Down
2 changes: 1 addition & 1 deletion fern/products/docs/pages/seo/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Fern optimizes your documentation for both traditional search engines and AI-pow

Without any configuration, Fern generates meta tags, social previews, canonical URLs, [JSON-LD structured data](/learn/docs/seo/setting-seo-metadata#structured-data-json-ld), clean slugs, and AI-optimized content via [`llms.txt`](/learn/docs/ai-features/llms-txt) for every indexable page.

Fern also generates a `sitemap.xml` for your documentation site that follows [Google's sitemap best practices](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap). Each page entry includes a `<lastmod>` timestamp that updates only when the page's content actually changes. Trivial formatting differences like whitespace or capitalization are ignored. These timestamps are invisible to readers and used exclusively by search engines to prioritize crawling recently updated pages.
Fern also generates a `sitemap.xml` for your documentation site that follows [Google's sitemap best practices](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap). A page published in several [profile](/learn/docs/configuration/profiles) editions gets one entry per edition. Each page entry includes a `<lastmod>` timestamp that updates only when the page's content actually changes. Trivial formatting differences like whitespace or capitalization are ignored. These timestamps are invisible to readers and used exclusively by search engines to prioritize crawling recently updated pages.

<Info>
Sitemap timestamps are separate from the [`last-updated` frontmatter field](/learn/docs/configuration/page-level-settings#last-updated), which displays a visible date in the page footer for readers.
Expand Down
Loading