Skip to navigation

Publishing to npm

View as Markdown

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. To distribute the SDK internally instead, generate to the local file system (optionally self-hosted) and build a tarball with fern generate --package.

Already publishing to npm?

If you’re using token-based authentication, npm has deprecated long-lived classic tokens. 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:

  • An initialized fern folder, a GitHub repository for your TypeScript SDK, and a TypeScript generator group in generators.yml. See Generating an SDK (TypeScript).

Configure SDK package settings

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
groups:
ts-sdk: # Group name for your TypeScript SDK
generators:
- name: fern-typescript-sdk
version: 3.97.1
output:
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
groups:
ts-sdk:
generators:
- name: fern-typescript-sdk
version: 3.97.1
output:
location: npm
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
groups:
ts-sdk:
generators:
- name: fern-typescript-sdk
version: 3.97.1
output:
location: npm
package-name: your-package-name
config:
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 the default branch (or the branch you specify), and tags a release automatically
  • mode: pull-request (recommended): 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
groups:
ts-sdk:
generators:
- name: fern-typescript-sdk
version: 3.97.1
output:
location: npm
package-name: your-package-name
config:
namespaceExport: YourClientName
github:
repository: your-org/your-repository
mode: push # or "pull-request"
branch: your-branch-name # Required for mode: push

Configure authentication

Choose how you want to authenticate with npmjs when publishing.

npm has deprecated long-lived classic tokens for publishing from CI/CD workflows. OpenID Connect (OIDC) authentication is strongly recommended for security.

npm has deprecated long-lived classic tokens. 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
groups:
ts-sdk:
generators:
- name: fern-typescript-sdk
version: 3.97.1
output:
location: npm
package-name: your-package-name
token: ${NPM_TOKEN}
config:
namespaceExport: YourClientName
github:
repository: your-org/your-repository
mode: push
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 version

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

.github/workflows/publish.yml
name: Publish TypeScript SDK
on:
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g., 1.0.0)"
required: true
type: string
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Install Fern
run: npm install -g fern-api
- name: Generate and publish SDK
env:
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
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 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
publish:
needs: [ compile, test ]
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
contents: read # ADD THIS: Required for actions/checkout@v4
id-token: write # ADD THIS: Required for OIDC
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up node
uses: actions/setup-node@v4
# ADD THIS: Ensure npm 11.5.1 or later is installed for OIDC support
- name: Update npm
run: npm install -g npm@latest
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
# MODIFY THIS: Remove npm config set and env block
- name: Publish to npm
run: |
if [[ ${GITHUB_REF} == *alpha* ]]; then
npm publish --access public --tag alpha
elif [[ ${GITHUB_REF} == *beta* ]]; then
npm publish --access public --tag beta
else
npm publish --access public
fi
# Previously had:
# run: |
# npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
# if [[ ${GITHUB_REF} == *alpha* ]]; then
# npm publish --access public --tag alpha
# elif [[ ${GITHUB_REF} == *beta* ]]; then
# npm publish --access public --tag beta
# else
# npm publish --access public
# fi
# env:
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Key changes:

  • Add permissions block with id-token: write and contents: read 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 or contents: read permissions in workflow
  • npm CLI version is older than 11.5.1
  • Using self-hosted runners (not 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 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.3 or later (if using Path 1)
  • When using --local generation, you need to use Fern CLI version 0.94.0 or later