# Quickstart > Start building beautiful documentation in under 5 minutes Docs cascade With Fern, you can build beautiful developer documentation that matches your brand. Fern supports writing pages (written in Markdown) and generating API Reference documentation (from an OpenAPI Specification). In this guide, we'll show you how to get started with Fern in under 5 minutes. ### Initialize your `fern` folder All the configuration for your docs lives in the `fern` folder. Inside you'll find a `docs.yml` file that contains all the settings for your documentation. Get started by cloning the [starter template](https://github.com/fern-api/docs-starter-openapi). ```bash git clone git@github.com:fern-api/docs-starter-openapi.git ``` Next, please update the template settings to use your organization. Please edit the details `fern.config.json` and `docs.yml` with your organization name. ```json {2} { "organization": "{{YOUR_ORGANIZATION}}", "version": "0.x.x" } ``` ```yml {2} instances: - url: {{YOUR_ORGANIZATION}}.docs.buildwithfern.com ``` Finally, run `fern generate --docs` to generate your documentation. If you prefer, you can use our CLI to create a new project. Install the CLI by running ```bash npm install -g fern-api ``` Then run ```bash fern init --docs ``` You will see a new `fern` folder in your project with the following structure: ```bash fern ├─ docs.yml └─ fern.config.json ``` Finally, run `fern generate --docs` to generate your documentation. ### Update your docs We provide a white-glove migration service as part of our Enterprise plan. Interested? Request it [here](https://buildwithfern.com/contact). Add content with MDX files. ```markdown --- title: "Page Title" description: "Subtitle (optional)" --- Hello world! ``` Fern supports [GitHub flavored Markdown (GFM)](https://github.github.com/gfm/) within MDX files, no plugin required. In order for the Markdown page to show up, you'll need to reference them from your `docs.yml` file. You can reference the Markdown page within a section or as a standalone page. ```yml navigation: - page: "Hello World" path: "pages/hello-world.mdx" - section: Overview content: - page: QuickStart path: pages/hello-world.mdx ``` Add an API Reference by adding an OpenAPI Specification to your project. ```bash fern init --openapi /path/to/openapi.yml ``` This will create an `openapi.yml` file in your project. You can reference this file in your `docs.yml` file by adding an api block. ```yml navigation: - api: "API Reference" ``` All of the branding for your docs can be configured in the `docs.yml` file. For example, to set the logos, colors, and fonts for your docs, you can add the following to your `docs.yml` file: ```yml colors: accentPrimary: dark: "#f0c193" light: "#af5f1b" logo: dark: ./docs/assets/logo-dark.svg light: ./docs/assets/logo-light.svg height: 40 href: https://buildwithfern.com/ favicon: ./docs/assets/favicon.png ``` ### Publish to production Fern supports hosting your docs website on a custom domain or on a custom subpath (e.g. [https://domain.com/docs](https://domain.com/docs)). Please reach out to the Fern team at [support@buildwithfern.com](mailto:support@buildwithfern.com) to configure this. Fern supports integrations with a variety of providers such as PostHog, Segment, Intercom, Google Tag Manager, etc. Find out more on this [page](/learn/docs/integrations/overview). Below are some examples of documentation websites that have been published using Fern: } /> } /> } /> } /> } /> } /> } /> } /> # Global Configuration > Customize your documentation using the docs.yml file Not all of the properties in `docs.yml` are documented here. If you'd like to see all properties, please check out the the raw [schema](https://github.com/fern-api/fern/blob/69e74d9c27dc031ec2e84e70b878c40e9e9678a5/packages/cli/configuration/fern/definition/docs.yml#L110-L153) ## Top-level properties Every Fern documentation website needs a `docs.yml` file with the core configuration settings. ```yaml docs.yml title: My Docs logo: href: mydomain.com dark: path/to/logo.png light: path/to/logo.png favicon: path/to/favicon.ico ``` A string that is used as the tab bar title. Learn more about the `logo` configuration [here](/learn/docs/getting-started/global-configuration#logo-configuration). Relative filepath to the favicon. Configure the `primaryAccent` and `background` colors. Learn more about the `colors` configuration [here](/learn/docs/getting-started/global-configuration#colors-configuration). An array of paths you want to configure to permanently redirect to another path. Learn more about the `redirects` configuration [here](/learn/docs/getting-started/global-configuration#redirects-configuration). Array of names and urls of links you want to include as a call to action. Learn more about the `navbar-links` configuration [here](/learn/docs/getting-started/global-configuration#navbar-links-configuration). Set a custom background image to be displayed behind every page. Learn more about the `background-image` configuration [here](/learn/docs/getting-started/global-configuration#background-image-configuration). Customize the fonts used in your documentation website. Learn more about the `typography` configuration [here](/learn/docs/getting-started/global-configuration#typography-configuration). Customize the layout of your documentation website. Learn more about the `layout` configuration [here](/learn/docs/getting-started/global-configuration#layout-configuration). Creates a landing page for your documentation website. Learn more about the `landing-page` configuration [here](/learn/docs/getting-started/global-configuration#landing-page-configuration). Sets the default language displayed by code snippets in the API Reference. Options include: `typescript`, `python`, `java`, `go`, `ruby`, `csharp`, `curl` ## Instances configuration An `instance` is the backend of a distinct docs website. Each instance is published to a unique domain using the `--instance` flag. It is most common to use instances to configure staging and production docs which publish to separate URLs. ```yaml docs.yml instances: - url: plantstore.docs.buildwithfern.com custom-domain: docs.plantstore.com edit-this-page: github: owner: fern repo: plant-store-docs branch: main ``` The URL where your Fern documentation is deployed. Must contain the suffix `docs.buildwithfern.com` The custom domain where your documentation is hosted. Learn more about setting up a custom domain [here](/learn/docs/building-your-docs/custom-domain). If `edit-this-page` is set, Fern will add an "Edit this page" link to the bottom of each page that links to the given public GitHub repository. Learn more about the `edit-this-page` object [here](#github-configuration). ## Colors configuration ```yaml docs.yml colors: accent-primary: light: "#418326" dark: "#ADFF8C" background: light: "#ffffff" dark: "#0d0e11" ``` The configured accent primary color for light and dark mode. The configured background colors for light and dark mode. The border color is used for the borders of cards and other elements. If `sidebarBackground` is set, the sidebar will also render a 1px border on the right side. By default, the sidebar will render with a transparent background without a border. If `headerBackground` is set, the header will render with a solid background, with a 1px solid border on the bottom. By default, the header will render with a transparent background, with a 1px faded border on the bottom. The background color of cards and code blocks. ## Logo configuration ```yaml docs.yml logo: href: mydomain.com dark: path/to/logo.png light: path/to/logo.png ``` Where clicking on the logo links you to. Path to the image for the dark mode logo. You can exclude this if you don't have dark mode enabled. SVG format is recommended. Path to the image for the light mode logo. You can exclude this if you don't have light mode enabled. SVG format is recommended. ## Redirects configuration ```yaml docs.yml redirects: - source: "/old-path" destination: "/new-path" - source: "/old-folder/*" destination: "/new-folder/*" ``` The path that you want to redirect from. The path that you want to redirect to. Toggle between **permanent** and **temporary** redirect (default `false`). When true, the status code is 308. When false the status code is 307. ## NavBar links configuration ```yaml docs.yml navbar-links: - type: minimal text: Contact support href: https://example.com/support - type: filled text: Login href: https://example.com/login rounded: false ``` One of `outlined`, `minimal`, or `filled`. This value controls the styling of the button. The url once you click on the button. Example: [https://buildwithfern.com/contact](https://buildwithfern.com/contact) Text inside the button. When `true`, the border radius of the button will be fully rounded. The [Font Awesome icon](https://fontawesome.com/icons) to be used in the button. This icon will appear to the **left** of the text content. Pro and Brand Icons from Font Awesome are supported. The [Font Awesome icon](https://fontawesome.com/icons) to be used in the button. This icon will appear to the **right** of the text content. Pro and Brand Icons from Font Awesome are supported. By default, the `rightIcon` for a `filled` button is set to `arrow-right`. ## Background image configuration ```yaml docs.yml background-image: light: ./path/to/bg-light.svg dark: ./path/to/bg-dark.svg ``` Relative filepath to the light-mode background image. Relative filepath to the dark-mode background image. ## Typography configuration ```yaml docs.yml {2-16} typography: bodyFont: name: Inter-Regular path: ./fonts/Inter-Regular.woff2 headingsFont: name: Inter-Bold paths: - path: ./fonts/Inter-Bold.woff2 weight: "400" style: normal - path: ./fonts/Inter-Bold.woff2 weight: 500 900 # <-- indicates a range of weights style: normal codeFont: name: Roboto-Mono-Regular path: ./fonts/Roboto-Mono-Regular.woff2 ``` Customize page and section titles. If not supplied, defaults to the body font. Learn more about font configuration [here](/learn/docs/getting-started/global-configuration#font-configuration). Customize paragraph text and other body text. Learn more about font configuration [here](/learn/docs/getting-started/global-configuration#font-configuration). Customize code blocks and inline code snippets. Learn more about font configuration [here](/learn/docs/getting-started/global-configuration#font-configuration). ### Font configuration ```yaml title="Basic" {3-4} typography: bodyFont: name: Inter-Regular path: ./fonts/Inter-Regular.woff2 ``` ```yaml title="Variable Font" {3-10} typography: bodyFont: name: Inter-Regular paths: - path: ./fonts/Inter-Bold.woff2 weight: "400" style: normal - path: ./fonts/Inter-Bold.woff2 weight: 500 900 # <-- indicates a range of weights style: normal ``` The name of the font. Defaults to a generated name that will be used to reference your custom font in the eventually injected CSS. Relative filepath to a variable font file. If the font file is not variable, use `paths` instead. Supported font file types are `.woff` and `woff2`. A list of font files for particular weights. Each element in the list includes a `path`, `weight`, and `style` property. ## Layout configuration ```yaml docs.yml layout: header-height: 70px page-width: 1344px content-width: 672px sidebar-width: 336px searchbar-placement: header tabs-placement: header content-alignment: left ``` Sets the height of the header. Defaults to `4rem` (`64px`). Valid options are `{number}rem` or `{number}px`. Sets the maximum width of the docs layout, including the sidebar and content. Defaults to `88rem` (`1408px`). Valid options are `{number}rem`, `{number}px`, or `full`. Sets the maximum width of the Markdown article content. Defaults to `44rem` (`704px`). Valid options are `{number}rem` or `{number}px`. Sets the width of the sidebar in desktop mode. Defaults to `18rem` (`288px`). Valid options are `{number}rem` or `{number}px`. Sets the placement of the searchbar. Can be one of `header`, `sidebar` or `header_tabs` (places the searchbar in the header but on the tabs row). Defaults to `sidebar`. This setting is ignored when `disable-header` is set to true. Set the placement of the tabs. Can be one of `header` or `sidebar`. Defaults to `sidebar`. This setting is ignored when `disable-header` is set to true. Set the alignment of the Markdown content. Can be one of `center` or `left`. Defaults to `center`. If set to true, the header will not be rendered. Instead, the logo will be rendered as part of the sidebar, and a 1px border will separate the sidebar from the content. ## GitHub configuration ```yaml docs.yml edit-this-page: github: owner: fern repo: plant-store-docs branch: main ``` Be sure the repository is set to **public** visibility. The owner of the GitHub repository where you host your documentation. The name of the GitHub repository where you host your documentation. The branch of the repository you would like the GitHub editor to open a PR to. Default is `main`. ## Landing page configuration ```yaml docs.yml landing-page: page: Page Title path: path/to/landing-page.mdx ``` The name of the landing page. Relative filepath to the desired landing page Markdown file. See [VapiAI's landing page live](https://docs.vapi.ai/welcome) and the associated [Markdown file](https://github.com/VapiAI/docs/blob/main/fern/welcome.mdx?plain=1). # Project Structure > An overview of the file and folder structure of a Fern Docs project This page provides an overview of the file and folder structure of a Fern Docs project. The following structure is recommended for organizing your documentation content, but is customizable to fit your needs. ## Top-level folders ```bash fern ├─ pages ├─ assets ├─ docs.yml ├─ openapi └─ fern.config.json ``` A Fern Docs project has the following top-level folders: * `pages`: Contains the Markdown (MDX) files that make up your documentation. * `assets`: Contains any images or videos used in your documentation. * `docs.yml`: The configuration file that defines the navigation, theme, and hosting details of your documentation. * `openapi`: Contains the OpenAPI Specification file (if you have an API Reference section in your documentation). * `fern.config.json`: The configuration file specifying your organization name and CLI version. ## Pages folder The `pages` folder contains the Markdown (MDX) files that make up your documentation. Each MDX file represents a page in your documentation. ```bash pages ├─ introduction │ ├─ quickstart.mdx │ ├─ project-structure.mdx │ └─ showcase.mdx ├─ building-your-docs │ ├─ navigation │ ├─ sections.mdx │ ├─ tabs.mdx │ └─ versions.mdx └─ └─ configuration.mdx ``` The `pages` folder is organized into subfolders based on the sections of your documentation. Each subfolder contains the MDX files for the pages in that section. ## Assets folder The `assets` folder contains any images or videos used in your documentation. You can reference these assets in your MDX files using relative paths. ```bash assets ├─ favicon.ico ├─ product-screenshot.svg ├─ demo-video.mp4 ├─ logo-dark-mode.png └─ logo-light-mode.png ``` ## `docs.yml` The `docs.yml` file is the configuration file that defines the navigation, theme, and hosting details of your documentation. You can customize the appearance and behavior of your documentation by editing this file. ```yml instances: - url: fern.docs.buildwithfern.com/learn custom-domain: buildwithfern.com/learn navigation: - section: Introduction layout: - page: QuickStart path: pages/introduction/quickstart.mdx - page: Project Structure path: pages/introduction/project-structure.mdx - page: Showcase path: pages/introduction/showcase.mdx navbar-links: - type: filled text: Book a demo url: https://buildwithfern.com/contact logo: light: ./images/logo-primary.svg dark: ./images/logo-white.svg colors: accentPrimary: dark: "#ADFF8C" light: "#209d63" favicon: ./images/favicon.ico title: Fern's Documentation ``` ## API Definitions The `openapi` folder contains the OpenAPI Specification file for your API Reference section. Fern will read either a YAML or JSON file from this folder to generate the API Reference documentation. If you don't have an API Reference section, you can skip this folder. ```bash openapi └─ openapi.yaml # OR openapi.json ``` To see what this looks like in practice, check out [Vellum's Fern configuration](https://github.com/vellum-ai/vellum-client-generator/tree/main/fern/openapi). The `definition` folder contains the Fern Definition YAML files used to generate the API Reference section. If you don't have an API Reference section, you can skip this folder. ```bash definition ├─ pets.yaml ├─ owners.yaml ├─ stores.yaml └─ api.yaml ``` To see what this looks like in practice, check out [Pier's Fern configuration](https://github.com/pierdeveloper/pier-fern-def/tree/main/fern/definition). If you have multiple APIs, you can organize them into separate folders within the `apis` folder. Each API should have its own API definition. For example: ```bash apis ├─ admin │ └─ openapi.json ├─ user │ └─ openapi.yaml ``` To see what this looks like in practice, check out [OctoAI's Fern configuration](https://github.com/octoml/fern-config/tree/main/fern/apis). ## `fern.config.json` The `fern.config.json` file specifies your organization name and the version of the Fern CLI used to generate the documentation. You can customize this file to reflect your organization's details. ```json { "organization": "my-organization", "version": "0.24.0" } ``` # Preview changes locally > View and share updates to your documentation Fern offers two ways to preview changes to your documentation: a [local development environment](#local-development) and [unique preview links](#generate-a-preview-link). ## Local development Fern allows you to view changes to your documentation in a locally-hosted environment. **Prerequisite** : Please install Node.js (version 18 or higher) before proceeding. Follow these steps to install and run the Fern CLI: **Step 1**: Install the Fern CLI: ```bash npm npm i -g fern-api ``` ```bash yarn yarn global add fern-api ``` **Step 2**: Navigate to the docs directory (where the `fern` folder is located) and execute the following command: ```bash fern docs dev ``` A local preview of your documentation will be available at `http://localhost:3000`. The functionality is available offline if you have run local development mode online at least once. Some features (e.g. search) are disabled in the local development environment. ### Custom ports By default, Fern uses port 3000. You can customize the port Fern runs on by using the `--port` flag. For example, to run Fern on port 3002, use this command: ```bash fern docs dev --port 3333 ``` If you attempt to run Fern on a port that's already in use, it will use the next available port: ## Generate a preview link Fern allows you to generate a shareable preview link displaying the current state of your docs. Each preview link is appended with a UUID and is not indexed. Currently, these links do not expire (this behavior is subject to change in the future). **Usage**: ```bash fern generate --docs --preview ``` **Example**: ```bash fern generate --docs --preview [docs]: Found 0 errors and 1 warnings. Run fern check --warnings to print out the warnings. [docs]: Published docs to https://fern-preview-a1da0157-93ca-4b1f-b310-8dd34fb891ca.docs.buildwithfern.com ┌─ │ ✓ docs.example.com └─ ``` # Publishing your docs When you are ready for your docs to be publicly accessible, you can publish them using the Fern CLI. ## Usage ```bash fern generate --docs ``` ### Example ```bash fern generate --docs [docs]: Found 0 errors and 1 warnings. Run fern check --warnings to print out the warnings. [docs]: ✓ All checks passed [docs]: Published docs to https://plantstore.docs.buildwithfern.com ┌─ │ ✓ https://plantstore.docs.buildwithfern.com └─ ``` ### Usage in GitHub Actions To automate the publishing process, you can use a GitHub Action workflow to publish your docs when a push is made to the `main` branch. [Be sure to add the `FERN_TOKEN` for your organization to the repository](/learn/cli-api/cli-reference/commands#fern-token). ```yaml .github/workflows/publish-docs.yml name: Publish Docs on: push: branches: - main jobs: run: runs-on: ubuntu-latest if: ${{ github.event_name == 'push' && contains(github.ref, 'refs/heads/main') && github.run_number > 1 }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install Fern run: npm install -g fern-api - name: Publish Docs env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} run: fern generate --docs ``` ## Hosting When you publish your docs, Fern takes care of hosting them for you. To publish your docs to a custom domain, check out our docs [here](/learn/docs/building-your-docs/custom-domain). ### Self-hosting your docs This feature is available on the Enterprise plan. [Contact us](https://buildwithfern.com/contact) to learn more. If you need access to your docs offline or would like to host your docs on your own server, Fern offers that option as well. Self-hosted docs have limited access to certain features (including search). # Configure your site navigation > Set up the navigation for your documentation site built with Fern Docs using the docs.yml file, including tabs, sections, pages, and more. ## Use `docs.yml` Every Fern Docs website has a special configuration file called `docs.yml`. Use this file to configure the navigation for your documentation site. ```yaml navigation: - section: Home contents: - page: Introduction path: ./intro.mdx - page: Authentication path: ./auth.mdx - api: API Reference navbar-links: - type: secondary text: Contact support url: https://example.com/support - type: primary text: Login url: https://example.com/login ``` ## Sections, contents, and pages The navigation organizes your documentation in the left-side nav bar. You can create sections for grouping related content. Each `section` has a name and a list of `contents`. The sections appear in the left-side nav bar in the order that they are listed in `docs.yml`. In `contents`, list your pages with names and corresponding file paths. The supported file types for pages are `.md` or `.mdx`. A basic navigation configuration with two sections is shown below. The first section is called `Introduction` and contains a single page called `My Page`. The second section is called **API Reference**. This is a special type of section that's automatically generated by Fern, and you do not need to add any pages to it by hand. For more information, see the [Generate API Reference](/learn/docs/api-references/generate-api-ref) page. ```yaml Example navigation config navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - api: API Reference ``` If you want to add another page to an existing section, create an `.md` or `.mdx` file. Then in `docs.yml`, create a new `page` in the `contents` list for that section, providing the path to the `.md` or `.mdx` file you created. Example: ```yaml Example navigation config navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - page: Another Page path: ./pages/another-page.mdx - api: API Reference ``` To add another section, add another `section` to the `navigation`. Example: ```yaml Example navigation config with additional section navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - api: API Reference - section: Help Center contents: - page: Contact Us path: contact-us.mdx ``` ### Hiding content To hide a page or an entire section of your docs, add `hidden: true`. A hidden page or section will still be discoverable using the exact URL, but it will be excluded from search and will not be indexed. ```yaml Example navigation config with additional section {7, 10} navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - page: Hidden Page hidden: true path: ./pages/my-hidden-page.mdx - section: Hidden Sections hidden: true contents: - page: Another Hidden Page path: ./pages/also-hidden.mdx ``` ## Section overviews To add an overview page to a section, add a `path` property to the section. ```yaml Example section with an overview {7} navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - section: Guides path: ./pages/guide-overview.mdx contents: - page: Simple Guide path: ./pages/guides/simple.mdx - page: Complex Guide path: ./pages/guides/complex.mdx ``` ## Nested sections If you'd like a section to toggle into more sections and pages, you can nest sections within sections. Here's an example: ```yaml Example navigation config with nested sections navigation: - tab: guides layout: - section: Learn contents: - section: Key Concepts contents: - page: Embeddings path: ./docs/pages/embeddings.mdx - page: Prompt Engineering path: ./docs/pages/prompts.mdx - section: Generation contents: - page: Command Nightly path: ./docs/pages/command.mdx - page: Likelihood path: ./docs/pages/likelihood.mdx ``` ![Result of above docs.yml example](https://fern-image-hosting.s3.amazonaws.com/fern/nested-sections.png) ## Sidebar icons For icons to appear next to sections and pages, add the `icon` key. The value should be a valid [Font Awesome icon](https://fontawesome.com/icons) name. Pro and Brand Icons from Font Awesome are supported. ```yaml Example navigation config with icons navigation: - section: Home icon: fa-regular fa-home contents: - page: My Page icon: fa-regular fa-file path: ./pages/my-page.mdx - api: API Reference icon: fa-regular fa-puzzle ``` ## 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/ ``` An external link within navigation ## Tabs Within the navigation, you can add `tabs`. Tabs are used to group sections together. The example below shows tabs for `Help Center`, `API Reference`, and an external link to `Github`. Each tab has a `title` and `icon`. [Browse the icons available](https://fontawesome.com/icons) from Font Awesome. Pro and Brand Icons are supported. ```yaml tabs: api: display-name: API Reference icon: puzzle help: display-name: Help Center icon: home github: display-name: GitHub icon: brands github href: https://github.com/fern-api/fern navigation: - tab: api layout: - section: Introduction contents: - page: My Page path: my-page.mdx - api: API Reference - tab: help layout: - section: Help Center contents: - page: Contact Us path: contact-us.mdx - tab: github ``` Here's an example of what the Tabs implementation looks like: ![Screenshot showing two vertically stacked tabs labeled API Reference and Help Center](https://fern-image-hosting.s3.amazonaws.com/fern/tabs.png) ## Versions If you have multiple versions of your documentation, you can introduce a dropdown version selector by specifying the `versions`. For more information, check out our [documentation on versioning](/learn/docs/building-your-docs/versioning). # Versioning > Allow users to navigate between different versions of your docs. ![A dropdown of the available versions](file:9cd760a4-1a46-4816-bf37-7471aed3bf39) Each version of your docs can contain its own distinct tabs, sections, pages, and API references. Versions can share content, as well. **To add versions to your docs:** ### Define your versions Create a `versions` folder inside of your `fern` folder. TO specify the contents of each version, add a `.yml` file to the `versions` folder to define the navigational structure of that version. Make sure to include the `navigation` and `tabs` properties, if applicable. ```bash fern/ ├─ fern.config.json ├─ generators.yml ├─ docs.yml ├─ pages/ ├─ ... └─ versions/ ├─ v2-1/pages/... ├─ v2-1.yml ├─ v2-2/pages/... └─ v2-2.yml ``` ```yaml navigation: - section: Introduction contents: - page: My Page path: ./v2-1/pages/my-page.mdx # relative path to the file - page: Shared Resource path: ../shared-pages/shared-resource.mdx - api: API Reference ``` ```yaml tabs: api: title: API Reference icon: puzzle help: title: Help Center icon: home navigation: - tab: api contents: - section: Introduction contents: - page: My Page path: ./v2-2/pages/my-page.mdx # relative path to the file - page: Shared Resource path: ../shared-pages/shared-resource.mdx - api: API Reference - tab: help contents: - section: Help Center contents: - page: Contact Us path: contact-us.mdx ``` ### Add your version configuration To define a version, in `docs.yml`, add an item to the `versions` list, specifying the `display-name` and `path`. ```bash fern/ ├─ fern.config.json ├─ generators.yml ├─ docs.yml └─ versions/ ├─ ... ├─ v2-1.yml └─ v2-2.yml ``` ```yaml versions: - display-name: v2.2 # shown in the dropdown path: ./versions/v2-2.yml # relative path to the version file - display-name: v2.1 path: ./versions/v2-1.yml ``` ### Remove extra `navigation` from `docs.yml` If your `docs.yml` file includes a `navigation` field or a `tabs` field, be sure to remove. Those fields should now belong in the version-specific `.yml` files. # Add an announcement banner to your docs > Prominently highlight new features, updates, or important information An announcement banner is a great way to draw attention to new features and product launches. When configured, the announcement bar appears at the top of your docs site. After the user dismisses the bar, it will reappear the next time you update the announcement. ```yaml docs.yml announcement: message: "🚀 New feature: Announcements are available! (Learn more) 🚀" ``` Markdown and HTML is supported in the announcement message. You can include links, images, and other formatting. [Custom css](/learn/docs/building-your-docs/custom-css-global-js#custom-css) can be used to customize the style of the announcement. Another docs change # Configure links and redirects for your site > Set up the navigation for your documentation site built with Fern Docs using the docs.yml file ## Redirects The `redirects` object allows you to redirect traffic from one path to another. You can also use [`regex`](https://www.npmjs.com/package/path-to-regexp) within redirects. ```yml redirects: - source: "/old-path" destination: "/new-path" - source: "/incorrect/path" destination: "/correct/path" - source: "/old-folder/:slug" # <- using regex destination: "/new-folder/:slug" ``` By default, the redirects implement temporary (302) redirects. If you would like to implement permanent (301) redirects, you can set `permanent: true`. ```yml redirects: - source: "/old-subdomain" destination: "/new-subdomain" permanent: true ``` If your docs are hosted on a subpath (like `buildwithfern.com/learn`), be sure to include the subpath in the redirect. ## 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/ ``` An external link within navigation # Customizing slugs within your site By default, Fern generates the slug of a page based on the navigation structure in the `docs.yml` file. ```yaml docs.yml {5, 7} instances: - url: plantstore.docs.buildwithfern.com navigation: - section: Get Started contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/get-started/welcome`. ```yaml docs.yml {5, 13, 15} instances: - url: plantstore.docs.buildwithfern.com tabs: docs: display-name: Docs reference: display-name: API Reference navigation: - tab: docs layout: - section: Get Started contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/docs/get-started/welcome`. ### Renaming slugs #### Modify a page or section slug To modify the slug used for a page or section, you can set the `slug` within the `navigation` object. ```yaml {3, 6} navigation: - section: Get Started slug: start contents: - page: Welcome slug: intro path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/start/intro`. #### Modify a tab slug To modify the slug used for a tab, you can set the `slug` within the `tabs` object. ```yaml {4} tabs: docs: display-name: Docs slug: guides reference: display-name: API Reference navigation: - tab: docs layout: - section: Get Started contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/guides/get-started/welcome`. #### Override a page's slug You can set the exact slug of a page within its frontmatter. [You can read more about the frontmatter configuration here](/learn/docs/content/frontmatter#slug). ```yaml title="docs.yml" navigation: - section: Get Started slug: start contents: - page: Quick Start path: ./docs/pages/quick-start.mdx ``` You can set the slug in the frontmatter of `./docs/pages/quick-start.mdx` to `start-up`: ```markdown title="quick-start.mdx" {2} --- slug: start-up --- ``` The page then becomes available at `plantstore.docs.buildwithfern.com/start-up`. #### Renaming slugs for subheadings By default, deep links to subheadings are generated by appending a `#` and the subheading title (converted to `kebab-casing-convention`) onto the page URl. ```yaml docs.yml navigation: - section: Get Started contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` ```markdown welcome.mdx ... ## Frequently Asked Questions ... ``` The link to this section will be available at `plantstore.docs.buildwithfern.com/get-started/welcome#frequently-asked-questions`. To rename the slug of the subheading, add the desired slug ```markdown welcome.mdx ## Frequently Asked Questions [#faqs] ``` The link to this section will now be available at `plantstore.docs.buildwithfern.com/get-started/welcome#faqs`. ### Skipping slugs To ignore a tab or section when generating the slug, simply indicate `skip-slug: true`. ```yaml docs.yml {6} instances: - url: plantstore.docs.buildwithfern.com navigation: - section: Get Started skip-slug: true contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/welcome`. ```yaml docs.yml {7, 15} instances: - url: plantstore.docs.buildwithfern.com tabs: docs: display-name: Docs skip-slug: true reference: display-name: API Reference navigation: - tab: docs layout: - section: Get Started skip-slug: true contents: - page: Welcome path: ./docs/pages/welcome.mdx ``` In the example above, the **Welcome** page would be hosted at `plantstore.docs.buildwithfern.com/welcome`. # Hiding content in your site If you would like to *hide* a section or a page, you can add `hidden: true` to its configuration. Hidden sections and pages are accessible by URL only. ```yaml title="docs.yml" navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - page: Hide and Seek hidden: true path: ./pages/hide-and-seek.mdx - api: API Reference ``` A site with a hidden page ```yaml title="docs.yml" navigation: - section: Introduction contents: - page: My Page path: ./pages/my-page.mdx - api: API Reference - section: Hidden Section hidden: true contents: - page: Hide and Seek path: ./pages/hide-and-seek.mdx ``` A site with a hidden section # Fully customize your docs > Add brand-specific styling, user interactions. and components to make your docs your own. Custom CSS & JS are available on the Basic plan. Adding Custom Components is available on the Pro plan. ## Custom CSS You can add custom CSS to your docs to further customize the look and feel. The defined class names are applied across all MDX files. Here's an example of what you can do with custom CSS: ```css maxLines=10 .petstore-table { background-color: white; border: 1px solid #DEDEE1; border-radius: 4px; } .dark .petstore-table { background-color: #1e1e1e; border: 1px solid #2e2e2e; } .petstore-table thead { position: sticky; top: 0; } .petstore-table thead tr { background-color: #edecee; border: 1px solid #DEDEE1; border-radius: 4px 4px 0px 0px; } .dark .petstore-table thead tr { background-color: #2e2e2e; border: 1px solid #2e2e2e; } .petstore-table th { padding: 6px; } .petstore-table tbody td { padding: 6px; } .petstore-table tbody tr:nth-child(odd) { border: 1px solid #DEDEE1; } .petstore-table tbody tr:nth-child(even) { border: 1px solid #DEDEE1; background-color: #f7f6f8; } .dark .petstore-table tbody tr:nth-child(odd) { border: 1px solid #2e2e2e; } .dark .petstore-table tbody tr:nth-child(even) { border: 1px solid #2e2e2e; background-color: #2e2e2e; } ``` ### Create `styles.css` Add a `styles.css` file and include it in your `fern/` project: ```bash {5} fern/ ├─ openapi/ ├─ pages/ ├─ images/ ├─ styles.css ├─ docs.yml └─ fern.config.json ``` ### Edit `docs.yml` In `docs.yml`, specify the path to the `styles.css` file: ```yaml css: ./styles.css ``` ### Add multiple custom CSS files (optional) You can specify any number of custom CSS files: ```yaml css: - ./css/header-styles.css - ./css/footer-styles.css ``` For customizing the background, logo, font, and layout of your Docs via Fern's built-in styling, check out the [Global Configuration](/learn/docs/getting-started/global-configuration). ## Custom JavaScript Customize the behavior of your Docs site by injecting custom JavaScript globally. Add a `custom.js` file and include it in your `fern/` project: ```bash {5} fern/ ├─ openapi/ ├─ pages/ ├─ images/ ├─ custom.js ├─ docs.yml └─ fern.config.json ``` In `docs.yml`, specify the path to the `custom.js` file: ```yaml js: ./custom.js ``` You can also specify multiple custom JS files stored locally and remote: ```yaml js: - path/to/js/file.js - path: path/to/another/js/file.js strategy: beforeInteractive - url: https://example.com/path/to/js/file.js ``` ### Strategy Optionally, specify the strategy for each custom JavaScript file. Choose from `beforeInteractive`, `afterInteractive` (default), and `lazyOnload`. ```yaml js: - path: path/to/another/js/file.js strategy: beforeInteractive ``` ## Custom components You can use custom CSS and JS to replace Fern's default UI components with your own. The `header` and `footer` are the most commonly replaced components. You can replace any component in the docs, including the sidebar, tabs, search bar, and more. To implement your own components in Fern Docs, write JavaScript to render your custom components in the DOM. Build to CSS and JavaScript files that are stored in `fern/` and referenced in `docs.yml`: ```bash {5-7} fern/ ├─ openapi/ ├─ pages/ ├─ images/ ├─ dist/ └─ output.css └─ output.js ├─ docs.yml └─ fern.config.json ``` ```yaml css: ./dist/output.css js: ./dist/output.js ``` ### Example custom components See this [GitHub repo](https://github.com/fern-api/docs-custom-js-example) and its [generated docs page](https://custom-js-example.docs.buildwithfern.com/get-started/welcome) for an example of how to replace the Fern `header` and `footer` with custom React components. #### Example custom header Custom header ```JavaScript ReactDOM.render( React.createElement(NavHeader), document.getElementById('fern-header'), ) ``` #### Example custom footer Custom footer ```JavaScript ReactDOM.render( React.createElement(NavFooter), document.getElementById('fern-footer'), ) ``` ### Important notes * `ReactDOM.render()` may need to be called multiple times to prevent it from unmounting (this side-effect will be removed in the future). * `yarn build` or `npm build` must generate files with deterministic names to be referenced in `docs.yml`. The above example uses a [`vite` config](https://github.com/fern-api/docs-custom-js-example/blob/main/custom-app/vite.config.ts) to accomplish this. * For your hosted Docs site, you may need to update your CD steps to include building the react-app. This approach is subject to change, with notice, as we make improvements to the plugin architecture. # Pull request previews > Fern's PR previews feature lets you preview changes to your docs from pull requests before merging to the live docs site. Use manually or in GitHub Actions. `PR previews` offer a way to preview changes from pull requests (PRs) before merging code to a production branch. This is useful for reviewing documentation changes before publishing them to your live documentation site. Use manually or in GitHub Actions. ## Usage ```bash fern generate --docs --preview ``` ## Example ```bash fern generate --docs --preview [docs]: Found 0 errors and 1 warnings. Run fern check --warnings to print out the warnings. [docs]: Published docs to https://fern-preview-a1da0157-93ca-4b1f-b310-8dd34fb891ca.docs.buildwithfern.com ┌─ │ ✓ docs.example.com └─ ``` ## Usage in GitHub Actions The following is a GitHub Action workflow that generates a preview URL for every pull request. [Be sure to add the `FERN_TOKEN` for your organization to the repository](/learn/cli-api/cli-reference/commands#fern-token). ```yaml name: preview-docs on: pull_request jobs: run: runs-on: ubuntu-latest permissions: write-all steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install Fern run: npm install -g fern-api - name: Generate preview URL id: generate-docs env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} run: | OUTPUT=$(fern generate --docs --preview 2>&1) || true echo "$OUTPUT" URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()') echo "Preview URL: $URL" echo "🌿 Preview your docs: $URL" > preview_url.txt - name: Comment URL in PR uses: thollander/actions-comment-pull-request@v2.4.3 with: filePath: preview_url.txt ``` Fern's PR previews GitHub Action requires a Fern token to run. Depending on your repository's permissions, you may need to use the following workflow to allow PR previews from forks to access this token. ```yaml .github/workflows/preview-docs.yml name: preview-docs on: pull_request_target: branches: - main jobs: run: runs-on: ubuntu-latest permissions: pull-requests: write # Only for commenting contents: read # For checking out code steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install Fern run: npm install -g fern-api - name: Checkout PR if: github.event_name == 'pull_request_target' run: | git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-${{ github.event.pull_request.number }} git checkout pr-${{ github.event.pull_request.number }} - name: Generate preview URL id: generate-docs env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} run: | OUTPUT=$(fern generate --docs --preview 2>&1) || true echo "$OUTPUT" URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()') echo "Preview URL: $URL" echo "🌿 Preview your docs: $URL" > preview_url.txt - name: Comment URL in PR uses: thollander/actions-comment-pull-request@v2.4.3 with: filePath: preview_url.txt ``` ## Link expiration Preview links do not expire. However, the time to live (TTL) is subject to change in the future. # Bring your custom domain > Learn how to set up your Fern-generated documentation site to use a custom subdomain or subpath. Bring Fern Docs to your custom domain. You can use: * A subdomain on your custom domain, such as `docs.example.com` * A subpath on your custom domain, such as `example.com/docs` This feature is available on the Basic plan and above. [Contact us](https://buildwithfern.com/contact) to get set up. To host your documentation on a subdomain, i.e. `docs.mydomain.com`, you need to create a CNAME record in your DNS settings. ### Update the domain in `docs.yml` ```yaml instances: - url: example.docs.buildwithfern.com custom-domain: docs.mydomain.com ``` Merge your changes into `main`. [Here's an example](https://github.com/octoml/fern-config/blob/389b67679953856ba0716537981a6d749635556f/fern/docs.yml#L1-L3). ### Create a CNAME record 1. Log in to your domain registrar's dashboard. 2. Navigate to the DNS settings for your domain. 3. Add a new CNAME record with the following details: * **Type**: `CNAME` * **Name**: `docs` (or any subdomain you want to use) * **Value**: `cname.vercel-dns.com.` ### Reach out to us Once you've completed the steps above, reach out via your dedicated Slack channel or [email](mailto:support@buildwithfern.com). You may need to create a TXT record to verify your domain. If you do, we'll provide you with the record to add. ### Verify the setup Once we've completed the setup on our end, you should be able to access your documentation at `docs.mydomain.com`. SSL will be automatically provisioned for your domain, but it may take a few minutes to propagate globally. It's helpful to check that you can access your new docs site from a mobile device or incognito browser. To host your documentation on a subpath, i.e. `mydomain.com/docs`, you need to edit your `docs.yml` configuration and then get provider-specific instructions for setting up the subpath. Common providers include Cloudflare, AWS Route53 and Cloudfront, Netlify, and Vercel. ### Configure the `url` in `docs.yml` Append that subpath to the end of the `url`. This example use `docs` for the subpath, but you can use any word you like, such as `reference` or `developer`. ```yaml instances: - url: example.docs.buildwithfern.com/docs ``` ### Configure the `custom-domain` Below the `url`, add a `custom-domain` key as shown in the examples below. ```yaml instances: - url: example.docs.buildwithfern.com/docs custom-domain: example.com/docs ``` [Here's an example.](https://github.com/fern-api/fern/blob/7d8631c6119787a8aaccb4ba49837e73c985db28/fern/docs.yml#L1-L3) ### Update the Fern Docs site If you created your Fern Docs site using one of our [Docs Quickstarts](/learn/docs/getting-started/quickstart), push the changes you made to your GitHub repository. This runs a GitHub Action to update the site with your new configuration. If you need to update your Fern Docs site manually, run `fern generate --docs`. ### Reach out to us This feature is available on the Fern Docs Basic plan and above. Reach out to [sales@buildwithfern.com](mailto:sales@buildwithfern.com) to set up your subscription and obtain the configuration for setting up your custom subpath. # Collecting feedback and suggestions from users Fern offers a variety of ways to track feedback and suggested improvements from users. ## On-page feedback By default, every Markdown page of your docs contains a feedback component at the bottom of the page: This feature is available on the Basic plan and above. [Contact us](https://buildwithfern.com/contact) to get set up. The feedback can be sent to you in real-time via the method of your choosing (e.g. Slack, email). To disable this feature on a page, set `hide-feedback: true` in the frontmatter of that page. You can read more about the frontmatter configuration [here](/learn/docs/content/frontmatter#on-page-feedback). ## Edit this page Allow users to open directly to the current page in your GitHub repository and suggest changes. You can configure this feature for the entire site in the [global configuration](/learn/docs/getting-started/global-configuration#instances-configuration), or for an individual page in the [frontmatter of that page](/learn/docs/content/frontmatter#edit-this-page). # Write docs content using Markdown > Use Markdown and MDX to add content to your Fern documentation site, including Fern's built-in component library. ## Add Markdown or MDX pages Add pages manually to your documentation by creating Markdown (`.md`) or MDX (`.mdx`) files. New to Markdown? See [Markdown Guide: Getting started](https://www.markdownguide.org/getting-started/). NOTE: Throughout our documentation, we refer to both Markdown and MDX as Markdown. [MDX](https://mdxjs.com/) is a version of Markdown, extended to allow the use of JSX components. Place your pages inside your `fern/` folder and link to them from your [navigation settings](/learn/docs/building-your-docs/navigation) in the `docs.yml` file. In the example below, the MDX files are inside a folder named `pages/`. ```bash fern/ ├─ fern.config.json ├─ docs.yml └─ pages/ ├─ welcome.mdx └─ quickstart.mdx ``` ```yml navigation: - section: Overview contents: - page: Welcome path: ./pages/welcome.mdx - page: Quickstart path: ./pages/quickstart.mdx ``` ## Page header Fern automatically generates the `

