From Fern

Onboarding guide for Fern Docs users migrating to Bengal

12 min read 2422 words

Fern is powerful for API-first teams with SDK generation. Bengal focuses purely on documentation—giving you full control over your content without proprietary syntax. If you're migrating away from Fern's docs platform, this guide shows you how.

Quick Wins (5 Minutes)

Understanding the Difference

Aspect Fern Bengal
Primary focus API + SDK + Docs Documentation only
Configuration fern.config.json+docs.yml bengal.toml
Content format MDX (proprietary extensions) Standard Markdown
Hosting Fern-hosted Self-hosted anywhere
SDK generation Built-in External tools

What Transfers Directly

Fern Bengal Status
MDX content Markdown ✅ Convert syntax
OpenAPI specs OpenAPI support ✅ Works directly
Navigation structure Directory-based nav ✅ Simpler
Code examples Code blocks ✅ Identical

Component → Directive Translation

Callouts

<Callout intent="info">
  This is an informational callout.
</Callout>

<Callout intent="warning">
  This is a warning callout.
</Callout>

<Callout intent="success">
  Operation completed successfully.
</Callout>

<Callout intent="danger">
  Critical warningproceed with caution.
</Callout>
:::{info}
This is an informational callout.
:::

:::{warning}
This is a warning callout.
:::

:::{tip}
Operation completed successfully.
:::

:::{danger}
Critical warning—proceed with caution.
:::

Tabs / Code Examples

<CodeBlocks>
  <CodeBlock title="Python">
    ```python
    import fern
    client = fern.Client(api_key="...")
    ```
  </CodeBlock>
  <CodeBlock title="TypeScript">
    ```typescript
    import { FernClient } from "fern";
    const client = new FernClient({ apiKey: "..." });
    ```
  </CodeBlock>
  <CodeBlock title="Go">
    ```go
    client := fern.NewClient(fern.WithAPIKey("..."))
    ```
  </CodeBlock>
</CodeBlocks>
:::{tab-set}
:::{tab} Python
```python
import myapi
client = myapi.Client(api_key="...")
```
:::{/tab}
:::{tab} TypeScript
```typescript
import { MyAPIClient } from "myapi";
const client = new MyAPIClient({ apiKey: "..." });
```
:::{/tab}
:::{tab} Go
```go
client := myapi.NewClient(myapi.WithAPIKey("..."))
```
:::{/tab}
:::{/tab-set}

Cards

<Cards>
  <Card
    title="Getting Started"
    icon="rocket"
    href="/docs/getting-started"
  >
    Set up your first integration in minutes.
  </Card>
  <Card
    title="API Reference"
    icon="book"
    href="/docs/api-reference"
  >
    Complete reference for all endpoints.
  </Card>
</Cards>
:::{cards}
:columns: 2

:::{card} Getting Started
:icon: rocket
:link: /docs/getting-started/

Set up your first integration in minutes.
:::{/card}

:::{card} API Reference
:icon: book
:link: /docs/api-reference/

Complete reference for all endpoints.
:::{/card}

:::{/cards}

Accordions

<Accordion title="How do I authenticate?">
  Use the `Authorization` header with your API key:

Authorization: Bearer YOUR_API_KEY

</Accordion>

<Accordion title="What are the rate limits?">
We allow 1000 requests per minute per API key.
</Accordion>
:::{dropdown} How do I authenticate?
:icon: key

Use the `Authorization` header with your API key:
```
Authorization: Bearer YOUR_API_KEY
```
:::

:::{dropdown} What are the rate limits?
:icon: clock

We allow 1000 requests per minute per API key.
:::

Steps / Guides

<Steps>
  <Step title="Install the SDK">
    ```bash
    npm install @your-company/sdk
    ```
  </Step>
  <Step title="Initialize">
    ```typescript
    import { Client } from "@your-company/sdk";
    const client = new Client({ apiKey: "..." });
    ```
  </Step>
  <Step title="Make a request">
    ```typescript
    const users = await client.users.list();
    ```
  </Step>
</Steps>
:::{steps}

:::{step} Install the SDK
```bash
npm install @your-company/sdk
```
:::{/step}

:::{step} Initialize
```typescript
import { Client } from "@your-company/sdk";
const client = new Client({ apiKey: "..." });
```
:::{/step}

:::{step} Make a request
```typescript
const users = await client.users.list();
```
:::{/step}

:::{/steps}

API Endpoint Documentation

# Fern generates from your API definition
# Custom docs in MDX reference generated content

