fern
Feature-rich Rust logging library. Provides log level configuration, detailed output destination customization, and flexible formatting features. Suitable for scenarios requiring detailed log control in medium to large-scale Rust projects.
Library
Fern
Overview
Fern is "a tool that automatically generates SDKs and documentation from API definitions," developed as a core library for modern API development ecosystems. Taking definition files such as OpenAPI, AsyncAPI, and gRPC as input, it automatically generates multi-language SDKs including TypeScript, Python, Go, Java, Ruby, and interactive API documentation. It significantly streamlines the creation and maintenance of high-quality client libraries and documentation, providing an environment where developers can focus on building APIs.
Details
Fern 2025 edition is rapidly growing as a comprehensive SDK generation platform supporting next-generation API development workflows. Graduated from Y Combinator and trusted by over 150 companies including Square, LaunchDarkly, and Eleven Labs, it's a reliable tool. Supporting industry-standard formats including OpenAPI, it batch-generates multi-language SDKs from a single definition file. Generated SDKs are type-safe and output as practical code including authentication processing, error handling, and response processing.
Key Features
- Multi-language SDK Generation: Supports TypeScript, Python, Go, Java, Ruby, C#, PHP
- Comprehensive Input Formats: Supports OpenAPI, AsyncAPI, OpenRPC, gRPC, and proprietary formats
- Automatic Documentation Generation: Automatically creates interactive API references and guides
- Type-safe Code Generation: Design emphasizing static type checking and IDE support
- Authentication & Error Handling: Standard equipped with features necessary for practical SDKs
- Cloud & Local Execution: Flexible build environments and CI/CD integration
Pros and Cons
Pros
- Automatically generates multi-language SDKs from API definitions, significantly reducing manual maintenance costs
- Improved development efficiency through type-safe, high-quality client libraries
- Compatibility with existing tools through support for industry-standard formats like OpenAPI
- Reliability through enterprise adoption by Square, LaunchDarkly, and others
- Enhanced API user experience through interactive documentation generation
- Flexible development environment through CI/CD integration and both cloud and local support
Cons
- Complexity in managing generated SDK impacts and dependencies when API design changes
- Limitations in customizing generated code and addressing business-specific requirements
- Concerns about long-term support and ecosystem maturity due to being a relatively new tool
- Challenges in generation quality and performance optimization for complex API specifications
- Lack of clarity in pricing structure and enterprise support for commercial use
- Learning costs and migration costs from existing SDK development workflows
Reference Pages
Code Examples
Basic Setup
# Install Fern
npm install -g fern-api
# Initialize new project
fern init
# Check configuration files
ls -la fern/
# fern.config.yml
# generators.yml
# definition/
Creating API Definition Files
# fern/definition/api.yml - Fern proprietary format
name: User Management API
auth: BearerAuth
base-path: /api/v1
types:
User:
properties:
id: string
name: string
email: string
created_at: datetime
CreateUserRequest:
properties:
name: string
email: string
UserResponse:
properties:
user: User
message: optional<string>
services:
UserService:
auth: true
base-path: /users
endpoints:
create:
docs: Create a new user
method: POST
path: ""
request: CreateUserRequest
response: UserResponse
get:
docs: Get user information
method: GET
path: /{id}
path-parameters:
id: string
response: User
list:
docs: Get user list
method: GET
path: ""
query-parameters:
page: optional<integer>
limit: optional<integer>
response: list<User>
SDK Generation Configuration
# fern/generators.yml
default-group: local
groups:
local:
generators:
- name: fernapi/fern-typescript-node-sdk
version: 0.15.0
output:
location: local-file-system
path: ./generated/typescript
config:
organization: my-company
sdk-name: my-api-sdk
- name: fernapi/fern-python-sdk
version: 2.0.0
output:
location: local-file-system
path: ./generated/python
config:
organization: my-company
package-name: my_api_sdk
- name: fernapi/fern-docs
version: 0.15.0
output:
location: local-file-system
path: ./generated/docs
Converting from OpenAPI
# Import existing OpenAPI file
fern add openapi openapi.json
# Validate OpenAPI specification
fern check
# Convert from OpenAPI to Fern definition
fern generate --local
# Check generated SDKs
ls generated/
# typescript/
# python/
# docs/
Advanced Configuration (Custom Generation Options)
# generators.yml - Detailed configuration example
groups:
production:
generators:
- name: fernapi/fern-typescript-node-sdk
version: 0.15.0
output:
location: npm
package-name: "@mycompany/api-sdk"
token: ${NPM_TOKEN}
config:
organization: mycompany
sdk-name: api-sdk
bundle: true
noDevDependencies: true
extraDependencies:
- name: axios
version: "^1.0.0"
- name: fernapi/fern-python-sdk
version: 2.0.0
output:
location: pypi
package-name: mycompany-api-sdk
token: ${PYPI_TOKEN}
config:
organization: mycompany
package-name: mycompany_api_sdk
extra-dependencies:
- requests>=2.25.0
- name: fernapi/fern-docs
version: 0.15.0
output:
location: github-pages
repository: mycompany/api-docs
token: ${GITHUB_TOKEN}
config:
title: "My Company API Documentation"
favicon: ./assets/favicon.ico
logo:
dark: ./assets/logo-dark.png
light: ./assets/logo-light.png
Generated SDK Usage Example
// TypeScript SDK usage example
import { MyApiClient } from '@mycompany/api-sdk';
const client = new MyApiClient({
environment: 'production', // or 'staging'
token: process.env.API_TOKEN
});
// Create user
const newUser = await client.userService.create({
name: 'John Doe',
email: '[email protected]'
});
console.log(`Created user: ${newUser.user.id}`);
// Get user list
const users = await client.userService.list({
page: 1,
limit: 10
});
users.forEach(user => {
console.log(`${user.name} (${user.email})`);
});
// Error handling
try {
const user = await client.userService.get('invalid-id');
} catch (error) {
if (error.statusCode === 404) {
console.log('User not found');
} else {
console.error('Unexpected error:', error.message);
}
}
CI/CD Integration Example
# .github/workflows/generate-sdks.yml
name: Generate SDKs
on:
push:
paths:
- 'fern/**'
pull_request:
paths:
- 'fern/**'
jobs:
generate-sdks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install Fern
run: npm install -g fern-api
- name: Validate API definition
run: fern check
- name: Generate SDKs
run: fern generate --group production
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run SDK tests
run: |
cd generated/typescript && npm test
cd generated/python && python -m pytest