Skip to content
FeedbackDashboard

Migrate from Fern

Migrate your API documentation from Fern Docs to the Stainless Docs Platform, including custom content, React components, and API reference.

Fern is a documentation platform that generates API docs from OpenAPI specifications alongside custom content.

This guide walks you through migrating your existing Fern documentation to Stainless.

Before starting, make sure you have:

If you already have a Stainless project, skip to Create your docs site.

To create a new Stainless project, you need an OpenAPI spec. Export your spec from Fern by running this command in your Fern project directory:

Terminal window
fern export openapi.yml

Then create your Stainless project:

  1. Log in to the Stainless dashboard
  2. Click New project
  3. Upload your exported openapi.yml file as the spec

To create a docs site for your Stainless project:

  1. In the Stainless dashboard, select your project
  2. Go to the API Docs tab
  3. Click Get started

Stainless creates a GitHub repository for your docs site and deploys it to a staging domain. For detailed setup instructions, see the Docs Platform quickstart.

To migrate your documentation content:

  1. Locate your Fern content: Find your .mdx and .md files in fern/docs/pages/
  2. Copy to Stainless: Copy these files into your Stainless site’s src/content/docs/ directory
  3. Update frontmatter: Replace Fern frontmatter with Stainless frontmatter

Fern frontmatter:

---
title: How to integrate
description: Learn how to integrate your API documentation
subtitle: Customize content using frontmatter
slug: how-to-integrate
keywords: integration, sdk generation, api, mcp servers, documentation
og:site_name: Your Company Inc.
og:title: SEO Metadata Title
---

Stainless frontmatter:

---
title: How to integrate
description: Learn how to integrate your API documentation
---

The title and description fields work the same way in both platforms.

If you need custom SEO metadata (keywords, Open Graph tags, etc.), you can optionally add a head property:

---
title: How to integrate
description: Learn how to integrate your API documentation
head:
- tag: meta
attrs:
name: keywords
content: integration, sdk generation, api, mcp servers, documentation
- tag: meta
attrs:
property: og:site_name
content: Your Company Inc.
- tag: meta
attrs:
property: og:title
content: SEO Metadata Title
---

Most pages only need title and description. The description field is used for SEO and appears in navigation previews.

Fern’s subtitle field has no direct equivalent in Stainless. Instead, add subtitle content directly in your page body after the frontmatter.

Fern’s slug field is supported but not recommended. In Stainless, file paths determine URLs, so src/content/docs/guides/quickstart.mdx becomes /docs/guides/quickstart/.

For more information about content organization, see Project structure.

Fern and Stainless use different component libraries. Replace Fern components with Stainless equivalents.

Fern provides multiple callout components (<Info>, <Warning>, <Note>, <Tip>, <Success>, <Error>). Stainless uses a single <Callout> component with a variant prop.

Fern:

<Info>This draws attention to important information.</Info>
<Warning>This raises a warning to watch out for.</Warning>
<Note>This highlights additional context.</Note>
<Tip>This suggests a helpful tip.</Tip>

Stainless:

import { Callout } from '@stainless-api/docs/components';
<Callout variant="note">
This draws attention to important information.
</Callout>
<Callout variant="warning">
This raises a warning to watch out for.
</Callout>
<Callout variant="note">
This highlights additional context.
</Callout>
<Callout variant="tip">
This suggests a helpful tip.
</Callout>

Both Fern and Stainless use standard markdown code fences with syntax highlighting.

Fern:

```ts title="example.ts"
const client = new Client();
```

Stainless:

```ts title="example.ts"
const client = new Client();
```

Code block syntax is largely compatible between the two platforms, so most code examples migrate without changes. Stainless code blocks do not support focus, startLine, or maxLines attributes.

wordWrap becomes wrap in Stainless.

For tabbed content, Fern uses <Tabs> with <Tab> children. Stainless uses <Tabs> with <TabItem> children from @astrojs/starlight/components;

Fern:

<Tabs>
<Tab title="Web">
Content for Web tab.
</Tab>
<Tab title="Mobile">
Content for Mobile tab.
</Tab>
</Tabs>

Stainless:

import { Tabs, TabItem } from "@astrojs/starlight/components";
<Tabs>
<TabItem label="Web">
Content for Web tab.
</TabItem>
<TabItem label="Mobile">
Content for Mobile tab.
</TabItem>
</Tabs>

Note that Fern uses title while Stainless uses label for tab headers.

For code examples in multiple languages, Fern uses a <CodeBlocks> wrapper component. Stainless uses the standard <Tabs> component with code fences inside.

