Publishing to npm

Publish your public-facing Fern TypeScript SDK to the npmjs registry. After following the steps on this page, you’ll have a versioned package published on npm.

Already publishing to npm?

If you’re currently using token-based authentication, npmjs is deprecating long-lived tokens in early 2025. See Migrating from token-based to OpenID Connect (OIDC) publishing to upgrade to the more secure OIDC authentication.

Versioned package published on npmjs.com

This page assumes that you have:

Configure SDK package settings

You’ll need to update your generators.yml file to configure the package name, output location, and client naming for npm publishing. Your generators.yml should live in your source repository (or on your local machine), not the repository that contains your TypeScript SDK code.

1

Configure output location

In the group for your TypeScript SDK, change the output location from local-file-system (the default) to npm to indicate that Fern should publish your package directly to the npmjs registry:

generators.yml
1groups:
2 ts-sdk: # Group name for your TypeScript SDK
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: 3.12.0
6 output:
7 location: npm
2

Add a unique package name

Your package name must be unique in the npmjs registry, otherwise publishing your SDK will fail.

generators.yml
1groups:
2 ts-sdk:
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: 3.12.0
6 output:
7 location: npm
8 package-name: your-package-name
3

Configure namespaceExport

The namespaceExport option controls the name of the generated client. This is the name customers use to import your SDK (import { your-client-name } from 'your-package-name';).

generators.yml
1groups:
2 ts-sdk:
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: 3.12.0
6 output:
7 location: npm
8 package-name: your-package-name
9 config:
10 namespaceExport: YourClientName # must be PascalCase

Configure GitHub publishing

Fern can automatically publish your SDK to npmjs via GitHub Actions. Configure your GitHub repository and publishing mode:

Optionally set the mode to control how Fern handles SDK publishing:

  • mode: release (default): Fern generates code, commits to main, and tags a release automatically
  • mode: pull-request: Fern generates code and creates a PR for you to review before release
  • mode: push: Fern generates code and pushes to a branch you specify for you to review before release

You can also configure other settings, like the reviewers or license. Refer to the full github (generators.yml) reference for more information.

generators.yml
1groups:
2 ts-sdk:
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: 3.12.0
6 output:
7 location: npm
8 package-name: your-package-name
9 config:
10 namespaceExport: YourClientName
11 github:
12 repository: your-org/your-repository
13 mode: push # or "pull-request"
14 branch: your-branch-name # Required for mode: push

Configure authentication

Choose how you want to authenticate with npmjs when publishing.

Starting in early 2025, npmjs.org is deprecating long-lived authentication tokens for publishing from CI/CD workflows. OpenID Connect (OIDC) authentication is strongly recommended for security.

This method is being deprecated by npmjs.org in early 2025. Long-lived authentication tokens can be exposed in logs, compromised, and are difficult to manage and rotate. OIDC-based authentication is strongly recommended instead.

1

Generate an npm token

  1. Log into npmjs.com
  2. Click on your profile picture and select Edit Profile
  3. Select Access Tokens
  4. Click Generate New Token and choose either Classic Token (select “Automation” type) or Granular Access Token
  5. Save your token securely - it won’t be displayed again
For more information on access tokens, see npm’s About access tokens documentation.
2

Add token to generators.yml

Add token: ${NPM_TOKEN} to the output section:

generators.yml
1groups:
2 ts-sdk:
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: 3.12.0
6 output:
7 location: npm
8 package-name: your-package-name
9 token: ${NPM_TOKEN}
10 config:
11 namespaceExport: YourClientName
12 github:
13 repository: your-org/your-repository
14 mode: push
15 branch: your-branch-name
3

Add NPM_TOKEN as a GitHub Actions secret

  1. Open your repository on GitHub and go to Settings
  2. Navigate to Secrets and variables > Actions
  3. Click New repository secret
  4. Name it NPM_TOKEN and paste your npm token
  5. Click Add secret

Publish your SDK

Your SDK will automatically be published to npmjs when you create a GitHub release with a version tag:

  1. Create a GitHub release with a version tag (for example, v1.0.0)
  2. The CI workflow will run automatically and publish to npm
  3. View your package on npmjs.com to confirm the new version

If you prefer to trigger publishes manually, create a .github/workflows/publish.yml file:

.github/workflows/publish.yml
1name: Publish TypeScript SDK
2
3on:
4 workflow_dispatch:
5 inputs:
6 version:
7 description: "Version to publish (e.g., 1.0.0)"
8 required: true
9 type: string
10
11jobs:
12 publish:
13 runs-on: ubuntu-latest
14 steps:
15 - name: Checkout repo
16 uses: actions/checkout@v4
17
18 - name: Install Fern
19 run: npm install -g fern-api
20
21 - name: Generate and publish SDK
22 env:
23 FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
24 run: fern generate --group ts-sdk --version ${{ inputs.version }} --log-level debug