<EndpointRequestSnippet endpoint="GET /users" />
<EndpointResponseSnippet endpoint="GET /users" />
## List Users

`GET /users`

### Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `limit` | integer | No | Maximum results (default: 20) |
| `offset` | integer | No | Pagination offset |

### Response

| Field | Type | Description |
|-------|------|-------------|
| `users` | array | List of user objects |
| `total` | integer | Total count |

### Example

```bash
curl -X GET "https://api.example.com/users?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Note**: Bengal generates API reference pages automatically from your OpenAPI spec via autodoc. Configure in `bengal.toml`:

```toml
[autodoc.openapi]
enabled = true
spec_file = "openapi.yaml"
```

This generates dedicated pages for each endpoint at `/api-reference/endpoints/...`

Configuration Comparison

Basic Config

// fern.config.json
{
  "organization": "your-org",
  "version": "0.x.x"
}
# docs.yml
instances:
  - url: https://docs.your-company.com

title: Your Company Docs

navigation:
  - section: Getting Started
    contents:
      - page: Introduction
        path: ./pages/introduction.mdx
      - page: Quickstart
        path: ./pages/quickstart.mdx
  - section: API Reference
    contents:
      - api: API Reference

colors:
  accentPrimary: "#0D9373"

logo:
  light: ./assets/logo-light.svg
  dark: ./assets/logo-dark.svg
[site]
title = "Your Company Docs"
baseurl = "https://docs.your-company.com"
theme = "bengal"

[site.logo]
light = "assets/logo-light.svg"
dark = "assets/logo-dark.svg"

# Navigation auto-generated from directory structure
# Use weight frontmatter for ordering

# OpenAPI integration
[autodoc.openapi]
enabled = true
spec = "openapi.yaml"
navigation:
  - section: Getting Started
    contents:
      - page: Introduction
        path: ./pages/introduction.mdx
      - page: Quickstart
        path: ./pages/quickstart.mdx
      - page: Authentication
        path: ./pages/authentication.mdx
  - section: Guides
    contents:
      - page: Webhooks
        path: ./pages/guides/webhooks.mdx
      - page: Pagination
        path: ./pages/guides/pagination.mdx
  - section: API Reference
    contents:
      - api: API Reference
# Navigation from directory structure + weight frontmatter:

content/
├── docs/
│   ├── getting-started/
│   │   ├── _index.md (weight: 10)
│   │   ├── introduction.md (weight: 10)
│   │   ├── quickstart.md (weight: 20)
│   │   └── authentication.md (weight: 30)
│   ├── guides/
│   │   ├── _index.md (weight: 20)
│   │   ├── webhooks.md (weight: 10)
│   │   └── pagination.md (weight: 20)
│   └── api-reference/
│       ├── _index.md (weight: 30)
│       └── ... (generated from OpenAPI)

Tip

No manualdocs.ymlupdates when you add pages. Bengal's directory structure is the navigation.


What You Don't Need Anymore

Fern Requires Bengal
fern.config.json Not needed
docs.ymlnavigation Auto-generated
Fern CLI (fern generate) bengal build
Fern hosting Any static host
Proprietary MDX syntax Standard markdown
Fern organization account Self-hosted

Feature Comparison

What Bengal Has

Feature Fern Bengal
Callouts <Callout> :::{note},:::{warning}
Tabs <CodeBlocks> :::{tab-set}
Cards <Cards> :::{cards}
Steps <Steps> :::{steps}
Accordions <Accordion> :::{dropdown}
Code blocks Built-in Built-in ✅
OpenAPI Built-in Autodoc generates pages from spec ✅
Search Built-in Built-in ✅
Dark mode Built-in Built-in ✅
Custom domains Paid feature Any host

What's Different (Trade-offs)

Feature Fern Bengal Notes
SDK generation Built-in External Use OpenAPI Generator, etc.
API playground Interactive Static External tools for testing
Type-safe API definitions Fern Definition OpenAPI Standard spec works
Hosting Managed Self-hosted More control
AI-powered search Built-in External Integrate your own

What Bengal Adds

Feature Description
Full source control Modify anything
No vendor lock-in Standard formats
Offline development Complete local workflow
Build-time validation bengal healthchecks
Content versioning _versions/folders
Custom themes Full theming control

SDK Generation Alternative

Fern's SDK generation is separate from documentation. Without Fern, you can use:

# OpenAPI Generator (most languages)
openapi-generator generate -i openapi.yaml -g python -o ./sdk/python

# For TypeScript specifically
npx @openapitools/openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-fetch \
  -o ./sdk/typescript

# Or use language-specific tools:
# Python: openapi-python-client
# Go: oapi-codegen
# Rust: openapi-generator with rust templates

Your OpenAPI spec works with any generator. Documentation is independent of SDK generation.


Directory Structure Comparison

Fern Bengal Notes
fern/ Project root Simpler structure
fern/docs/pages/ content/docs/ Content location
fern/docs/assets/ assets/ Static files
fern.config.json Not needed No central config
docs.yml bengal.toml+ directories Simpler
fern/openapi/ Project root orapi/ Flexible location

What Bengal Adds

---
title: API Reference
api_version: "2.0"
base_url: "https://api.example.com/v2"
---

# {{ page.title }}

Current version: **{{ page.metadata.api_version }}**
Base URL: `{{ page.metadata.base_url }}`

Use template variables directly in markdown.

<!-- _snippets/auth-note.md -->
:::{note}
All API requests require authentication.
Include your API key in the `Authorization` header.
:::

<!-- In any page -->
:::{include} /_snippets/auth-note.md
:::

DRY principle for documentation.

# Check all links
bengal health linkcheck

# Full health check
bengal health

# Analyze site structure
bengal analyze

Catch problems before they reach users.

# Deploy anywhere
bengal build
# Output is static HTML

# Works with:
# - GitHub Pages
# - Netlify
# - Vercel
# - Cloudflare Pages
# - AWS S3 + CloudFront
# - Any web server

Migration Steps

  1. 1

    Install Bengal

    pip install bengal
    # or with uv
    uv add bengal
    
  2. 2

    Create New Site

    bengal new site mysite
    cd mysite
    
  3. 3

    Copy Content

    # Copy your Fern MDX files
    cp -r /path/to/fern/docs/pages/* content/docs/
    
    # Copy assets
    cp -r /path/to/fern/docs/assets/* assets/
    
    # Copy OpenAPI spec
    cp /path/to/fern/openapi/openapi.yaml .
    
  4. 4

    Convert MDX Syntax

    Replace Fern components with directives:

    Find Replace With
    <Callout intent="info"> :::{info}
    <Callout intent="warning"> :::{warning}
    <Callout intent="success"> :::{tip}
    <Callout intent="danger"> :::{danger}
    <CodeBlocks> :::{tab-set}
    <CodeBlock title="X"> :::{tab} X
    <Cards> :::{cards}
    <Card> :::{card}
    <Steps> :::{steps}
    <Step> :::{step}
    <Accordion> :::{dropdown}
  5. 5

    Rename Files

    # Rename .mdx to .md
    find content -name "*.mdx" -exec sh -c 'mv "$1" "${1%.mdx}.md"' _ {} \;
    
    # Create section index files
    # For each directory, create _index.md
    
  6. 6

    Add Frontmatter

    Add ordering to pages:

    ---
    title: Quickstart
    weight: 20
    description: Get started in 5 minutes
    ---
    
  7. 7

    Configure OpenAPI (Optional)

    If using OpenAPI for API reference:

    # config/_default/autodoc.yaml
    autodoc:
      openapi:
        enabled: true
        specs:
          - path: "openapi.yaml"
            output_prefix: "api-reference"
    
  8. 8

    Test

    bengal build
    bengal health linkcheck
    bengal serve
    

Migration Checklist

Before You Start

  • Install Bengal:pip install bengal
  • Export/download your Fern content
  • Create new Bengal site:bengal new site mysite

Content Migration

  • Copy MDX files tocontent/docs/
  • Rename.mdxto.md
  • Convert<Callout>to:::{note}, etc.
  • Convert<CodeBlocks>to:::{tab-set}
  • Convert<Cards>to:::{cards}
  • Convert<Steps>to:::{steps}
  • Remove Fern-specific imports

Configuration

  • Createbengal.toml
  • Addweightfrontmatter for ordering
  • Create_index.mdfor each section
  • Configure OpenAPI autodoc if used

Assets

  • Copy images toassets/
  • Update image paths in content
  • Copy OpenAPI specs

Verify

  • Build:bengal build
  • Check:bengal health linkcheck
  • Preview:bengal serve

Quick Reference Card

Task Fern Bengal
Install npm install fern-api pip install bengal
Initialize fern init bengal new site
Generate fern generate bengal build
Serve Fern hosting bengal serve
Deploy Push to Fern Any static host
Callout <Callout> :::{note}
Tabs <CodeBlocks> :::{tab-set}
Cards <Cards> :::{cards}
Steps <Steps> :::{steps}

Common Questions


Next Steps