Fern:

<CodeBlocks>
```typescript title="TypeScript"
const client = new Client();
```
```python title="Python"
client = Client()
```
</CodeBlocks>

Stainless:

import { Tabs, TabItem } from "@astrojs/starlight/components";
<Tabs>
<TabItem label="TypeScript">
```typescript
const client = new Client();
```
</TabItem>
<TabItem label="Python">
```python
client = Client()
```
</TabItem>
</Tabs>

To migrate custom React components from Fern:

  1. Copy component files: Copy your .tsx and .ts files from fern/components/ to your Stainless site’s src/components/ directory
  2. Update imports: Update any Fern-specific imports to use standard React or Astro imports
  3. Import in content: Import and use components in your MDX files

Example:

src/components/CustomCard.tsx
import { useState } from "react";
export default function CustomCard({ title, content }) {
return (
<div className="custom-card">
<h3>{title}</h3>
<p>{content}</p>
</div>
);
}

Use in content:

---
title: Example Page
---
import CustomCard from "/src/components/CustomCard.tsx";
<CustomCard
title="My Card"
content="Card content here"
/>

If your component needs to be interactive (uses state, event handlers, or effects), add a client directive like client:load:

<CustomCard
title="My Card"
content="Card content here"
client:load
/>

Note the client:load directive is only needed for interactive components, you can omit it for most static content. For more information, see Astro’s client directives documentation.

Fern uses docs.yml to configure navigation. Stainless uses astro.config.ts.

Fern navigation:

docs.yml
navigation:
- section: Getting Started
contents:
- page: Quickstart
path: ./docs/quickstart.mdx
- page: Authentication
path: ./docs/authentication.mdx
- api: API Reference

Stainless navigation:

astro.config.ts
export default defineConfig({
integrations: [
stainlessDocs({
sidebar: [
{
label: 'Getting Started',
items: [
{ label: 'Quickstart', slug: 'docs/quickstart' },
{ label: 'Authentication', slug: 'docs/authentication' },
],
},
{
label: 'API Reference',
autogenerate: { directory: 'api' },
},
],
}),
],
});

The API reference section is automatically generated from your OpenAPI spec. For more information about navigation configuration, see Navigation.

To migrate your branding from Fern to Stainless:

Fern:

docs.yml
colors:
accent-primary: '#4F46E5'
background: '#FFFFFF'

Stainless:

theme.css
:root {
--stl-color-accent: #4F46E5;
}

Stainless also supports the light-dark() function for different colors in light and dark mode:

theme.css
:root {
--stl-color-accent: light-dark(#4F46E5, #7C3AED);
}

For more color customization options, see Styles, fonts, and CSS.

Fern:

docs.yml
logo:
light: ./assets/logo-light.svg
dark: ./assets/logo-dark.svg

Stainless:

  1. Copy your logo files to src/assets/
  2. Configure in astro.config.ts:
export default defineConfig({
integrations: [
stainlessDocs({
logo: {
light: './src/assets/logo-light.svg',
dark: './src/assets/logo-dark.svg',
replacesTitle: true,
alt: 'Your Company',
},
}),
],
});

For more branding options, see Logo and branding.

Fern uses Algolia for search.

Stainless includes built-in search that understands the structure of your SDKs:

  • Metadata-driven indexing: Search indexes are built directly from your SDK’s structural metadata, providing more relevant and precise results than HTML scraping.
  • Faceted search: Users can filter results by programming language and narrow down by resources, methods, types, or properties.
  • Conversational AI: An integrated AI-powered search allows users to ask questions in natural language. A RAG pipeline brings relevant SDK metadata into context for accurate answers.
  • LLM-friendly Markdown: Every documentation page has an LLM-friendly Markdown representation available by adding .md to any URL.

Both Fern and Stainless automatically generate API reference documentation from your OpenAPI spec.

FeatureFernStainless
Auto-generation
SDK code samplesManual setupAutomatic
SEO control
Search indexingConfigurable

You can host your documentation site on Stainless, or with any hosting provider that supports static sites. When you push changes to your main branch, Stainless automatically builds and deploys your site:

Terminal window
git add -A
git commit -m "Migrate from Fern to Stainless"
git push origin main

Monitor your build status in the Stainless dashboard under your project’s API Docs tab.

Your site is initially deployed to a staging domain (a subdomain of stldocs.app). To use a custom domain, see Custom domain.

Now that you have migrated from Fern to Stainless:

If you have questions or need help with your migration, reach out to our team.