` page header for each page from `docs.yml`. For example, here's the `docs.yml` entry that maps the page you are reading now: ```yml - page: Write Markdown content path: ./docs/pages/fern-docs/content/write-markdown.mdx ``` The value for `page` is used as the content of the top `

` element of this page. Thus, when adding content to your Markdown pages, begin with `

` instead of `

`. ## Fern components Fern has a built-in component library you can use in Markdown. [Explore the components.](/learn/docs/content/components/overview) ## Links in Markdown ### Link target When clicked, links to relative URLs open in the same tab, whereas links to absolute URLs open in a new browser tab. ### Link format Use a `/` character to begin a relative URL to another page on your docs site. This routes to the `url` defined in your `docs.yml` file, such as `example-docs.buildwithfern.com`. For example, if you want to link to `https://example-docs.buildwithfern.com/overview/introduction`, you can write the link in Markdown as follows: ```mdx Read the [Introduction](/learn/overview/introduction). ``` ## Images You can use locally stored images or URLs to include images in your Markdown pages. Use either [Markdown syntax](https://www.markdownguide.org/basic-syntax/#images-1) or the [`` HTML tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img) to insert the image. ## LaTeX Fern supports [LaTeX](https://www.latex-project.org/) math equations. To use LaTeX, wrap your inline math equations in `$`. For example, `$(x^2 + y^2 = z^2)$` will render $x^2 + y^2 = z^2$. For display math equations, wrap the equation in `$$`. For example: ```latex $$ % \f is defined as #1f(#2) using the macro \f\relax{x} = \int_{-\infty}^\infty \f\hat\xi\,e^{2 \pi i \xi x} \,d\xi $$ ``` ## Diagrams Fern supports creating diagrams within your Markdown using [Mermaid](https://mermaid.js.org/). Mermaid offers a variety of diagrams, including flowcharts, entity-relationship models, and Gantt charts. To include a Mermaid diagram in your Markdown file, create a codeblock marked with `mermaid`. ````markdown ```mermaid erDiagram CUSTOMER ||--o{ PLANT-ORDER : places PLANT-ORDER ||--|{ PLANT-ID : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses ``` ```` ```mermaid erDiagram CUSTOMER ||--o{ PLANT-ORDER : places PLANT-ORDER ||--|{ PLANT-ID : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses ``` # Components Overview > Enhance your docs with Fern's built-in component library. Use components to create interactive and engaging documentation. Fern provides a library of 15+ built-in-components to make your documentation more interactive and engaging. Components are building blocks that you can add to any MDX page. ## Usage Specify a component in your MDX file while writing content. For example, to add a `Card` component, use the following syntax: ```mdx Give us a star! Fern's CLI & docs source code is available on GitHub. ``` This will automatically render a card with the title, icon, and content you specified. Give us a star! The source code to Fern's CLI is available on GitHub. ## Bring your own components Want to bring your own UI components, such as a custom header and footer? You can on the Enterprise plan. [Contact us](https://buildwithfern.com/contact) to learn more. ## Requests for new components Have a component in mind that you'd like to see in Fern? Let us know by filing a [GitHub Issue](https://github.com/fern-api/fern/issues/new?assignees=\&labels=\&projects=\&template=feature-request.md\&title=%5BFeature%5D). # Accordions > Expand or collapse to reveal more information Standalone content # Accordion Groups > Display expandable/collapsible options that can reveal more information You can put other components inside Accordions. ```ts index.ts export function generateRandomNumber() { return Math.random(); } ``` This is a second option. This is a third option. # Aside > Push any content inside the Aside component to the right of the page in a sticky container ```jsx ``` # Callouts > A built-in component to show important information to the reader ## Callout properties Customize your Callouts using the `title` and `icon` properties. The title of your Callout The icon of your Callout. Can be a [Font Awesome](https://fontawesome.com/icons) icon name or an HTML element.
This Callout uses a title and a custom icon. ```markdown This Callout uses a title and a custom icon. ``` ## Callout varieties ### Note callouts This adds a note in the content ```jsx This adds a note in the content ``` ### Warning callouts This raises a warning to watch out for ```jsx This raises a warning to watch out for ``` ### Error callouts This indicates a potential error ```jsx This indicates a potential error ``` ### Info callouts This draws attention to important information ```jsx This draws attention to important information ``` ### Tip callouts This suggests a helpful tip ```jsx This suggests a helpful tip ``` ### Check callouts This brings us a checked status ```jsx This brings us a checked status ``` # Cards > Use cards to display content in a box ### Basic The icon field references a Font Awesome icon. ### Custom icon } href="https://github.com/fern-api/fern/tree/main/generators/python"> Pass in an image tag to use a custom icon. ### Icon position You can set the icon positon as `left` or `top`. Default is `top`. # Card Groups > Show cards side by side in a grid format The `CardGroup` component lets you group multiple `Card` components together. It's most often used to put multiple cards on the same column. This is the first card. This is the second card. This is the third card. This is the fourth and final card. # Code Blocks > Write beautiful code snippets in your documentation Fern uses [Shiki](https://shiki.matsu.io/) to do syntax highlighting. It's very reliable and performant. Below are examples of how you can configure syntax highlighting in code snippets. ## Basic To create a code snippet, you need to wrap your code in three backticks. You can also specify the language for syntax highlighting after the opening backticks. ```js console.log("hello world") ``` ````mdx ```js console.log("hello world") ``` ```` ## Titles You can add a title to your code snippet by adding a title after the language identifier. ```js Hello World Snippet console.log("hello world") ``` ````mdx ```js Hello World Snippet console.log("hello world") ``` ```` You may also use a `title` prop or `filename` prop to achieve the same result. For example, `title="Hello World Snippet"` or `filename="Hello World Snippet"`. ## Line highlighting You can highlight specific lines in your code snippet by placing a numeric range inside `{}` after the language identifier. ```js {2-4} console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); ``` ````markdown ```javascript {2-4} console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); ``` ```` The range is inclusive and can be a single number, a comma-separated list of numbers, or ranges. For example, `{1,3,5-7}` will highlight lines 1, 3, 5, 6, and 7. ## Line focusing Instead of highlighting lines, you can focus on specific lines by adding a comment `[!code focus]` or by adding a `focus` attribute after the language identifier. The `focus` attribute works the same way as the `highlight` attribute. ```javascript focus={2-4} console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); ``` ````markdown ```javascript focus={2-4} console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); ``` ```` ## Max height You can control the max height of the code block by adding a `maxLines` attribute after the language identifier. The `maxLines` attribute should be a number representing the maximum number of lines to display. By default, the code block will display up to 20 lines. ```python maxLines=10 def is_prime(num): """Check if a number is prime.""" if num <= 1: return False for i in range(2, num): if num % i == 0: return False return True start = 10 end = 50 print(f"Prime numbers between {start} and {end} are:") prime_numbers = [] for num in range(start, end+1): if is_prime(num): prime_numbers.append(num) for prime in prime_numbers: print(prime) ``` ````markdown maxLines=10 ```python maxLines=10 def is_prime(num): """Check if a number is prime.""" if num <= 1: return False for i in range(2, num): if num % i == 0: return False return True start = 10 end = 50 print(f"Prime numbers between {start} and {end} are:") prime_numbers = [] for num in range(start, end+1): if is_prime(num): prime_numbers.append(num) for prime in prime_numbers: print(prime) ``` ```` To disable the default 20 lines limit, you can set `maxLines` to `0`. ## Wrap overflow By default, long lines that exceed the width of the code block become scrollable: ```txt title="Without Word Wrap" A very very very long line of text that may cause the codeblock to overflow and scroll as a result. ``` ````markdown ```txt title="Without Word Wrap" A very very very long line of text that may cause the codeblock to overflow and scroll as a result. ``` ```` To disable scrolling and wrap overflow onto the next line, use the `wordWrap` prop: ```txt title="With Word Wrap" wordWrap A very very very long line of text that may cause the codeblock to overflow and scroll as a result. ``` ````markdown ```txt title="With Word Wrap" wordWrap A very very very long line of text that may cause the codeblock to overflow and scroll as a result. ``` ```` ## Combining props You can combine the `title`, `highlight`, `focus`, `maxLines`, and `wordWrap` props to create a code block with a title, highlighted lines, and a maximum height. ```javascript title="Hello, World!" {2-4} maxLines=5 console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); console.log("Line 6"); console.log("Line 7"); console.log("Line 8"); console.log("Line 9"); console.log("Line 10"); ``` ````markdown maxLines=5 ```javascript title="Hello, World!" {2-4} maxLines=5 console.log("Line 1"); console.log("Line 2"); console.log("Line 3"); console.log("Line 4"); console.log("Line 5"); console.log("Line 6"); console.log("Line 7"); console.log("Line 8"); console.log("Line 9"); console.log("Line 10"); ``` ```` ## Tabbed CodeBlocks The `CodeBlocks` component is used to display multiple code snippets in a tabbed view. It does not take any props. ```javascript title="helloWorld.js" console.log("Hello World"); ``` ```python title="hello_world.py" print('Hello World!') ``` ```java title="HelloWorld.java" class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } ``` ````jsx maxLines=0 ```javascript title="helloWorld.js" console.log("Hello World"); ``` ```python title="hello_world.py" print('Hello World!') ``` ```java title="HelloWorld.java" class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } } ``` ```` # Steps > The Steps component helps you display a set of instructions to the user. The `Steps` component is used when you want to display a set of instructions for the user to follow. ### First Step Initial instructions. ### Second Step More instructions. ### Third Step Final Instructions # Frames > Wrap images in a container with the frame component Sample photo of mountains ### Adding a subtle background In the scenario where you want to draw more attention to your framed images or your content blends with the main background of your documentation, you can use the `background="subtle"` prop to add a subtle background to the frame. ```jsx title="Subtle background" {3} ``` # Tabs > The Tabs component allows you to display related content in a tabbed view. You can add any number of tabs. ☝️ Welcome to the content that you can only see inside the first Tab. ✌️ Here's content that's only inside the second Tab. 💪 Here's content that's only inside the third Tab. # Endpoint Request Snippet > Reference an endpoint request from your API Reference The `EndpointRequestSnippet` component is used to reference an endpoint request from your API Reference. Below is an example of referencing the request for the `POST /snippets` endpoint. ```jsx ``` will be rendered as: ### Reference particular examples If you want to reference a particular example in the request snippet, you can set `example` prop to the name of the example. See the steps below: ### Define named examples The highlighted lines show how to set the example name. ```yaml {12} paths: /pet: put: summary: Update an existing pet operationId: pets_update requestBody: content: application/json: schema: $ref: '#/components/schemas/Pet' examples: ExampleWithMarkley: summary: This is an example of a Pet value: name: Markley id: 44 ``` ```yaml {11} service: auth: true base-path: "" endpoints: update: docs: Update an existing pet method: PUT path: /pet request: Pet examples: - name: ExampleWithMarkley docs: This is an example of a Pet request: name: Markley id: 44 ``` ### Reference the example In the API Definition, the example had a name `ExampleWithMarkley`. You can reference the example directly: ```jsx {3} ``` {/* ### Props Below is a description of all the supported props for the `EndpointRequestSnippet` component. ```fern EndpointRequestSnippetProps: properties: endpoint: type: string docs: The endpoint using `METHOD /path` format. example: type: optional docs: The name of the example to display, defaults to the first example. ``` */} # Endpoint Response Snippet > Reference an endpoint response from your API Reference The `EndpointResponseSnippet` component is used to reference an endpoint response from your API Reference. Below is an example of referencing the response for the `POST /snippets` endpoint. ```jsx ``` will be rendered as ### Reference particular examples If you want to reference a particular example in the response snippet, you can set `example` prop to the name of the example. See the steps below: ### Define named examples The highlighted lines show how to set the example name. ```yaml {13} paths: /pet/{petId}: put: summary: Get a pet operationId: pets_get responses: '200': content: application/json: schema: $ref: '#/components/schemas/Pet' examples: ExampleWithMarkley: summary: This is an example of a Pet value: name: Markley id: 44 ``` ```yaml {11} service: auth: true base-path: "" endpoints: update: docs: Get a pet method: GET path: /pet/{petId} response: Pet examples: - name: ExampleWithMarkley docs: This is an example of a Pet response: body: name: Markley id: 44 ``` ### Reference the example In the API Definition, the example had a name `ExampleWithMarkley`. You can reference the example directly: ```jsx {3} ``` {/* ### Props Below is a description of all the supported props for the `EndpointResponseSnippet` component. ```fern EndpointResponseSnippetProps: properties: endpoint: type: string docs: The endpoint using `METHOD /path` format. example: type: optional docs: The name of the example to display, defaults to the first example. ``` */} # Customize content using frontmatter > Use frontmatter to set a variety of page properties and metadata. You can optionally use frontmatter to set each page's title, full slug override, meta description, a URL to suggest edits to the page, and its OpenGraph image. You can also use frontmatter to disable certain page element like the table of contents and on-page feedback. Frontmatter must be added to the top of a `.md` or `.mdx` file, before the rest of the content. Use sets of three dashes to indicate the beginning and end of your frontmatter, as shown: ```mdx --- title: Customize content using frontmatter subtitle: Set titles, add meta descriptions, and more slug: frontmatter description: Use frontmatter to set the page title, subtitle, slug, meta description, its OpenGraph image, and a URL to suggest edits. --- ``` ## Title **Name**: `title`
**Type**: string
**Default**: The name of the page as specified in `docs.yml` Set the content for the [`` element](https://web.dev/learn/html/document-structure#document_title) for a page. This title is displayed in browser tabs, history, and bookmarks, as well as in search engine results. Having a unique and informative title for each page benefits your site's SEO (Search Engine Optimization). <Tip title="Tip"> For more information, see [Google's guidelines for useful titles](https://developers.google.com/search/docs/appearance/title-link#page-titles). </Tip> If no `title` is provided in the frontmatter of a page, Fern uses the value for that page in `docs.yml`. For example, if a page is defined like this in `docs.yml`: <CodeBlock title="docs.yml"> ```yaml - page: Overview path: ./docs/pages/api-overview.mdx ``` </CodeBlock> Then, if Fern does not find a `title` in that page's frontmatter, `Overview` is used for the default title. ### Site-wide title text You can set a field named `title` in `docs.yml` like this: <CodeBlock title="docs.yml"> ```yaml instances: - url: fern.docs.buildwithfern.com title: Fern | Documentation # <-- set site-wide ``` </CodeBlock> The value you enter for this field is appended to every page's title across your docs site, as ` - TITLE_VALUE`. For example, with the above setting in `docs.yml`, the `Overview` page's title becomes `Overview - Fern | Documentation`. ## Subtitle **Name**: `subtitle`<br /> **Type**: string<br /> **Default**: None Renders as a subtitle on the page. If `description` is not set, `subtitle` is also used as the meta description tag. ## Slug **Name**: `slug`<br /> **Type**: string<br /> **Default**: None The `slug` you set in a page's frontmatter overrides the URL for that page derived from `docs.yml`. This slug begins from the root of your docs site, ignoring the tab or section that the page is under. This allows you to set a custom full slug for any page. As an example, consider this navigation setup in `docs.yml`: <CodeBlock title="docs.yml navigation example"> ```yaml navigation: - tab: overview layout: - section: Support contents: - page: Email Us path: ./pages/emailus.mdx slug: email ``` </CodeBlock> The `slug` set in `docs.yml` affects only the final part of the URL, so the `emailus.mdx` page is available at `/overview/support/email`. In contrast, the `slug` that you set in frontmatter affects the full URL. For example, you can set the frontmatter `slug` to `email`, as shown: <CodeBlock title="frontmatter in emailus.mdx"> ```mdx --- slug: email --- ``` </CodeBlock> The page then becomes available at `/email`. ## Meta description **Name**: `description`<br /> **Type**: string<br /> **Default**: None Set the [meta description](https://web.dev/learn/html/metadata#description) for a page. Like the page title, the meta description is important for SEO. It impacts the text that search engines display about your page in search results snippets. It can also influence search engine indexing and ranking. For more information, see [Google's guidelines for meta descriptions](https://developers.google.com/search/docs/appearance/snippet#meta-descriptions). ## Edit this page **Name**: `edit-this-page-url`<br /> **Type**: string (absolute URL)<br /> **Default**: None Provide the absolute link to the source `.md` or `.mdx` file in GitHub. Fern uses it to add an `Edit this page` link to the page, which users of your documentation can use to suggest corrections or additions. <Frame> <img src="file:3cea72b7-0c7a-413f-a2f3-42ce56817406" alt="Edit this page feature" /> </Frame> ## Meta image **Name**: `image`<br /> **Type**: string (absolute URL)<br /> **Default**: None Configure the `<meta property="og:image">` metadata for a page using an absolute path to an image hosted online. This provides an image to show next to a link to your documentation when the link is shared on social media, using a metadata protocol called [OpenGraph](https://ogp.me/). For more information, see the [web.dev explanation of OpenGraph](https://web.dev/learn/html/metadata#open_graph). ## Table of contents **Name**: `hide-toc`<br /> **Type**: boolean<br /> **Default**: false Controls the conditional rendering of the table of contents feature on the right-side of the page. Set to true to disable this feature. <Frame> <img src="file:670cd72d-3494-4c83-8fa7-afb01a024a94" alt="Table of contents feature" /> </Frame> <Tip> By default, Fern will center the contents of a page when the table of contents is hidden. To control the layout of the page, see the [layout documentation](#layout). </Tip> ## Navigation links **Name**: `hide-nav-links`<br /> **Type**: boolean<br /> **Default**: false Controls the conditional rendering of the navigation links (previous, next) at the bottom of the page. Set to true to disable this feature. <Frame> <img src="file:4a988453-6988-4d64-95ad-1a3bbc8ce815" alt="Navigation links feature" /> </Frame> ## On-page feedback **Name**: `hide-feedback`<br /> **Type**: boolean<br /> **Default**: false Controls the conditional rendering of the on-page feedback form at the bottom of the page. Set to true to disable this feature. <Frame> <img src="file:a10b108c-029d-43c5-91fa-dbf2330ee4db" alt="On-page feedback feature" /> </Frame> ## Page logo **Name**: `logo`<br /> **Type**: object<br /> **Default**: None You can override the site-wide logo for a page by setting a field named `logo` in any page's frontmatter like this: <CodeBlock title="index.mdx logo example"> ```mdx --- logo: light: /path/to/page-logo.png dark: /path/to/page-logo.png --- ``` </CodeBlock> This field specifies the logo for this page. If no logo is set, the site-wide [logo configuration](/learn/docs/getting-started/global-configuration#logo-configuration) is used. ## Layout **Name**: `layout`<br /> **Type**: `overview`, `guide`, `reference`, `page`, or `custom`<br /> **Default**: `guide` Sets the page layout. * `overview`: A spacious, full-width layout without a table of contents. Perfect for landing pages, section overviews, and content that benefits from maximum horizontal space. Navigation sidebar remains visible. * `guide`: The default documentation layout featuring a table of contents on the right side. Ideal for tutorials, how-to guides, and any content that benefits from easy navigation through sections. * `reference`: A full-width layout optimized for an API or SDK reference. Removes the table of contents so you can add another column, such as code examples. Navigation sidebar remains visible. * `page`: A distraction-free, full-screen layout that hides both the table of contents and navigation sidebar. Best for standalone content that benefits from focused reading experiences. * `custom`: A blank canvas layout that removes all default styling constraints. Hides both the table of contents and navigation sidebar, allowing complete control over the page layout. ## SEO metadata Fern supports adding SEO metadata in the frontmatter. | Property | Description | Type | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | | `headline` | When set, the `<title />` tag in the document head will use this value rather than the `title` property. This property changes the title that search engines see when crawling this page, and can be used to address Duplicate Title issues in your SEO report. | string | | `canonical-url` | Overrides the canonical url for this page. Must be a full URL including the protocol (i.e. `https://buildwithfern.com/learn/docs/content/frontmatter`) | string | | `og:site_name` | The name of your website as it should appear when your content is shared. | string | | `og:title` | The title of your page as it should appear when your content is shared. | string | | `og:description` | The description of your page as it should appear when your content is shared. | string | | `og:url` | The URL of your page. | string | | `og:image` | The URL or identifier of the image that will be displayed when your content is shared. | URL or relative path to file | | `og:image:width` | The width of the image in pixels. | number | | `og:image:height` | The height of the image in pixels. | number | | `og:locale` | The locale of the page, typically in the format `language_TERRITORY` (e.g., `en_US`). | string | | `og:logo` | The URL or identifier of the logo image of your website that will be displayed when your content is shared. | URL or relative path to file | | `twitter:title` | The title of your page as it should appear in a tweet. | string | | `twitter:description` | The description of your page as it should appear in a tweet. | string | | `twitter:handle` | The Twitter handle of the page creator or site. | string | | `twitter:image` | The URL or identifier of the image that will be displayed in a tweet. | URL or relative path to file | | `twitter:site` | The name of your website as it should appear in a tweet. | string | | `twitter:url` | The URL of your page. | string | | `twitter:card` | The type of card to be used for sharing on Twitter. | `summary`, `summary_large_image`, `app`, `player` | | `noindex` | If set to `true`, the page will not be indexed by search engines. Defaults to `false`. | boolean | | `nofollow` | If set to `true`, a search engine will not follow any links present on the page. Defaults to `false`. | boolean | # Reusable Snippets > Reusable, custom snippets to keep content in sync. Edit once, update everywhere. Keep your documentation DRY (Don't Repeat Yourself) by defining a reusable snippet once, and then referencing it in multiple places. This way, you only need to update the snippet in one place to keep all references in sync. ## Create a reusable snippet To use reusable snippets, start by creating a new folder in your `fern` project called `snippets`. Inside the `snippets` folder, create a new file for each snippet you want to define. For example: ```bash fern └─ pages └─ my-tutorial.mdx └─ assets └─ snippets ├─ herbs.mdx ├─ peace-lily.mdx └─ trees.mdx ``` In each snippet file, define the content you want to reuse. For example, `peace-lily.mdx` might contain: ```mdx snippets/peace-lily.mdx <Warning> Remember to water your plant at least twice a week. </Warning> ``` ## Use a reusable snippet To use a snippet in your documentation, reference it by its file path (including the `.mdx` extension) in your content. For example, to include the `peace-lily` snippet in your content, use: ```mdx pages/my-tutorial.mdx --- title: Getting started with your peace lily description: Peace lily care tips for beginners --- ## Caring for your new plant Peace lilies are easy to grow and relatively trouble-free. <Markdown src="../snippets/peace-lily.mdx" /> ``` # Keep a Changelog > Record the notable changes to your project Keep a record of how your project has changed by writing changelog entries. The changelog will automatically populate with the files contained within the `changelog` folder. <Frame caption="Keep your users updated as your project evolves" background="subtle"> <img src="file:57618dba-bb22-4264-9b81-26662cc8be24" /> </Frame> ## Configure your Changelog <AccordionGroup> <Accordion title="Top-level Changelog"> Configure a changelog for your project by creating a changelog folder. <CodeBlock title="Configure a Changelog"> ```yaml {4-6} fern/ ├─ fern.config.json ├─ docs.yml ├─ changelog/ ├─ 07-08-24.md └─ 08-21-24.mdx ``` </CodeBlock> Once you've configured your changelog, specify where it should appear within your docs in your `docs.yml`. <CodeBlock title="docs.yml"> ```yaml {8-11} tabs: guides: display-name: Guides icon: light book-open api: display-name: API Reference icon: light code changelog: display-name: Changelog icon: light clock changelog: ./changelog ``` </CodeBlock> [View an example](https://github.com/humanloop/humanloop-docs/blob/30ddedaf6d2779361e8ee1f373f722364e5dd71d/fern/versions/v5.yml#L10-L13) in GitHub of Humanloop's `docs.yml` which powers [their Changelog](https://humanloop.com/docs/changelog). </Accordion> <Accordion title="API-level Changelog"> Configure a changelog at the API-level by creating a changelog folder specific to an API. <CodeBlocks> <CodeBlock title="OpenAPI"> ```yaml {6-8} fern/ ├─ fern.config.json ├─ docs.yml └─ openapi/ ├─ openapi.yml └─ changelog/ ├─ 07-15-24.md └─ 08-23-24.mdx ``` </CodeBlock> <CodeBlock title="Fern Definition"> ```yaml {7-9} fern/ ├─ fern.config.json ├─ docs.yml └─ definition/ ├─ api.yml ├─ imdb.yml └─ changelog/ ├─ 07-15-24.md └─ 08-23-24.mdx ``` </CodeBlock> <CodeBlock title="Multiple APIs"> ```yaml {8-10,14-17} fern/ ├─ fern.config.json ├─ docs.yml └─ apis/ ├─ user-api/ └─ openapi/ ├─ openapi.yml ├─ openapi-overrides.yml └─ changelog ├─ 07-15-24.md └─ 08-23-24.mdx └─ admin-api/ └─ openapi/ ├─ openapi.yml └─ changelog ├─ 06-29-24.md └─ 08-02-24.md └─ 08-15-24.md ``` </CodeBlock> </CodeBlocks> Changelogs contained within your API folder will automatically be displayed at the bottom of your API reference. You do not need to configure your changelog(s) within `docs.yml`. View an example of a changelog per API in [Astronomer's docs](https://www.astronomer.io/docs/api/iam-api-reference/changelog). <Frame caption="A unique changelog per API" background="subtle"> <img src="file:5cdc1858-d056-4aa5-a47e-0c0114b63fb2" /> </Frame> </Accordion> <Accordion title="Section-level Changelog"> Configure a changelog for your project by creating a changelog folder. <CodeBlock title="Configure a Changelog"> ```yaml {4-6} fern/ ├─ fern.config.json ├─ docs.yml ├─ pages/ ├─ changelog/ ├─ 07-08-24.md └─ 08-21-24.mdx ``` </CodeBlock> Once you've configured your changelog, specify where it should appear within your navigation in your `docs.yml`. <CodeBlock title="docs.yml"> ```yaml {9-11} navigation: - section: Introduction contents: - page: Authentication path: ./pages/authentication.mdx - page: Versioning path: ./pages/versioning.mdx - api: API Reference - changelog: ./changelog title: Release Notes slug: api-release-notes ``` </CodeBlock> </Accordion> </AccordionGroup> ## Write a Changelog Entry Create a new changelog entry by writing a Markdown file. You can use `.md` or `.mdx` files. The benefit of using `.mdx` is that you can leverage the built-in [component library](/learn/docs/content/components/overview) within an entry. <CodeBlock title="fern/openapi/changelog/2024-07-31.mdx"> ```mdx ## Summary In the latest release, we've added endpoints to create a new Plant. ### What's new? New endpoints: - `POST /plant` add a new plant to inventory. New object schemas: - `CreatePlantRequest` <Note> Have questions? Reach out to your local botanist. </Note> ``` </CodeBlock> ### Entry date Changelog entries are automatically sorted chronologically by the date specific in the file name. Specify the date of your entry using one of the following formats: * MM-DD-YYYY (e.g., 10-06-2024) * MM-DD-YY (e.g., 10-06-24) * YYYY-MM-DD (e.g., 2024-04-21) ### Linking to an Entry Each changelog entry has a unique URL you can direct users to. For example, `https://humanloop.com/docs/v5/changelog/2024/8/16` # Generate your API Reference > Use Fern Docs to generate your API Reference documentation from your API definition, using your choice of either OpenAPI or Fern Definition. A key benefit of using Fern Docs is that once you've defined your API, you get your API Reference documentation with just one line. Add `- api: API Reference` to your navigation in `docs.yml` and Fern takes care of the rest! You'll see your endpoints, types, and cURL snippets automatically populated from your [OpenAPI Specification](/learn/api-definition/openapi/overview) or [Fern Definition](/learn/api-definition/fern/overview). Example: ```yml docs.yml navigation: - api: API Reference ``` ### API Reference configuration options | Property | Value | | ---------------- | ------------------------------------------------------------------------------------------------------ | | `api` (required) | Title of the API Reference Section | | `api-name` | Name of the API we are referencing, if there are [multiple APIs](#include-more-than-one-api-reference) | | `audiences` | List of [audiences](/learn/api-definition/fern/audiences) to filter the API Reference for | | `display-errors` | Displays error schemas in the API References | | `snippets` | Enable [generated SDK code snippets](/learn/cli-api/api-reference/snippets/get) in your API Reference | | `summary` | Relative path to the Markdown file; the summary is displayed at the top of the API section | | `layout` | Customize the order that your API endpoints are displayed in the docs site | | `icon` | Icon to display next to the API section in the navigation | | `slug` | Customize the slug for the API section (by default, the slug is generated from the API title) | | `skip-slug` | When `true`, skips the slug generation for the API section | | `alphabetized` | When `true`, organizes all sections and endpoints in alphabetically order | | `flattened` | Display all endpoints at the top level (hides the API Reference Section's title) | | `paginated` | Display all endpoints on separate pages (by default, endpoints are displayed on one single, long page) | More on customizing your API Reference [here](/learn/docs/api-references/customize-api-reference-layout). ### Include more than one API Reference To include multiple, distinct API definitions in your documentation, you can indicate which to include using the `api-name` property. The `api-name` corresponds to the name of the folder where your API definition is housed. ```yaml title="docs.yml" navigation: - api: Plant Store api-name: plant-api - api: Garden api-name: garden-api ``` # Display SDK snippets > Enable SDK code examples in TypeScript, Python, Go, and more from the request and response examples documented in your API definition. Once enabled, Fern Docs will automatically populate the snippets within your API Reference. If you use Fern's SDK Generator, you can automatically show SDK code snippets in your API Reference. SDK languages appear in a drop-down. By default, cURL snippets will be displayed to users. <Frame> ![SDK code snippet selector](https://fern-image-hosting.s3.amazonaws.com/sdk-code-snippets.png) </Frame> ## Configuring SDK Snippets To configure SDK snippets, you'll need to name your SDKs in `generators.yml` and then reference that name in `docs.yml`. In the following example, We'll use `your-organization` as the package name because it is a common practice. For example, Stripe calls their npm package `stripe` and Twilio calls their PyPI package `twilio`. ### Add examples to your API definition In order to generate code snippets, Fern needs to read request examples from your API definition. If you're using a Fern Definition, you can follow [these instructions](/learn/api-definition/fern/examples). If you're using an OpenAPI Specification, you can follow [these instructions](https://swagger.io/docs/specification/adding-examples/). ### Define a package name for your SDK(s) <CodeBlock title="generators.yml"> ```yaml groups: production: generators: - name: fernapi/fern-python-sdk version: 2.8.0 output: location: pypi token: ${PYPI_TOKEN} package-name: your-package-name # <--- add this field ... - name: fernapi/fern-typescript-node-sdk version: 0.20.9 output: location: npm token: ${NPM_TOKEN} package-name: your-package-name # <--- add this field - name: fernapi/fern-ruby-sdk version: 0.6.3 output: location: rubygems token: ${RUBYGEMS_TOKEN} package-name: your-package-name # <--- add this field - name: fernapi/fern-go-sdk version: 0.22.0 github: repository: your-organization/your-repository # <--- add this field ... ``` </CodeBlock> <Callout intent="info"> SDK snippets automatically populated in your Fern Docs is a paid feature included in the [SDK Starter plan](https://buildwithfern.com/pricing). </Callout> ### Add the package name to your docs configuration Add the package name for the corresponding SDK to your `docs.yml` file. For Go, use the exact URL where the SDK repository is located. <CodeBlock title="docs.yml"> ```yaml navigation: - api: API Reference snippets: python: your-package-name # <--- needs to match the naming in generators.yml typescript: your-package-name go: https://github.com/your-organization/your-repository # <--- needs the https://github.com/ prefix ``` </CodeBlock> ### Trigger generation As the final step, trigger your docs generation by running `fern generate --docs` locally or in CI/CD (i.e., GitHub Actions). The SDK snippets will now appear via a drop-down! ### Set default snippet To set the default snippet shown in the API Reference drop-down, specify the `default-language` in your `docs.yml`. <CodeBlock title="docs.yml"> ```yaml {1} default-language: typescript navigation: - api: API Reference snippets: python: your-package-name typescript: your-package-name ``` </CodeBlock> ## Language support TypeScript, Python, Go, and Ruby are the supported SDK code snippet languages. Our development work is driven by customer requests, so please request support for another language by [opening an issue](https://github.com/fern-api/fern/issues/new/choose). ## Access via API If you'd like to bring SDK snippets into your own documentation, you can use the [Snippets API](/learn/cli-api/api-reference/snippets/get). API access requires a [SDK Business plan](https://buildwithfern.com/pricing) or above. Merge.dev is an example of a Fern customer that uses the Snippets API to bring Python code samples [into their API Reference](https://docs.merge.dev/hris/employees/#employees_list). ## Endpoint request and response snippets Looking for information on generating API endpoint request and response snippets? See our documentation on [Endpoint Request Snippets](/learn/docs/content/components/request-snippet) and [Endpoint Response Snippets](/learn/docs/content/components/response-snippet). # API Playground > Reduce "time to 200" by allowing users to make real calls to your API from right within the API Reference. <Tip> This feature is available on the Basic plan and above. [Contact us](https://buildwithfern.com/contact) to get set up. </Tip> Fern's API Playground allows users to make authenticated requests to your API without ever leaving your documentation. ### Auto-populate with examples Fern will automatically populate the fields of the endpoint with the values set in your API specification. <div> <iframe src="https://www.loom.com/embed/a48d921459b54dde9652c3fcc85ebc54?sid=2c0b4f4d-7e24-4fc5-a617-8d933195bfec?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen /> </div> ### Authenticated sessions Once a user sets their authentication credentials once, their credentials persist throughout their entire exploration. <div> <iframe src="https://www.loom.com/embed/7de9948ae878448094b5e92da5effd41?sid=702889b7-aa3d-4669-994e-83c196d7bc3e?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen /> </div> <Info> Authentication credentials are only stored client-side using cookies. No sensitive user information is collected or stored. </Info> ### Multiple environments Allow users to test their calls in a sandbox environment or select the environment relevant to them. Users can switch between multiple environments. Once they've selected their environment, it persists throughout their entire exploration. <div> <iframe src="https://www.loom.com/embed/cb642161678e41cabcb677b900006f40?sid=5e45243c-3ba1-45cf-860b-72eee1970fc5?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen /> </div> ### WebSocket Playground For APIs that support WebSocket connections, the API Playground includes a **WebSocket**-specific Playground. The WebSocket Playground also allows users to establish a connection with the API, and send/receive messages in real-time. <div> <iframe src="https://www.loom.com/embed/be4da30404794e9983c4fe639f78d4c8?sid=73b7aeda-98fa-4531-87ed-1e5909500fe2?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen /> </div> # Auto-populate API keys > Make integrating with your API frictionless by adding your login flow to the API Playground. <Tip> This feature is available on the Enterprise plan. [Contact us](https://buildwithfern.com/contact) to learn more. </Tip> Fern can integrate with your authentication flow, allowing users to login and have their API key automatically populated with the click of a button. <div> <iframe src="https://www.loom.com/embed/790eb5849f1c4622aae09527908fdc7a?sid=d77062f8-35c3-41ab-8669-4c28b62e233b?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen /> </div> With this feature, you can **create new users of your API** directly from within your documentation. # Advanced configuration > Configure advanced settings like the server URLs reachable by the API playground and authentication with OAuth. If you subscribe to Fern's Pro or Enterprise Plans, you can customize your API Playground settings to suit your customers needs. All configuration settings are defined in the `docs.yml` file, under API Reference navigation configuration, in a `Playground` object. ### Filtering Server Urls If you have multiple environments for your API, you can filter the server URLs that are displayed in the API Playground. To filter server URLs, add the `environments` property to the `PlaygroundSettings` object in your `docs.yml`, like so: ```yaml navigation: api: playground: environments: - Staging-A - Staging-B ``` ### Enabling OAuth 2.0 Authorization Injection If you have defined an endpoint that executes OAuth 2.0 Client Credentials Authorization in your API definition, you can enable OAuth 2.0 Authorization Injection in your API Playground. More information on enabling OAuth 2.0 Authorization Injection can be found [here](/learn/api-definition/fern/authentication#oauth-client-credentials). To enable OAuth 2.0 Authorization Injection, simply add the `oauth` feature flag to the `PlaygroundSettings` object in your `docs.yml`, like so: ```yaml navigation: api: playground: oauth: true ``` # Endpoint errors configuration > Enable errors to show up on the endpoint pages of your documentation, from the error names, codes, and objects returned configured in your API definition. This configuration enables errors to show up on the endpoint pages of your documentation. The error names, codes, and objects returned are configured in your API definition. ## Configuration <CodeBlock title="docs.yml"> ```yaml navigation: - api: API Reference display-errors: true #<--- add this line ``` </CodeBlock> ## Example <Frame> ![Endpoint errors](https://fern-image-hosting.s3.amazonaws.com/fern/errors.png) </Frame> By clicking on an error, you can see the error name, code, and object returned. The response also updates to show the error object. <Frame> ![Endpoint errors when expanded](https://fern-image-hosting.s3.amazonaws.com/fern/errors-expanded.png) </Frame> # Audiences > Use audiences to filter the endpoints, schemas, and properties that are displayed in your API Reference. Audiences are a useful tool for segmenting your API for different consumers. Common examples of audiences include `public` and `beta`. You can configure audiences in both [the OpenAPI Specification](/learn/api-definition/openapi/audiences) as well as [the Fern Definition](/learn/api-definition/fern/audiences). Once you've added audiences to your API Specification, you can filter to that audience by adding the `audience` property to the `api` object in your `docs.yml` navigation. <CodeBlocks> ```yaml title="docs.yml" {3-4} navigation: - api: API Reference audiences: - public ``` </CodeBlocks> Here's [an example from Schematic](https://github.com/SchematicHQ/schematic-fern-config/blob/e19f5ea69a343727ed018e79127bf4fd20ad0f7b/fern/docs.yml#L128-L129) in production. # Customize API Reference layout > Customize your API Reference's naming, ordering, and structure. When you [include an API in your `docs.yml` file](/learn/docs/api-references/generate-api-ref), you can customize how the endpoints and sections are displayed in the sidebar navigation. By default, the reference will generate a navigation hierarchy based on the structure of the API spec, but several customizations can be configured. <Note title="API Sections"> If you are using an OpenAPI Specification, sections are created based on the `tags` property, converted to `lowerCamelCase` convention (e.g., createUser). If you are using a Fern Definition, sections are created based on the [`service`](/learn/api-definition/fern/endpoints#service-definition) file names. </Note> If you would like to only display a subset of endpoints, read more about the Audiences property for [OpenAPI Specifications](/learn/api-definition/openapi/audiences) or [Fern Definitions](/learn/api-definition/fern/audiences). ## Ordering the API Reference ### Alphabetizing endpoints and sections To sort all sections and endpoints alphabetically, unless explicitly ordered in `layout`, set `alphabetized` to `true`. ```yaml title="docs.yml" navigation: - api: API Reference alphabetized: true ``` ### Ordering top-level sections The `layout` option allows you to specify the order of sub-packages, sections, endpoints, and pages at the top level of your API Reference. <Tabs> <Tab title="OpenAPI Specification"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - POST /user - user - store - plant ``` </Tab> <Tab title="Fern Definition"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - user.create - user - store - plant ``` </Tab> </Tabs> <Frame> <img src="file:c270c637-54e0-4a4e-9d7f-fddbf668990a" alt="Ordered API Reference" /> </Frame> ### Ordering section contents Adding a `:` after the section name allows you to specify the order of its nested sub-packages and endpoints. <Note title="Referencing Endpoints"> To reference an endpoint, you can use either: * `METHOD /path/name` (best for OpenAPI Specification) * `serviceName.endpointName` (best for Fern Definition) </Note> <Tabs> <Tab title="OpenAPI Specification"> You can reference an endpoint using the format `METHOD /path`. ```yaml title="docs.yml" navigation: - api: API Reference layout: - user: - POST /user - PUT /user/{username} - DELETE /user/{username} ``` </Tab> <Tab title="Fern Definition"> You can reference an endpoint using the format `serviceName.endpointName`. ```yaml title="docs.yml" navigation: - api: API Reference layout: - user: - user.create - user.update - user.delete ``` </Tab> </Tabs> <Frame> <img src="file:6e49e1b1-42e5-4694-83f0-d2755ca5a6bc" alt="Content ordered in the API Reference" /> </Frame> ## Customizing the API Reference ### Flattening sections To remove the API Reference title and display the section contents, set `flattened` to `true`. ```yaml title="docs.yml" navigation: - api: API Reference flattened: true ``` <Frame> <img src="file:37fb0ede-af02-46cd-8531-d4aaeaf2dd99" alt="Flattened API Reference" /> </Frame> ### Styling endpoints To customize the display of an endpoint, you can expand the endpoint description to include a `title` and `slug`, or set the endpoint as `hidden`. <Tabs> <Tab title="OpenAPI Specification"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - user: - endpoint: POST /user title: Create a User slug: user-creation - DELETE /user/{username} ``` </Tab> <Tab title="Fern Definition"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - user: - endpoint: user.create title: Create a User slug: user-creation - user.delete ``` </Tab> </Tabs> <Frame> <img src="file:f1686a0b-5376-4dbf-ac09-c274cbf5fc41" alt="Setting an endpoint title" /> </Frame> ### Adding custom sections You can add arbitrary folders in the sidebar by adding a `section` to your API Reference layout. A section can comprise entire groups of endpoints, individual endpoints, or even just Markdown pages. Sections can be customized by adding properties like a `icon`, `summary`, `slug` (or `skip-slug`), and `contents`. <Tabs> <Tab title="OpenAPI Specification"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - section: My Section icon: flower contents: - PUT /user/{username} - plant ``` </Tab> <Tab title="Fern Definition"> ```yaml title="docs.yml" navigation: - api: API Reference layout: - section: My Section icon: flower contents: - user.update - plant ``` </Tab> </Tabs> <Frame> <img src="file:34a92b3d-17e3-49eb-8cdd-9ab640577c58" alt="Custom section in the API Reference" /> </Frame> ### Adding a section overview The `summary` property allows you to add an `.md` or `.mdx` page as an overview of the API Reference or a section. ```yaml title="docs.yml" navigation: - api: API Reference summary: pages/api-overview.mdx layout: - user: summary: pages/user-overview.mdx ``` <Frame> <img src="file:1c6f748b-69c6-45fb-b371-09ab80592266" alt="API Reference with a summary page" /> </Frame> ### Adding pages and links You can add regular pages and external links within your API Reference. ```yaml title="docs.yml" navigation: - api: API Reference layout: - user: contents: - page: User Guide path: ./docs/pages/user-guide.mdx - link: Link Title href: http://google.com ``` ### Disable long-scrolling By default, the API Reference renders all endpoints on a single page (long-scrolling). To create separate pages for each endpoint, set `paginated: true`. ```yaml title="docs.yml" navigation: - api: API Reference paginated: true ``` # Write Markdown content in your API Reference > Add Markdown content to your API Reference including summary pages and content between endpoints. Fern Docs allows you to write Markdown content in your API Reference documentation. This feature is useful for providing additional context, examples, or explanations for your API endpoints. There are a few ways to accomplish this: ## In OpenAPI If you're using OpenAPI to define your API, you can include Markdown content in your OpenAPI Specification. For example, you can include a [callout](/learn/docs/content/components/callouts#note-callouts) in the `description` field of an endpoint: ```yaml title="api/openapi.yml" paths: /pets: get: summary: List all pets description: | Get a list of all pets in the system. <Note>This endpoint requires authentication.</Note> ``` ## In Fern Definition If you're using Fern's simpler API definition format, you can include Markdown content in your API definition. For example, you can include a [callout](/learn/docs/content/components/callouts#note-callouts) in the `docs` field of an endpoint: ```yaml title="api/service.yml" service: endpoints: get: path: /pets docs: | Get a list of all pets in the system. <Note>This endpoint requires authentication.</Note> ``` ## Adding a summary page You can also create a Markdown page that provides an overview of your API Reference. This page can include general information about your API, such as authentication requirements, rate limits, or other important details. To add a summary page, create a Markdown file in your `fern/` folder and link to it in your `docs.yml` file: ```yaml title="docs.yml" navigation: - api: API Reference summary: ./pages/api-summary.mdx ``` By including the `summary` field, the `API Reference` section title will link to the `api-summary.mdx` page. ## Adding Markdown content between endpoints In addition to adding Markdown content to individual endpoints, you can also include Markdown content between endpoints in your API Reference. This content can provide context or explanations that apply to multiple endpoints. This feature requires you to use the `layout` field in your `docs.yml` file, which is described in the [Customize your API Reference](/learn/docs/api-references/customize-api-reference-layout) guide. To add Markdown content between endpoints, create a Markdown file in your `fern/` folder and link to it in your `docs.yml` file: ```yaml title="docs.yml" navigation: - api: API Reference layout: - pet: - page: Pet CRUD path: ./pages/pet-crud.mdx - addPet - updatePet - deletePet - page: Pet Search path: ./pages/pet-search.mdx - findPets - findPetsByStatus - findPetsByTags - findPetsByType - findPetsByBreed ``` # Integrations > Integrate with third party platforms for analytics, support, etc. <CardGroup cols={2}> <Card title="PostHog" href="/learn/docs/integrations/analytics/posthog" horizontal icon={<img src="https://cdn.brandfetch.io/id2veLU_gI/idG9S94wXO.svg" />} iconSize={12} /> <Card title="Segment" href="/learn/docs/integrations/analytics/segment" horizontal icon={ <img src="https://cdn.brandfetch.io/idiousYjQz/theme/dark/symbol.svg?k=id64Mup7ac&t=1717151164256?t=1717151164256" /> } iconSize={12} /> <Card title="FullStory" href="/learn/docs/integrations/analytics/fullstory" horizontal icon={<img src="https://cdn.brandfetch.io/idRtIBDum6/w/400/h/400/theme/dark/icon.jpeg" />} iconSize={12} /> <Card title="Intercom" href="/learn/docs/integrations/support/intercom" horizontal icon={<img src="https://cdn.brandfetch.io/idYJNDWF1m/theme/dark/symbol.svg" />} iconSize={12} /> <Card title="Postman" href="/learn/docs/integrations/postman" horizontal icon={<img src="https://seeklogo.com/images/P/postman-logo-0087CA0D15-seeklogo.com.png" />} iconSize={12} /> </CardGroup> ## Enabling Analytics You can define your analytics configuration in `docs.yml`. You only need to include entries for the platforms you want to connect. ```yaml docs.yml analytics: posthog: api-key: ${POSTOHG_API_KEY} endpoint: https://self.hosted.posthog.com/ segment: write-key: ${SEGMENT_WRITE_KEY} intercom: app-id: ${INTERCOM_APP_ID} endpoint: https://intercom.custom-instance.com/ fullstory: org-id: ${FULLSTORY_ORG_ID} ``` ### Environment Variables If your docs configuration is public, then we do not advise adding secret values directly to `docs.yml`. Instead, you can reference an environment variable by using the syntax `${VARIABLE_NAME}`. <Note> If you are using GitHub Workflows to trigger docs generation, you must make sure that the environment variables are available during the workflow run. ```yaml {4} - name: Publish Docs env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} POSTHOG_API_KEY: ${{ secrets.POSTHOG_PROJECT_API_KEY }} run: | npm install -g fern-api fern generate --docs ``` </Note> ## Postman <Info> The Postman integration is not configured in `docs.yml`. Check out this [page](/learn/docs/integrations/postman) to learn more. </Info> # Google Analytics > Add Google Analytics to your Docs with Fern. Fern supports integrating with both [Google Analytics 4](https://developers.google.com/analytics) and [Google Tag Manager](https://tagmanager.google.com/). <Tip> This feature is available on the Fern Basic plan and above. Reach out to [support@buildwithfern.com](mailto:support@buildwithfern.com) to set up your Google Analytics. </Tip> # PostHog > Learn how to integrate PostHog with Fern Docs! ## Add Posthog to your Docs To integrate PostHog, you'll need a Posthog API Key, and optionally, you can configure a custom Posthog host. ### Integrate Posthog You can find your PostHog API Key under your [project settings.](https://us.posthog.com/settings/project) Then, in your `docs.yml` file, add your Posthog configuration: <CodeBlock title="docs.yml"> ```yaml analytics: posthog: api-key: ${POSTHOG_API_KEY} # reads your api key from environment variables # Optional endpoint: ${POSTHOG_API_HOST} # e.g. https://analytics.example.com or https://eu.i.posthog.com ``` </CodeBlock> # Fullstory > Learn how to integrate Fern Docs with Fullstory to track user behavior and analytics. ## Add Fullstory to your Docs To add Fullstory to your Docs, you need to add your Fullstory `orgId` to your `docs.yml` file. ### Get your Fullstory Org ID When you login to your Fullstory account, your Org ID can be found in the URL of your browser. ``` https://app.fullstory.com/ui/<ORG_ID>/home ``` Additionally, you can find your Org ID in [Settings > Data Capture and Privacy > Fullstory Setup](https://help.fullstory.com/hc/en-us/articles/360047075853-How-do-I-find-my-Fullstory-Org-Id#:~:text=You%20can%20find%20your%20Org,embedded%20in%20the%20Fullstory%20snippet.\&text=More%20information%20about%20installation%20and,the%20URL%20of%20your%20browser.) inside the Fullstory snippet: 1. Log in to your Fullstory account. 2. Find **Settings** in a dropdown by clicking your organization's name or logo in the top left. 3. Navigate the sidebar to the Data Capture and Privacy section. Click on "Fullstory Setup", located under the heading. 4. Retrieve the Org Id from the snippet, where it is assigned to `window['_fs_org']`. It will appear as `window['_fs_org'] = '<ORG_ID>'`. You can find visual instructions in [Fullstory's guide](https://help.fullstory.com/hc/en-us/articles/360047075853-How-do-I-find-my-Fullstory-Org-Id#:~:text=You%20can%20find%20your%20Org,embedded%20in%20the%20Fullstory%20snippet.\&text=More%20information%20about%20installation%20and,the%20URL%20of%20your%20browser.) about this topic. ### Integrate Fullstory with your Docs In your `docs.yml` file, add your Fullstory Org ID: <CodeBlock title="docs.yml"> ```yaml analytics: fullstory: org-id: ${FULLSTORY_ORG_ID} # reads your org id from environment variables ``` </CodeBlock> # Segment > Learn how to integrate Fern Docs with Segment to track user behavior and analytics. <Note> Currently we only support Segment via a custom writeKey in the docs.yml file, however you can add other providers to your docs page through [Custom Javascript](/learn/docs/building-your-docs/custom-css-global-js). We are also working on adding support for additional analytics tools via the docs.yml file analytics block! </Note> ## Add Segment to your Docs To add Segment to your Docs, you need to add the Segment writeKey to your `docs.yml` file. ### Get your Segment writeKey 1. Log in to your Segment account. 2. Go to the workspace where you want to add the Docs integration. 3. Click on the Source you want to track.' 4. Click on the `Settings` tab. 5. Copy the `Write Key` from the `API Keys` section. ### Add the Segment writeKey to your Docs In your `docs.yml` file, add the Segment writeKey: <CodeBlock title="docs.yml"> ```yaml analytics: segment: write-key: ${SEGMENT_WRITE_KEY} # scans environment variable ``` </CodeBlock> # Intercom > Learn how to integrate Intercom with Fern Docs! ## Add Intercom to your Docs To add Intercom to your Docs, you need to your Intercom `app_id`, also known as the Intercom workspace ID. This is a unique code assigned to your app when you create it in Intercom. Additionally, you may configure a custom Intercom endpoint. ### Get your Intercom App Id Your app ID is available under [Settings > Workspace > General](https://app.intercom.com/a/apps/_/settings/workspace/general) in the "Workspace name & time zone" tab. See [Intercom's FAQ](https://www.intercom.com/help/en/articles/8771110-getting-started-faqs#h_c12f89cf9d) for visual instructions. ### Integrate Intercom with your Docs In your `docs.yml` file, add your Intercom config: <CodeBlock title="docs.yml"> ```yaml analytics: intercom: app-id: ${INTERCOM_APP_ID} # reads your org id from environment variables # Optional endpoint: ${INTERCOM_ENDPOINT} # e.g. https://intercom.custom-instance.com ``` </CodeBlock> # Postman Integeration > Generate a postman collection full of example requests and responses ## Showcase <CardGroup cols={2}> <Card title="Primer" href="https://www.postman.com/primerio/workspace/primer-docs/overview" horizontal icon={<img src="https://cdn.prod.website-files.com/5e9dc792e1210c5325f7ebbc/64b039144f484892355032dd_62146168.png" />} iconSize={12} /> <Card title="MirrorWOrld" href="https://developer.mirrorworld.fun/" horizontal icon={<img src="https://cdn.brandfetch.io/idLEJUb6Vb/w/400/h/400/theme/dark/icon.jpeg" />} iconSize={12} /> </CardGroup> ## Getting started The configuration for the postman generator lives in your fern folder, in a file called [`generators.yml`](/learn/api-definition/introduction/what-is-the-fern-folder#generatorsyml). ### **Step 1**: Configure your `generators.yml` Start by running the following command: ```sh fern add fern-postman --group postman ``` Once the command completes, you will see the following configuration added: ```yaml title="generators.yml" {2-8} groups: postman: generators: - name: fernapi/fern-postman version: 0.0.45 output: location: local-file-system path: ../postman ``` ### **Step 2**: Generate a `collection.json` Start by running the following command ```sh fern generate --group postman ``` This will trigger postman collection on Fern's cloud. Once complete, you'll see a `collection.json`: ```bash {4-5} fern/ ├─ fern.config.json ├─ generators.yml postman ├─ collection.json ``` ## Publishing If you'd like Fern to publish the collection directly to Postman instead, you can modify your `generators.yml` configuration in the following way: ```yaml title="generators.yml" {6-9} generators: postman: generators: - name: fernapi/fern-postman version: 0.4.0 output: location: postman api-key: ${POSTMAN_API_KEY} workspace-id: 07e228e5-3f91-4223-8e27-bbfe4a81a601 config: collection-name: My collection name ``` If you'd like to publish to a particular collection, just specify the collection ID. ```yaml title="generators.yml" {10} generators: postman: generators: - name: fernapi/fern-postman version: 0.4.0 output: location: postman api-key: ${POSTMAN_API_KEY} workspace-id: 07e228e5-3f91-4223-8e27-bbfe4a81a601 collection-id: 21510182-14b07230-46e2-431e-8153-d5c7d217b214 config: collection-name: My collection name ``` # Hosting with GitLab To host your Fern docs using GitLab, you will need to [add a Fern token to your repository variables](/learn/docs/developer-tools/gitlab#add-a-token-to-gitlab). <Accordion title="GitLab CI/CD configuration"> The following GitLab CI/CD workflow will generate a preview link of your docs on merge request and publish your docs when updates are made to `main`. To add this to your GitLab Fern project, create a `.gitlab-ci.yml` file in the root of your repository. ```yaml .gitlab-ci.yml stages: - check - preview_docs - publish_docs - publish_sdks before_script: - apt-get update -y - apt-get install -y curl - curl -sL https://deb.nodesource.com/setup_current.x | bash - - apt-get install -y nodejs - npm install -g fern-api check: stage: check rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_BRANCH == "main"' script: - echo "Checking API is valid" - fern check preview_docs: stage: preview_docs rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' script: - echo "Running fern generate --docs --preview..." - | OUTPUT=$(fern generate --docs --preview) || true echo "$OUTPUT" DEMO_URL=$(echo "$OUTPUT" | grep -oP -m1 '(https://[^\s]+-preview-[^\s]+)(?: )') echo "Preview URL: $DEMO_URL" - | if [ -z "$DEMO_URL" ]; then echo "No DEMO_URL found" exit 1 fi curl --location --request POST \ --header "PRIVATE-TOKEN: $REPO_TOKEN" \ --header "Content-Type: application/json" \ --url "https://gitlab.com/api/v4/projects/$CI_MERGE_REQUEST_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" \ --data-raw "{ \"body\": \"🌿 Preview your docs [here]($DEMO_URL)\" }" publish_docs: stage: publish_docs rules: - if: '$CI_COMMIT_BRANCH == "main"' script: - echo "Publishing Docs" - fern generate --docs publish_sdks: stage: publish_sdks rules: - if: '$CI_PIPELINE_SOURCE == "web"' script: - echo "Publishing SDKs" - fern generate --group ts-sdk --version $VERSION --log-level debug ``` </Accordion> ## Add a token to GitLab <Steps> ### Log in Log into [GitLab](https://gitlab.com/users/sign_in). ### Navigate to CI/CD in settings Click on the **Settings** tab in your repository. Then, click on **CI/CD**. ### Add variable Scroll to the **Variables** section and select **Expand** > **Add variable**. Add your key and value, *deselect* **Protect variable**, and then click **Save changes**. </Steps> ## Preview docs with GitLab <Steps> ### Contact us To get set up with a GitLab pipeline to preview your docs automatically, reach out via your dedicated Slack channel or [email](mailto:support@buildwithfern.com). ### Log in Log into [GitLab](https://gitlab.com/users/sign_in). ### Navigate to Access Tokens Click on the **Settings** tab in your repository. Then, click on **Access Tokens**. ### Generate project access token Click on **Add new token**. You then need to: * Add your token name * Select an expiry date (note: once the token expires, you will need to generate a new one) * Set role to **Reporter** * Set scope to **api** When finished, click **Create project access token**. <Note title="Save your token"> Be sure to save the generated token - it won't be displayed after you leave the page. </Note> ### Add token to repository variables You can do this using [the steps listed above](/learn/docs/developer-tools/gitlab#add-a-token-to-gitlab). </Steps> # Using Vale ## What is Vale? [Vale](https://vale.sh/) is an open-source tool for linting content from a variety of different file types, including Markdown. ## Using Vale with MDX Once installed, you can use Vale with MDX files by adding a `.vale.ini` file to your Fern repo. <Tip> Be sure to add ```txt [formats] mdx = md ``` to your `.vale.ini` configuration so the MDX format is recognized. </Tip> To use Vale's HTML-style comments (`<!-- comment -->`) in an MDX file, wrap within an MDX-styled comment (`{/* comment */}`). For example: * **disable Vale**: `{/* <!-- vale off --> */}` * **enable Vale**: `{/* <!-- vale on --> */}` ```markdown title='Example Vale Usage' Vale will check this text. {/* <!-- vale off --> */} Vale won't check this text. {/* <!-- vale on --> */} Vale will start checking this text again. ```