Project structure

Configuring fern starts with the fern folder, which contains your API definitions, SDK generators, and your CLI version.

Fern recommends a multi-repository structure with your fern folder in a source repository (containing your API definitions and generation configuration) and each generated SDK in its own separate repository.

Directory structure

When you run fern init (for the Fern Definition) or fern init --spec-type path/to/spec (for other specs), your fern folder is initialized with the following files:

$fern/
> ├─ fern.config.json # Root-level config for entire Fern project
> ├─ generators.yml # Defines SDKs and docs to generate
> └─ spec-folder/ # definition, openapi, asyncapi, etc.
> └─ spec-file.yml # API definition file

Core configuration files

Beyond the core files, you can optionally use an overrides file to customize your API definition without modifying the original spec. See Overrides for instructions.

fern.config.json

The fern.config.json file stores your organization name and the Fern CLI version. Pinning the version provides deterministic builds.

fern.config.json
1{
2 "organization": "plant-catalog",
3 "version": "<Markdown src="/snippets/version-number-cli.mdx"/>"
4}

When working with a locally installed CLI, set version to "*". See Install Fern CLI locally for details.

generators.yml

The generators.yml file specifies which SDKs to generate. For OpenAPI, it also points to the location of your spec. For Fern Definition, Fern automatically detects your spec when your definition/ folder is at the same level as generators.yml.

generators.yml
1# Your API definition
2api:
3 specs:
4 - openapi: ./openapi-1.yml
5
6# SDK generators
7groups:
8 ts-sdk:
9 generators:
10 - name: fernapi/fern-typescript-sdk
11 version: <Markdown src="/snippets/version-number-ts.mdx"/>
12 github:
13 repository: your-organization/typescript-sdk-repo # Location of TypeScript SDK
14
15 python-sdk:
16 generators:
17 - name: fernapi/fern-python-sdk
18 version: <Markdown src="/snippets/version-number-python.mdx"/>
19 github:
20 repository: your-organization/python-sdk-repo # Location of Python SDK

API definition file

For Fern Definition, your API configuration is split across two files: api.yml for API-wide configuration and separate .yml files for your actual endpoint and type definitions. See What is a Fern Definition? for more information.

For the other specification formats (OpenAPI, AsyncAPI, OpenRPC, and gRPC), you’ll have a single self-contained specification file.

To generate API reference documentation, set the api-name property in your docs.yml file.

Multiple APIs

When working with multiple API definitions, you can organize them in multiple ways depending on your SDK generation needs.

Use this approach when each API should generate its own independent set of SDKs.

$fern/
> ├─ fern.config.json
> └─ apis/
> ├─ user-api/
> │ ├─ generators.yml # Configures user-api SDKs
> │ └─ openapi.yml
> └─ payments-api/
> ├─ generators.yml # Configures payments-api SDKs
> └─ openapi.yml

Each API must have its own generators.yml file:

apis/user-api/generators.yml
1api:
2 specs:
3 - openapi: openapi.yml
4groups:
5 ts-sdk:
6 generators:
7 - name: fernapi/fern-typescript-sdk
8 github:
9 repository: company/user-api-typescript

You can use this same pattern for API versioning. See Versioned APIs below.

Pro and Enterprise feature

This feature is available only for the Pro and Enterprise plans. You can merge up to five APIs into a single SDK on the Pro plan, and unlimited APIs on the Enterprise plan. To get started, reach out to support@buildwithfern.com.

Use this approach to merge multiple APIs into a single set of SDKs.

$fern/
> ├─ fern.config.json
> ├─ generators.yml # Single config for combined SDKs
> ├─ user-api/
> │ └─ openapi.yml
> └─ payments-api/
> └─ openapi.yml

List all APIs in a single generators.yml:

generators.yml
1api:
2 specs:
3 - openapi: user-api/openapi.yml
4 - openapi: payments-api/openapi.yml

If your APIs have overlapping schema names, add namespaces:

generators.yml
1api:
2 specs:
3 - openapi: user-api/openapi.yml
4 - namespace: payments
5 openapi: payments-api/openapi.yml

When supporting multiple API versions, you can publish them as separate packages or combine them into a single package with namespaces.

Option 1: Separate packages for each API version

Use this approach when you want each API version to be independently installable (e.g., @company/sdk-v1, @company/sdk-v2). This use case follows the Separate SDKs for each API pattern.

$fern/
> ├─ fern.config.json
> └─ apis/
> ├─ v1/
> │ ├─ generators.yml # Configures v1 SDKs
> │ └─ openapi.yml
> └─ v2/
> ├─ generators.yml # Configures v2 SDKs
> └─ openapi.yml

Each API must have its own generators.yml file:

apis/v1/generators.yml
1api:
2 specs:
3 - openapi: openapi.yml
4groups:
5 ts-sdk:
6 generators:
7 - name: fernapi/fern-typescript-sdk
8 github:
9 repository: company/sdk-v1

Option 2: Namespace-based versioning

If you prefer a single package with multiple API versions, use namespaces. This generates clients like client.v1 and client.v2 within the same package. Note that this increases package size as all versions are bundled together.

$fern/
> ├─ fern.config.json
> ├─ generators.yml # Single config for all versions
> └─ apis/
> ├─ v1/
> │ └─ openapi.yml
> └─ v2/
> └─ openapi.yml

List all API versions in a single generators.yml with namespaces:

generators.yml
1api:
2 specs:
3 - namespace: v1
4 openapi: apis/v1/openapi.yml
5 - namespace: v2
6 openapi: apis/v2/openapi.yml
7groups:
8 ts-sdk:
9 generators:
10 - name: fernapi/fern-typescript-sdk
11 github:
12 repository: company/sdk