Add your FERN_TOKEN as a repository secret (run fern token to generate one), then trigger the workflow from the Actions tab.


Migrating from token-based to OIDC publishing

If you’re currently using token-based authentication and need to migrate to OIDC, follow these steps:

Why migrate to OIDC

npmjs is implementing trusted publishing to remove security risks associated with long-lived tokens, which can be:

  • Exposed in logs or configuration files
  • Compromised and used persistently until manually revoked
  • Difficult to manage and rotate

OIDC-based publishing uses short-lived, cryptographically signed tokens that are specific to your workflow and can’t be extracted or reused.

Prerequisites

Before migrating, ensure you have:

  • A package published to npmjs.org
  • A GitHub repository with GitHub Actions configured
  • Access to your package settings on npmjs.com
  • Fern CLI version 0.94.0 or later (for local generation)

Choose your migration path

Select the approach that fits your situation:

Use this path if you can’t upgrade the generator or have customized your CI workflow.

When to use this path:

  • You can’t upgrade due to breaking changes or bugs
  • You’ve customized your CI workflow and added it to .fernignore
  • Path 1 didn’t update your workflow file
1

Configure trusted publishing on npmjs.com

Follow the same instructions as Path 1 to add your repository as a trusted publisher on npmjs.com.

2

Update your CI workflow manually

Open your .github/workflows/ci.yml file and make these changes to the publish job:

.github/workflows/ci.yml
1publish:
2 needs: [ compile, test ]
3 if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
4 runs-on: ubuntu-latest
5 permissions:
6 id-token: write # ADD THIS: Required for OIDC
7 steps:
8 - name: Checkout repo
9 uses: actions/checkout@v4
10
11 - name: Set up node
12 uses: actions/setup-node@v4
13
14 # ADD THIS: Ensure npm 11.5.1 or later is installed for OIDC support
15 - name: Update npm
16 run: npm install -g npm@latest
17
18 - name: Install pnpm
19 uses: pnpm/action-setup@v4
20
21 - name: Install dependencies
22 run: pnpm install
23
24 - name: Build
25 run: pnpm build
26
27 # MODIFY THIS: Remove npm config set and env block
28 - name: Publish to npm
29 run: |
30 if [[ ${GITHUB_REF} == *alpha* ]]; then
31 npm publish --access public --tag alpha
32 elif [[ ${GITHUB_REF} == *beta* ]]; then
33 npm publish --access public --tag beta
34 else
35 npm publish --access public
36 fi
37 # Previously had:
38 # run: |
39 # npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
40 # if [[ ${GITHUB_REF} == *alpha* ]]; then
41 # npm publish --access public --tag alpha
42 # elif [[ ${GITHUB_REF} == *beta* ]]; then
43 # npm publish --access public --tag beta
44 # else
45 # npm publish --access public
46 # fi
47 # env:
48 # NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Key changes:

  • Add permissions block with id-token: write to the publish job
  • Add step to update npm to version 11.5.1 or later
  • Remove the npm config set line from the publish step
  • Remove the env block with NPM_TOKEN from the publish step
3

(Optional) Add ci.yml to .fernignore

If you haven’t already, add your CI workflow to .fernignore to prevent future generator updates from overwriting your manual changes:

.fernignore
.github/workflows/ci.yml
4

Remove the NPM_TOKEN secret

After verifying the migration works, remove the NPM_TOKEN secret from your GitHub repository settings.

Verify your migration

After completing either migration path:

  1. Trigger a workflow run by creating a GitHub release with an alpha tag (for example, v1.0.0-alpha)
  2. Check the workflow logs to verify the publish step succeeds
  3. Verify provenance by visiting your package on npmjs.com - you should see a provenance badge

Migration troubleshooting

Common causes:

  • Workflow filename doesn’t match exactly (must be ci.yml with the .yml extension)
  • Missing id-token: write permission in workflow
  • npm CLI version is older than 11.5.1
  • Using self-hosted runners (not currently supported)

Solution: Double-check your trusted publisher configuration on npmjs.com matches your actual workflow file name and verify all requirements are met.

If your workflow continues using the old token-based authentication:

  • Verify you’ve removed the npm config set line and the env: NPM_TOKEN block from the publish step
  • Check that npm CLI version 11.5.1+ is installed (add the update npm step)
  • Ensure you’re using generator version 3.12.0 or later (if using Path 1)
  • When using --local generation, you need to use Fern CLI version 0.94.0 or later