diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml index 675808397..c8e4591d7 100644 --- a/.github/workflows/preview-docs.yml +++ b/.github/workflows/preview-docs.yml @@ -8,6 +8,7 @@ on: jobs: run: + if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: pull-requests: write # Only for commenting diff --git a/AGENTS.md b/AGENTS.md index 0e4c68ecf..2951e9e68 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -88,6 +88,77 @@ The correct link is: - **Same-page anchors**: `#section-name` — these don't need a full path. - **Anchors on internal links**: `/learn/docs/config/navigation#section-availability` — append `#anchor` to the URL path. +## Cross-referencing + +When new functionality is documented — whether on a new page or as new behavior added to an existing page — related pages elsewhere in the docs usually need pointers to it. Without those pointers, the canonical content is hard to discover from the angles a reader is most likely to come in from. + +### Pick a canonical home + +One page owns the full explanation; every other page that touches the topic links *to* it rather than restating it. + +- Walkthroughs, setup steps, and concept explanations live on the canonical page. +- Reference pages get a sentence + link, not a paragraph of duplicated detail. +- If you find yourself copying more than a sentence or two into a reference page, the content probably belongs on the canonical page. + +### Find the targets + +Sweep the docs for related touchpoints before assuming you're done: + +```bash +grep -rln "\|" fern/products --include="*.mdx" +``` + +Then read each candidate to find the natural insertion point. Common targets: + +- **Behavior pages** — e.g., a feature affects search → cross-link from `customization/search.mdx`. +- **Dashboard pages** — e.g., a feature has dashboard settings → cross-link from `dashboard/pages/`. +- **Adjacent feature pages** — e.g., Ask Fern, RBAC, localization, when scope or behavior overlaps. +- **Overview / landing pages** — sometimes a card on a hub page is warranted; usually only when the feature is a top-level setup step, not a configuration detail. + +### Pick the form + +| Form | Use when | +|------|----------| +| Inline sentence in an existing paragraph | The reference fits a list of similar items already on the page (e.g., "for sites with X, Y, or [new thing]"). | +| `` callout | The reference is a real but secondary consideration that would distract from the main flow if inlined. | +| New section (`##`) | The target page genuinely needs to document the feature from its own angle (e.g., dashboard config for the feature). | +| New page | Only if the feature has substantial standalone content that doesn't fit elsewhere. | + +Default to the lightest form that works. New pages and new sections add maintenance surface; inline sentences and Notes don't. + +### Frame by function, not by plumbing + +Lead the cross-reference with what each feature *does* and how they complement or differ. Don't headline the connection with shared config infrastructure — same YAML key, sibling files in the same directory, same lifecycle. + +- Good: "X decides A; Y decides B." Contrast on function. +- Bad: "Y is also configured under the same `agents` key." Contrast on plumbing. + +If the only thing linking two features is that they live in the same key, that's not a cross-reference worth writing. Config mechanics belong on the page that is itself about configuration. + +### Bidirectional links + +Reference pages always link *to* canonical. Linking back from canonical to a reference page is optional — only do it when the reference page has additional detail the canonical page doesn't cover (e.g., dashboard click-paths). Most cross-references are one-way. + +### Anchor links + +Internal anchors only resolve for `##` / `###` headings. Things that look like headings but aren't: + +- `` inside `` — JSX prop, no anchor generated. +- ``, ``, `` — same. + +If you want to deep-link to a step or tab, add a real `##` heading nearby, or link to the page without an anchor and let the reader scroll. + +### Sweep checklist + +After documenting any new functionality, before declaring the work done: + +1. Grep for the feature/setting name and 1–2 related keywords across `fern/products/**/*.mdx`. +2. For each hit on a different page, decide: is a cross-reference warranted? +3. For each warranted cross-ref, pick the lightest form that fits. +4. Frame each cross-ref by what each feature does, not by shared config keys or directory structure. +5. If the functionality has dashboard settings, verify `fern/products/dashboard/pages/` covers them — usually folded into the most relevant existing page, not a new page. +6. Verify every link you wrote — see *Link checking* above for URL construction. + ## Changelog entries Changelog entries live in `fern/products/docs/pages/changelog/` and `fern/products/dashboard/pages/changelog/`. Filename format: `YYYY-MM-DD.mdx`. diff --git a/fern/products/api-def/openapi/auth.mdx b/fern/products/api-def/openapi/auth.mdx index 7aca361ce..6940b776e 100644 --- a/fern/products/api-def/openapi/auth.mdx +++ b/fern/products/api-def/openapi/auth.mdx @@ -218,6 +218,8 @@ auth-schemes: env: MY_CLIENT_SECRET ``` +[Set `omit: true` on `username` or `password`](/learn/sdks/reference/generators-yml#usernameomit-passwordomit) to remove it from the generated SDK. + diff --git a/fern/products/api-def/openapi/extensions/availability.mdx b/fern/products/api-def/openapi/extensions/availability.mdx index 362281593..0d52666a3 100644 --- a/fern/products/api-def/openapi/extensions/availability.mdx +++ b/fern/products/api-def/openapi/extensions/availability.mdx @@ -5,7 +5,7 @@ description: Mark API endpoint availability in OpenAPI with `x-fern-availability --- -The `x-fern-availability` extension is used to mark the availability of an endpoint within your OpenAPI definition. The availability information propagates into the generated Fern Docs website as visual tags. +The `x-fern-availability` extension is used to mark the availability of an endpoint within your OpenAPI definition. The availability information propagates into the generated Fern Docs website as visual tags, SDKs, and [CLIs](/learn/cli-generator/get-started/openapi-extensions#availability-badges). You can configure the `availability` of sections in your API Reference documentation in your [`docs.yml` file](/learn/docs/configuration/site-level-settings). diff --git a/fern/products/api-def/openapi/extensions/method-names.mdx b/fern/products/api-def/openapi/extensions/method-names.mdx index c18e0b9a4..82c460fae 100644 --- a/fern/products/api-def/openapi/extensions/method-names.mdx +++ b/fern/products/api-def/openapi/extensions/method-names.mdx @@ -5,7 +5,7 @@ description: Use `x-fern-sdk-method-name` and `x-fern-sdk-group-name` to finetun --- -Use the `x-fern-sdk-group-name` and `x-fern-sdk-method-name` extensions to control how endpoints are organized in your SDK. +Use the `x-fern-sdk-group-name` and `x-fern-sdk-method-name` extensions to control how endpoints are organized in your [SDKs](/learn/sdks/overview/introduction) and [CLIs](/learn/cli-generator/get-started/openapi-extensions). If no extensions are present, Fern uses your operation ID to generate SDK method names. Format operation IDs as `{tag_name}_{operation_name}` (example: `users_get`) to automatically generate methods like `users.get()`. If the operation ID doesn't start with a tag, Fern uses it directly as the method name. diff --git a/fern/products/api-def/openapi/extensions/overview.md b/fern/products/api-def/openapi/extensions/overview.md index f1dc736d3..da37a84fc 100644 --- a/fern/products/api-def/openapi/extensions/overview.md +++ b/fern/products/api-def/openapi/extensions/overview.md @@ -4,7 +4,7 @@ headline: Extensions overview (OpenAPI) description: Learn about OpenAPI extensions in Fern. Customize authentication, SDK methods, versioning, and more for better API specs. --- -Fern supports a variety of OpenAPI extensions that enhance your API specification and generate higher-quality SDKs. +Fern supports a variety of OpenAPI extensions that enhance your API specification and generate higher-quality SDKs and [CLIs](/learn/cli-generator/get-started/openapi-extensions). You can apply these extensions in two ways: by overlaying them in a separate file or by embedding them directly in your OpenAPI specification. See [Overlays](/learn/api-definitions/openapi/overlays) for more information. diff --git a/fern/products/api-def/openapi/extensions/pagination.mdx b/fern/products/api-def/openapi/extensions/pagination.mdx index 8548ecd68..9120fae98 100644 --- a/fern/products/api-def/openapi/extensions/pagination.mdx +++ b/fern/products/api-def/openapi/extensions/pagination.mdx @@ -7,7 +7,7 @@ description: Configure auto-pagination for list endpoints using the x-fern-pagin -The `x-fern-pagination` extension configures auto-pagination for list endpoints in your OpenAPI specification. [Fern's generated SDKs](/learn/sdks/deep-dives/auto-pagination) provide simple iterators that handle pagination automatically, so SDK users can loop through all results without managing pagination complexity manually. +The `x-fern-pagination` extension configures auto-pagination for list endpoints in your OpenAPI specification. [SDK](/learn/sdks/deep-dives/auto-pagination) and [CLI](/learn/cli-generator/get-started/openapi-extensions#pagination) users get automatic pagination without managing page tokens manually. To configure pagination: diff --git a/fern/products/api-def/openapi/overlays.mdx b/fern/products/api-def/openapi/overlays.mdx index 9c72a48dd..61b98ac3e 100644 --- a/fern/products/api-def/openapi/overlays.mdx +++ b/fern/products/api-def/openapi/overlays.mdx @@ -7,7 +7,7 @@ description: Use the OpenAPI Overlay Specification to customize your OpenAPI def Overlays let you customize your OpenAPI specification without modifying the original file. This is useful when: - Your API specification is auto-generated from server code -- You need different configurations for SDKs versus documentation +- You need different configurations for SDKs, documentation, or [generated CLIs](/learn/cli-generator/get-started/customization#overrides-and-overlays) - You want to add Fern configurations like pagination or SDK method names - You want to make bulk changes across many endpoints using JSONPath wildcards diff --git a/fern/products/api-def/pages/overrides.mdx b/fern/products/api-def/pages/overrides.mdx index ca9d24858..710b95072 100644 --- a/fern/products/api-def/pages/overrides.mdx +++ b/fern/products/api-def/pages/overrides.mdx @@ -7,7 +7,7 @@ description: Customize your API definition using a separate overrides file. Use an overrides file to customize your OpenAPI, AsyncAPI, or OpenRPC definition without modifying the original spec. This is useful when: * Your API specification is auto-generated from server code -* You need different configurations for SDKs versus documentation +* You need different configurations for SDKs, documentation, or [generated CLIs](/learn/cli-generator/get-started/customization#overrides-and-overlays) Overrides are available for OpenAPI, AsyncAPI, and OpenRPC specifications. diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-10.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-10.mdx new file mode 100644 index 000000000..d78386222 --- /dev/null +++ b/fern/products/cli-api-reference/cli-changelog/2026-05-10.mdx @@ -0,0 +1,6 @@ +## 5.22.0 +**`(feat):`** Add `fern sdk list` command to list configured and available SDK generators. +Displays configured SDKs from local fern.yml and available generators from the +Fern registry. Supports `--language`, `--type`, and `--json` flags. + + diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-11.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-11.mdx new file mode 100644 index 000000000..f0d5cbce8 --- /dev/null +++ b/fern/products/cli-api-reference/cli-changelog/2026-05-11.mdx @@ -0,0 +1,26 @@ +## 5.23.1 +**`(fix):`** Fix `fern docs dev` hanging indefinitely on Node.js v26+ on Linux by disabling +io_uring in the child server process. Node 26 enables io_uring by default in +libuv, which has a busy-loop bug where worker threads spin on an internal +eventfd, starving the main event loop. + + +## 5.23.0 +**`(internal):`** Add an opt-in `VerificationStep` to the post-generation pipeline that runs +`.fern/verify.sh` (when emitted by the generator) inside a language-specific +`{generatorImage}-validator` container after replay and before any GitHub +push. A failing script aborts the pipeline before opening a PR and surfaces +raw stderr through the pipeline logger; a missing script is a silent no-op. + +The step is gated on a hidden `--verify` flag for `fern generate`; when +passed (with `--local` or `--runner`), the local workspace runner sets +`config.verify.enabled = true` on the pipeline and the configured container +runtime (`docker` or `podman`) is forwarded to the validator container. +Remote/Fiddle generation does not honor this flag yet. + + +## 5.22.1 +**`(fix):`** Fix `fern docs dev` failing with pnpm 11 due to esbuild build scripts being blocked by default. +Writes `onlyBuiltDependencies` config to the bundle folder before installing esbuild. + + diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-12.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-12.mdx new file mode 100644 index 000000000..b3333e3df --- /dev/null +++ b/fern/products/cli-api-reference/cli-changelog/2026-05-12.mdx @@ -0,0 +1,17 @@ +## 5.23.3 +**`(fix):`** Property-level `x-fern-audiences` filtering now also applies on the V3 OpenAPI / AsyncAPI / +OpenRPC import path used by `fern docs dev` and `fern generate --from-openapi`. Inline +request-body properties, query parameters, inline webhook payload properties, named-type +properties, `v2RequestBodies`, and the docs `v2Examples` blocks (type-level, request body, +response body, endpoint-level, `v2Responses`, and webhook payload examples) are now scrubbed +using the same exclusion semantics as the Fern Definition path. Untagged elements remain +universal and are never silently removed. + + +## 5.23.2 +**`(fix):`** Suppress Fern's platform `User-Agent` header in generated SDKs when the API definition +declares a global `User-Agent` header (case-insensitive) under `api.headers`. This +allows customers to fully override the SDK User-Agent via their Fern Definition without +the auto-generated `/` value also being emitted. + + diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-13.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-13.mdx new file mode 100644 index 000000000..f7d2601ea --- /dev/null +++ b/fern/products/cli-api-reference/cli-changelog/2026-05-13.mdx @@ -0,0 +1,30 @@ +## 5.24.0 +**`(internal):`** Plumb `verify`, `verifyRunner`, and `verifyValidatorVersion` flags through +`GenerationRunner.RunArgs` so the seed runner can invoke +`PostGenerationPipeline` with `VerificationStep` and exercise the same +validator-container code path that `fern generate --local --verify` uses. +No customer-facing CLI behavior change — the flags are opt-in and used only +by the seed test runner today. + + +## 5.23.6 +**`(fix):`** Fix `fern docs dev` hot reload not working for .mdx file changes. The backend +now updates the docs definition before notifying the browser to refresh, and +the reload handler properly recovers from errors instead of silently blocking +all future reloads. + + +## 5.23.5 +**`(fix):`** Fix SDK generation crashing with `fatal: is not a valid object` +when the prior fern-bot PR was squash-merged and its branch deleted. +The stale `fern-generation-base` tag update is now skipped with a +warning; the SDK PR still opens. + + +## 5.23.4 +**`(fix):`** Fix allOf composition so inline elements with real constraints (e.g. `pattern`, `minLength`) produce a properly merged type instead of being silently dropped. Also refactored the allOf shortcircuit logic to use a metadata allowlist, which is safer against new OpenAPI fields. + + +**`(fix):`** Fix example generation for allOf compositions to merge base schema fields into property overrides. When an allOf override specifies only `items` without `type: array`, the base schema's type is now correctly inherited, producing properly typed examples instead of null. + + diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-14.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-14.mdx new file mode 100644 index 000000000..547149eb0 --- /dev/null +++ b/fern/products/cli-api-reference/cli-changelog/2026-05-14.mdx @@ -0,0 +1,65 @@ +## 5.26.4 +**`(fix):`** Fix `missing-redirects` causing `fern check` to exit with code 1 even when +the rule is configured at `warn`. Rule initialization failures now honor +the configured severity (`warn` emits a warning, `error` emits an error) +instead of always being reported as fatal. The `missing-redirects` rule +also degrades to a warning when the local docs navigation fails to +resolve, captures the underlying `failAndThrow` message so the warning +explains *why* (e.g. `Folder not found: ...`) instead of `[object Object]`, +and non-`Error` throws are formatted readably across the validator. + + +## 5.26.3 +**`(fix):`** Fix `fern docs dev` grabbing the local fern token for authentication when loading a global theme + + +## 5.26.2 +**`(fix):`** Fix commit author attribution for GitHub Enterprise: API-created commits now +use the Fern bot identity instead of the PAT-owning user, matching the git CLI +behavior of Fern 3.x generators. + + +**`(fix):`** Authenticate Venus calls during local Docker generation (`fern generate --local`) +by silently picking up an existing `FERN_TOKEN` env var or saved login token, +matching the remote generation path. Previously, `useLocalDocker` skipped the +auth flow entirely, leaving Venus calls (e.g. `GET /organizations/{org_id}`) +unauthenticated. + + +## 5.26.1 +**`(fix):`** Forward `--verify` through the remote (Fiddle) generation path. Previously the +CLI-level `--verify` flag only worked for local generation; on remote runs the +value was silently dropped before reaching `CreateJobRequestV2.verify`. The +flag now plumbs through `runRemoteGenerationForAPIWorkspace` → +`runRemoteGenerationForGenerator` → `createAndStartJob` and is set on the +Fiddle job request, enabling the generator-cli pipeline's VerificationStep +against the language-specific validator on opted-in runs. + + +## 5.26.0 +**`(feat):`** Add `fern docs link check` command to validate links on live documentation sites. +Supports text, JSON, and CSV output formats via `--output` flag. +Use `--url ` to specify which docs site to check, or auto-detect from docs.yml. + + +**`(feat):`** Add progress bars matching `fern docs dev` style for `fern docs link check`. +Broken links show status codes, blocked links show diagnostic details, +and error messages include actionable context. + + +**`(feat):`** The `fern docs link check` command now resolves broken link sources to local file paths when the server provides `sourcePageIds` and a Fern workspace is available. + + +## 5.25.0 +**`(feat):`** Register the new `fernapi/fern-cli` generator in the CLI configuration. + + +## 5.24.2 +**`(fix):`** Fix `fern config migrate` producing wrong file path references in the generated `fern.yml`. Paths from `generators.yml` (relative to the `fern/` directory) are now correctly re-rooted to be relative to the project root where `fern.yml` is created. This also fixes the `docs` `$ref` pointer to use `./fern/docs.yml` instead of `./docs.yml`. + + +## 5.24.1 +**`(chore):`** Propagate Fern `docs:` strings into generated JSON Schemas so editor hovers +work for schemas served from `schema.buildwithfern.dev`. + + diff --git a/fern/products/cli-api-reference/pages/commands.mdx b/fern/products/cli-api-reference/pages/commands.mdx index 642f8251d..b8de8d3ea 100644 --- a/fern/products/cli-api-reference/pages/commands.mdx +++ b/fern/products/cli-api-reference/pages/commands.mdx @@ -29,6 +29,7 @@ hideOnThisPage: true | [`fern docs md check`](#fern-docs-md-check) | Validate MDX syntax in documentation files | | [`fern docs theme export`](#fern-docs-theme-export) | Export theme-eligible fields from `docs.yml` into a standalone directory | | [`fern docs theme upload`](#fern-docs-theme-upload) | Upload a theme to Fern's registry | +| [`fern docs link check`](#fern-docs-link-check) | Check for broken links on a live documentation site | | [`fern docs theme list`](#fern-docs-theme-list) | List all themes for your organization | ## SDK generation commands @@ -276,12 +277,12 @@ hideOnThisPage: true The `--broken-links` and `--strict-broken-links` flags are deprecated. Use the [`broken-links` validation rule](/learn/docs/configuration/site-level-settings#check-configuration) in `docs.yml` instead. - - You can also use the [Fern Dashboard](https://dashboard.buildwithfern.com/) to validate both internal and external links on your live published site. Use `fern check` to validate your API definition and Fern configuration, including [`fern.config.json`](/learn/sdks/overview/project-structure#fernconfigjson), `generators.yml`, and `docs.yml`. It checks for broken links, invalid API examples, configuration errors, and more. When all checks pass, the command produces no output. + Most `fern check` rules — including [`broken-links`](/learn/docs/configuration/site-level-settings#check-configuration) — validate against the navigation tree built from your **local** config and do not crawl your live deployed site or follow external URLs. The exception is the [`missing-redirects` rule](/learn/docs/seo/redirects#catching-missing-redirects), which compares your local navigation against the previously published state and therefore requires `fern login` or `FERN_TOKEN`. + ```bash fern check [--api ] [--warnings] @@ -298,6 +299,10 @@ hideOnThisPage: true missing-redirects: error ``` + + To check links on a published site, use [`fern docs link check`](#fern-docs-link-check) or the link checker in the [Fern Dashboard](https://dashboard.buildwithfern.com/) instead. + + ### api Use `--api ` to specify which API you'd like to check. @@ -464,6 +469,73 @@ hideOnThisPage: true + + + Use `fern docs link check` to scan a live documentation site for broken links. The command crawls the published site, checks every link, and reports broken (404) and blocked (403) URLs along with their source pages. + + + ```bash + fern docs link check [--url ] [--output ] + ``` + + + + Unlike the [`broken-links` rule](#fern-check) in `fern check`, which validates only internal links in your local YAML navigation tree, `fern docs link check` checks all links — internal and external — on your live deployed site. + + + By default, the command auto-detects your docs URL from the `instances` in `docs.yml`. When all links are valid, the command exits with a success message. + + The command first scrapes every page on the site, then checks each link it finds. When broken links are found, the output includes a summary and a grouped list of broken URLs with status codes and source file paths. + + ```plaintext + ◆ Checking links on your-org.docs.buildwithfern.com... + + Scraping pages [████████████████████] 100% | 42/42 + Checking links [████████████████████] 100% | 240/240 + + Finished in 2 minutes, 23 seconds + + Summary + Pages scanned 42 + Links checked 240 + ✓ Working 228 + ✗ Broken 8 (external) + ⚠ Blocked 4 + + ───────────────────────────────────── + + External Broken Links (8) + + ✗ https://example.com/removed-page → 404 + fern/pages/quickstart.mdx + fern/pages/overview.mdx + + ✗ https://example.com/old-endpoint → 404 + fern/pages/integrations.mdx + ``` + + ### url + + Use `--url` to specify which docs site to check. This is useful when you have multiple instances or want to check a preview deployment. + + ```bash + fern docs link check --url https://your-org.docs.buildwithfern.com + ``` + + ### output + + Use `--output` to control the output format. Supported values are `text` (default), `json`, and `csv`. + + ```bash + # JSON output for programmatic use + fern docs link check --output json + + # CSV output for spreadsheets or reporting + fern docs link check --output csv + ``` + + + Use `fern docs md check` to validate MDX syntax across all documentation pages referenced in your navigation configuration, including `docs.yml`, versioned configuration files, and product-specific YAML files. diff --git a/fern/products/cli-generator/authentication.mdx b/fern/products/cli-generator/authentication.mdx new file mode 100644 index 000000000..d0023d808 --- /dev/null +++ b/fern/products/cli-generator/authentication.mdx @@ -0,0 +1,68 @@ +--- +title: Authentication +description: Configure how generated CLIs authenticate with your API using environment variables, CLI flags, files, or fallback chains. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +Each generated CLI reads authentication credentials from the security schemes declared in your OpenAPI spec. Credentials can come from environment variables, CLI flags, files, or a combination of these through fallback chains. + +Without a credential, the CLI still works — you can explore the command tree, view help, and use `--dry-run`. + +## Credential sources + +The CLI supports several ways to supply credentials, configured at build time. + +| Source | Description | +| --- | --- | +| Environment variable | Read from an env var (the most common option). | +| CLI flag | Auto-registered as a `--` global flag. | +| File | Read trimmed contents from a file path (`~` is expanded). | +| Literal | Baked into the binary at compile time. | +| Fallback chain | Try multiple sources in order; first non-empty value wins. | + +A typical fallback chain lets the CLI flag override the env var, which in turn overrides a file: + +```bash +# CLI flag takes priority +box users get-current-user --api-token sk-123 + +# Otherwise falls back to the environment variable +export BOX_API_KEY=sk-123 +box users get-current-user + +# Otherwise reads from a file +echo "sk-123" > ~/.box/token +box users get-current-user +``` + +## Supported auth schemes + +The CLI supports every scheme type that OpenAPI's `securitySchemes` defines: + +| Scheme | How the CLI applies it | +| --- | --- | +| Bearer (`http: bearer`) | Sends `Authorization: Bearer `. | +| API key (`apiKey`) | Sends the key in the configured header (for example, `X-Auth-Token`). | +| Basic (`http: basic`) | Sends `Authorization: Basic `. Each field has its own credential source. | +| OAuth 2 | Treated as bearer — sends `Authorization: Bearer `. | + +## Auth strategies + +When a spec declares multiple security schemes, the CLI composes them according to one of these strategies: + +| Strategy | Behavior | +| --- | --- | +| Auto | Default. Infers the right composition from the spec's `security` blocks. | +| Any | The API accepts any one of the declared schemes. The first scheme with a credential wins. | +| All | The API requires every scheme simultaneously (for example, HMAC signature plus API key). | +| Routing | Per-operation dispatch. Each endpoint's `security` block determines which schemes to use. | + +Operations that declare `security: []` (an empty list) opt out of authentication entirely — no credentials are sent regardless of what's configured. + +## Help output + +Every generated CLI includes a dynamically rendered `Authentication:` section in its `--help` output listing every scheme, the expected env var or flag, and whether a credential is detected. diff --git a/fern/products/cli-generator/cli-generator.yml b/fern/products/cli-generator/cli-generator.yml index 7519597cd..78c95aaeb 100644 --- a/fern/products/cli-generator/cli-generator.yml +++ b/fern/products/cli-generator/cli-generator.yml @@ -4,4 +4,15 @@ navigation: - page: Overview path: ./overview.mdx slug: overview - + - page: Features + path: ./features.mdx + slug: features + - page: Authentication + path: ./authentication.mdx + slug: authentication + - page: OpenAPI extensions + path: ./openapi-extensions.mdx + slug: openapi-extensions + - page: Customization + path: ./customization.mdx + slug: customization diff --git a/fern/products/cli-generator/customization.mdx b/fern/products/cli-generator/customization.mdx new file mode 100644 index 000000000..edc0020b2 --- /dev/null +++ b/fern/products/cli-generator/customization.mdx @@ -0,0 +1,68 @@ +--- +title: Customization +description: Customize generated CLIs with overrides, overlays, multi-spec merging, and custom commands. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +A generated CLI can be customized at three levels: the OpenAPI spec it's built from, the configuration that combines multiple specs into a single command tree, and code that adds custom commands alongside the spec-derived ones. + +## Overrides and overlays + +The CLI generator supports both [overrides](/learn/api-definitions/openapi/overrides) and [overlays](/learn/api-definitions/openapi/overlays) for customizing the OpenAPI spec before the CLI is built. This lets you add Fern extensions, rename parameters, or remove internal endpoints without modifying your original spec. + +Overlays follow the [OpenAPI Overlay Specification](https://spec.openapis.org/overlay/v1.0.0.html) and use JSONPath to target elements: + +```yaml title="overlay.yaml" +overlay: 1.0.0 +info: + title: CLI customizations + version: 1.0.0 +actions: + - target: $.paths['/plants'].get + update: + x-fern-sdk-group-name: plants + x-fern-sdk-method-name: list + - target: $.paths['/internal/debug'] + remove: true +``` + +When both are present, overrides are applied first, then overlays. + +## Multi-spec merging + +A single CLI can combine multiple OpenAPI specs into one command tree. This is useful for APIs that split their spec across domains or versions. + +Specs can be merged flat (all commands at the top level) or under a namespace prefix: + +```rust title="main.rs" +CliApp::new("my-api") + .spec(include_str!("core.yaml")) + .spec_under("billing", include_str!("billing.yaml")) + .run() +``` + +This produces a CLI where core commands live at the top level and billing commands live under a `billing` subcommand: + +```bash +my-api users list # from core.yaml +my-api billing invoices list # from billing.yaml +``` + +When a namespace matches a top-level resource in the incoming spec, the CLI hoists that resource's methods into the namespace to avoid repetition (for example, `billing billing invoices list` becomes `billing invoices list`). + +## Custom commands + +Generated CLIs can include custom commands alongside the spec-derived ones. Custom commands have access to the same API executor, so they can chain multiple API calls into a single workflow. + +```rust title="main.rs" +CliApp::new("my-api") + .spec(include_str!("openapi.yaml")) + .auth_scheme_env("bearerAuth", "MY_API_TOKEN") + .command(whoami_cmd(), whoami_handler) + .run() +``` + diff --git a/fern/products/cli-generator/features.mdx b/fern/products/cli-generator/features.mdx new file mode 100644 index 000000000..f7d770175 --- /dev/null +++ b/fern/products/cli-generator/features.mdx @@ -0,0 +1,146 @@ +--- +title: Features +description: Explore the capabilities of Fern's generated CLIs, including output formatting, pagination, dry-run mode, and TLS configuration. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +Generated CLIs ship with a common set of runtime flags and environment variables: output formatting, pagination, dry-run previewing, TLS and proxy configuration, exit codes, and structured logging. APIs with templated server URLs also expose per-variable flags and environment variables. + +## Output formatting + +Use the `--format` flag to control how responses are displayed. + +| Format | Flag | Description | +| --- | --- | --- | +| JSON | `--format json` | Default. Pretty-printed JSON. | +| Table | `--format table` | Columnar table. Nested objects flatten to `parent.child` column names. | +| YAML | `--format yaml` | YAML representation of the response. | +| CSV | `--format csv` | Comma-separated values, suitable for piping into spreadsheet tools. | + +```bash +# Display plants in a table +contoso plants list --format table + +# Export orders as CSV +contoso orders list --format csv > orders.csv +``` + +## Dry-run mode + +Pass `--dry-run` to validate arguments and preview the HTTP request without sending it. The CLI prints the method, URL, headers, and body it would send, then exits. + +```bash +contoso plants get --params '{"plantId": "abc"}' --dry-run +``` + +## Pagination + +For endpoints annotated with [`x-fern-pagination`](/learn/api-definitions/openapi/extensions/pagination), the CLI auto-paginates when the `--page-all` flag is set. + +| Flag | Description | Default | +| --- | --- | --- | +| `--page-all` | Fetch every page and emit one JSON line per page (NDJSON). | Off | +| `--page-limit ` | Maximum number of pages to fetch. | 10 | +| `--page-delay ` | Delay in milliseconds between page requests. | 100 | + +```bash +# Fetch all plants, one JSON line per page +contoso plants list --page-all + +# Limit to 5 pages with a 200 ms delay +contoso plants list --page-all --page-limit 5 --page-delay 200 +``` + +Paginated output works with all output formats. For table and CSV formats, headers are only emitted on the first page so the output concatenates cleanly. + +## Passing parameters + +| Flag | Purpose | +| --- | --- | +| `--params ` | URL path and query parameters as a JSON object. | +| `--json ` | Request body for POST, PUT, and PATCH methods. | + +```bash +# Path + query parameters +contoso plants get --params '{"plantId": "abc"}' + +# Request body +contoso plants create \ + --json '{"name": "Monstera", "species": "Monstera deliciosa", "sunlight": "indirect"}' +``` + +## Server URL variables + +For APIs with [templated server URLs](/learn/api-definitions/openapi/extensions/server-names-and-url-templating) (such as `https://api.example.com/stores/{store_hash}/v3`), the CLI automatically exposes each template variable as a CLI flag and environment variable. + +```bash +# Pass the variable as a flag +bigcommerce --store-hash abc123 v3 customers list + +# Or set it via an environment variable +export BIGCOMMERCE_STORE_HASH=abc123 +bigcommerce v3 customers list +``` + +## File uploads and downloads + +For endpoints with `format: binary` request bodies, pass a file path as the `--file` argument. For binary responses, use `--output ` to save the response body to a file. + +## Exit codes + +| Code | Meaning | Example cause | +| --- | --- | --- | +| `0` | Success | Command completed normally. | +| `1` | API error | Server returned a 4xx/5xx response. | +| `2` | Auth error | Credentials missing or invalid. | +| `3` | Validation error | Bad arguments, unknown command, or invalid JSON. | +| `4` | Discovery error | Couldn't load API schema. | +| `5` | Internal error | Unexpected failure. | + +All errors are emitted as structured JSON on stderr, making them easy to parse in scripts and CI pipelines. + +## TLS, proxies, and CA bundles + +Every generated CLI honors environment variables for TLS and proxy configuration at runtime. Variables are scoped by binary name — `` is the CLI's binary name uppercased with hyphens mapped to underscores (for example, `CONTOSO`). + +| Variable | Effect | +| --- | --- | +| `_CA_BUNDLE` | Path to a PEM file appended to the default trust roots. | +| `_INSECURE=1` | Disable TLS verification. Logs a warning. Not for production use. | +| `_PROXY` | HTTP/HTTPS proxy URL, overriding `HTTPS_PROXY` / `HTTP_PROXY`. | +| `_NO_PROXY` | Comma-separated proxy bypass list scoped to this CLI. | +| `_TIMEOUT_SECS` | Total request timeout. None by default. | +| `_CONNECT_TIMEOUT_SECS` | Connection-establishment timeout. | + +Standard environment variables (`HTTPS_PROXY`, `HTTP_PROXY`, `NO_PROXY`, `SSL_CERT_FILE`) are honored when the scoped overrides are absent. + + + +**Behind a MITM proxy (Proxyman, Charles, mitmproxy):** + +```bash +export SSL_CERT_FILE=~/path/to/proxyman-ca.pem +export HTTPS_PROXY=http://127.0.0.1:9090 +contoso plants list +``` + +**Corporate network with a custom root CA:** + +```bash +export CONTOSO_CA_BUNDLE=/etc/ssl/corp-roots.pem +contoso plants list +``` + + + +## Structured logging + +Logging is off by default. Set `_LOG` to a [tracing filter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html) to emit structured logs to stderr. Set `_LOG_FILE` to a directory path to write daily rotated JSON log files. + +```bash +CONTOSO_LOG=debug contoso plants list +``` diff --git a/fern/products/cli-generator/openapi-extensions.mdx b/fern/products/cli-generator/openapi-extensions.mdx new file mode 100644 index 000000000..01b516cc4 --- /dev/null +++ b/fern/products/cli-generator/openapi-extensions.mdx @@ -0,0 +1,144 @@ +--- +title: OpenAPI extensions +description: Learn which Fern OpenAPI extensions influence the generated CLI and how they map to commands, flags, and help text. +availability: beta +--- + + +The CLI generator is in early access. [Reach out](https://buildwithfern.com/book-demo?type=cli) to get started. + + +The CLI generator reads several [Fern OpenAPI extensions](/learn/api-definitions/openapi/extensions/overview) to shape the generated CLI. You can add these extensions directly in your spec or apply them through [overlays](/learn/api-definitions/openapi/overlays). + +## Command structure + +### `x-fern-sdk-group-name` + +Determines the subcommand group hierarchy. Each list element becomes a nested subcommand, with names converted from camelCase to kebab-case. + +```yaml title="openapi.yaml" {4-6} +paths: + /scheduled-events/{uuid}/invitees: + get: + x-fern-sdk-group-name: + - scheduledEvents + - invitees + x-fern-sdk-method-name: list-event-invitees +``` + +Produces: `cli scheduled-events invitees list-event-invitees` + +### `x-fern-sdk-method-name` + +Sets the leaf command name (used as-is). + +```yaml title="openapi.yaml" {4} +paths: + /users/me: + get: + x-fern-sdk-method-name: get-current-user +``` + +Produces: `cli get-current-user` (or nested under a group if `x-fern-sdk-group-name` is also set). + + +If neither extension is present, the CLI falls back to the `operationId`. + + +See [SDK method names](/learn/api-definitions/openapi/extensions/method-names) for more details. + +## Filtering + +### `x-fern-ignore` + +Excludes operations or parameters from the generated CLI. An ignored operation produces no command; an ignored parameter produces no flag. + +```yaml title="openapi.yaml" {4} +paths: + /internal/debug: + get: + x-fern-ignore: true +``` + +At the parameter level: + +```yaml title="openapi.yaml" {7} +paths: + /users: + get: + parameters: + - name: internalParam + in: query + x-fern-ignore: true + schema: + type: string +``` + +See [Ignoring elements](/learn/api-definitions/openapi/extensions/ignoring-elements) for more details. + +## Availability badges + +### `x-fern-availability` + +Adds a status badge next to the command in `--help` output. + +| Value | Badge | +| --- | --- | +| `alpha` | `[Alpha]` | +| `beta` | `[Beta]` | +| `preview` | `[Preview]` | +| `generally-available` or `ga` | `[GA]` | +| `deprecated` | `[Deprecated]` | +| `legacy` | `[Legacy]` | + +```yaml title="openapi.yaml" {4} +paths: + /v2/reports: + get: + x-fern-availability: beta +``` + +OpenAPI's standard `deprecated: true` is also honored and maps to `[Deprecated]` when `x-fern-availability` isn't set. + +See [Availability](/learn/api-definitions/openapi/extensions/availability) for more details. + +## Parameter naming + +### `x-fern-parameter-name` + +Overrides the CLI flag name derived from a parameter. By default, parameter names are converted to kebab-case for use as flags. + +```yaml title="openapi.yaml" {9} +paths: + /users: + get: + parameters: + - name: X-API-Version + in: header + schema: + type: string + x-fern-parameter-name: api-version +``` + +Produces `--api-version` instead of `--x-api-version`. + +See [Customize parameter names](/learn/api-definitions/openapi/extensions/parameter-names) for more details. + +## Pagination + +### `x-fern-pagination` + +Enables auto-pagination for an endpoint. When present, the CLI recognizes `--page-all`, `--page-limit`, and `--page-delay` flags for that command. + +```yaml title="openapi.yaml" {5-8} +paths: + /plants: + get: + operationId: list_plants + x-fern-pagination: + cursor: $request.cursor + next_cursor: $response.next + results: $response.results +``` + +See [Pagination](/learn/api-definitions/openapi/extensions/pagination) for all supported pagination schemes (offset, cursor, URI, and path). diff --git a/fern/products/cli-generator/overview.mdx b/fern/products/cli-generator/overview.mdx index c78e4ede6..763595728 100644 --- a/fern/products/cli-generator/overview.mdx +++ b/fern/products/cli-generator/overview.mdx @@ -25,6 +25,10 @@ Building a CLI by hand is a multi-quarter project — commands, auth, pagination ## How it works + +Generate a CLI from an OpenAPI spec or a GraphQL introspection schema. + + The CLI generator plugs into the same Fern workflow as your Docs and SDKs. When your spec changes, Fern opens a PR against your CLI repo with the generated source. On release, Fern automatically publishes the CLI to npm, Homebrew, and GitHub Releases so your users can install it with their package manager of choice. The CLI stays in sync with your Docs and SDKs, and you never need to write CLI code by hand. The output is a single statically linked Rust binary. Users drop it onto their PATH and run it. There's no language runtime and no dependencies. diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index 77e194548..e9ad34d01 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -509,6 +509,8 @@ navigation: hidden: true - website: hidden: true + - scribeWebhooks: + hidden: true # must be included to use the schema component - api: API reference api-name: docs-yml diff --git a/fern/products/docs/pages/ai/fern-writer.mp4 b/fern/products/docs/pages/ai/fern-writer.mp4 index cbc7afc6c..7db9f3f71 100644 Binary files a/fern/products/docs/pages/ai/fern-writer.mp4 and b/fern/products/docs/pages/ai/fern-writer.mp4 differ diff --git a/fern/products/docs/pages/ai/writer-open-pr.png b/fern/products/docs/pages/ai/writer-open-pr.png index d44644ea1..a1b94c265 100644 Binary files a/fern/products/docs/pages/ai/writer-open-pr.png and b/fern/products/docs/pages/ai/writer-open-pr.png differ diff --git a/fern/products/docs/pages/ai/writer-slack.png b/fern/products/docs/pages/ai/writer-slack.png deleted file mode 100644 index f56b83f31..000000000 Binary files a/fern/products/docs/pages/ai/writer-slack.png and /dev/null differ diff --git a/fern/products/docs/pages/ai/writer.mdx b/fern/products/docs/pages/ai/writer.mdx index 07f8595ca..79c4ce423 100644 --- a/fern/products/docs/pages/ai/writer.mdx +++ b/fern/products/docs/pages/ai/writer.mdx @@ -6,11 +6,15 @@ description: A Slack-based technical writing agent that updates your documentati Fern Writer is a Slack-based technical writing agent that keeps your docs aligned as your product evolves. It's powered by [Devin from Cognition](https://cognition.ai/blog/introducing-devin). Fern Writer understands Fern components and your writing style, and can be customized via an `AGENTS.md` file in your docs repository. - - Fern Writer in Slack + + ## How it works @@ -19,34 +23,8 @@ Fern Writer is a Slack-based technical writing agent that keeps your docs aligne In Slack channels where you've added Fern Writer, tag `@Fern Writer` and describe the change you need. Fern Writer [only responds when directly tagged](#privacy-and-data-handling). It will react to your message to confirm receipt, then create a pull request and reply with a link. - - Fern Writer opening a PR - - Fern Writer supports image and file attachments for additional context. When tagged in an existing thread, it reads the full conversation to understand context before responding. -| Use case | Sample request | -|----------|----------------| -| Document a new feature from a pull request | `@Fern Writer document the new rate limiting feature added in PR #123` | -| Add new content to existing pages | `@Fern Writer add a section about webhook retry behavior to the webhooks guide` | -| Reorganize and consolidate content | `@Fern Writer merge the authentication and authorization pages, and add a redirect from the old auth page` | -| Fix errors and improve clarity | `@Fern Writer fix the broken code example in the quickstart and update the package version to v2.1.0` | - - - - - ### Reviewing and merging Request changes by commenting in the Slack thread. Once the PR meets your requirements, merge it like any other pull request. @@ -62,6 +40,30 @@ Request changes by commenting in the Slack thread. Once the PR meets your requir Each pull request includes a **Requested by** field in the description, attributing the change to the person or team that initiated the request. Commits are signed and attributed to `fern-support`, ensuring that automated changes are clearly distinguishable from manual contributions in your repository's history. +## Example requests + + +@Fern Writer document the new rate limiting feature added in PR #123 + + +
+ + +@Fern Writer add a section about webhook retry behavior to the webhooks guide + + +
+ + +@Fern Writer merge the authentication and authorization pages, and add a redirect from the old auth page + + +
+ + +@Fern Writer fix the broken code example in the quickstart and update the package version to v2.1.0 + + ## Setup diff --git a/fern/products/docs/pages/api-references/library-docs.mdx b/fern/products/docs/pages/api-references/library-docs.mdx index e00a59ce9..5396750d7 100644 --- a/fern/products/docs/pages/api-references/library-docs.mdx +++ b/fern/products/docs/pages/api-references/library-docs.mdx @@ -4,7 +4,9 @@ description: Generate MDX documentation pages from your Python or C++ library so --- -The library docs generator parses your **Python or C++** library source code and generates MDX documentation pages for modules, classes, functions, methods, and parameters. Generated pages include cross-reference links and hierarchical navigation, and are integrated directly into your Fern Docs site. +The library docs generator parses your **Python or C++** library source code and generates MDX documentation pages for modules, classes, functions, methods, and parameters. Generated pages are added to your Fern Docs site with hierarchical navigation. + +Cross-links are automatic. When a fully-qualified identifier appears in a code block — for example, in a class signature or type annotation — the generator links it to the page documenting that symbol, so readers can jump straight to the definition. ## Configuration diff --git a/fern/products/docs/pages/changelog/2026-05-14.mdx b/fern/products/docs/pages/changelog/2026-05-14.mdx new file mode 100644 index 000000000..65c76969c --- /dev/null +++ b/fern/products/docs/pages/changelog/2026-05-14.mdx @@ -0,0 +1,16 @@ +--- +tags: ["configuration"] +--- + +## CLI link checker + +You can now check for broken links on your live documentation site directly from the Fern CLI with `fern docs link check`. The command scrapes every page on your published site, checks all internal and external links, and reports broken (404) and blocked (403) URLs along with the source pages where they appear. + +```bash +fern docs link check --url https://buildwithfern.com/learn +fern docs link check --url https://elevenlabs.io/docs +``` + +This complements the existing [`broken-links` rule](/learn/docs/configuration/site-level-settings#check-configuration) in `fern check`, which validates internal links against your local YAML navigation tree. Use `fern docs link check` after publishing to catch live 404s and broken external URLs that local validation can't detect. + + diff --git a/fern/products/docs/pages/component-library/default-components/runnable-endpoint.mdx b/fern/products/docs/pages/component-library/default-components/runnable-endpoint.mdx index 57f7540ab..f3d4e5efc 100644 --- a/fern/products/docs/pages/component-library/default-components/runnable-endpoint.mdx +++ b/fern/products/docs/pages/component-library/default-components/runnable-endpoint.mdx @@ -4,26 +4,31 @@ description: Add testable API endpoints to your docs with RunnableEndpoint. Supp --- -The `` component lets users make real HTTP requests to your APIs directly in the API Reference. It auto-detects endpoint definitions from your API specification and provides a request builder with inputs for headers, path parameters, query parameters, and request bodies. +The `` component lets users make real HTTP requests to your APIs directly from your documentation. It auto-detects the endpoint definition from your API specification, renders a request builder for headers, path parameters, query parameters, and request bodies, and displays the response status, headers, body, and timing inline. Form inputs persist in local storage across page reloads. ## Usage
- ![Runnable Endpoint component example](runnable-endpoint.png) +
```jsx Markdown - + ``` -## Features +## Variants -The component supports: -- **Multiple examples** – When your endpoint has multiple pre-configured examples, the component displays a dropdown selector in the header so users can switch between different examples -- **Multiple environments** – If your API defines multiple environments (production, staging, development), the component automatically displays an environment selector so users can test against different base URLs -- **API Reference integration** – Each `` includes a button that links users to the full API Reference documentation for the endpoint -- **Real-time response preview** – Users can view response status, headers, body, and response time immediately after sending requests -- **Form persistence** – Form inputs are automatically persisted in the browser's local storage, so users' test data is preserved even when navigating between pages or refreshing the browser +### Collapse by default + +Use `collapsed` to render the component with the form section hidden. Users can expand it by clicking the component. + +
+ +
+ +```jsx Markdown + +``` ## Properties diff --git a/fern/products/docs/pages/component-library/default-components/webhook-payload-snippet.mdx b/fern/products/docs/pages/component-library/default-components/webhook-payload-snippet.mdx index ad8f9004c..a197f2546 100644 --- a/fern/products/docs/pages/component-library/default-components/webhook-payload-snippet.mdx +++ b/fern/products/docs/pages/component-library/default-components/webhook-payload-snippet.mdx @@ -4,16 +4,26 @@ description: Reference a webhook payload from your API Reference to display exam --- -Use the `` component to reference a webhook payload from your API Reference. +The `` component displays a webhook's request payload schema from your API Reference. It renders the same fields, types, and example values that appear on the webhook's full API Reference page, so readers can inspect the payload inline alongside your prose. + +To display the schema for a regular HTTP endpoint, use the [``](/learn/docs/writing-content/components/endpoint-schema-snippet) component. ## Usage +Reference a webhook by its `operationId`. + +
+
+ +
+
+ ```jsx Markdown - + ``` ## Properties - The operation ID of the webhook to display. + The `operationId` of the webhook to display. If your API uses [namespaces](/learn/api-definitions/overview/project-structure#combined-sdks-from-multiple-apis), prefix with the namespace and `::` (e.g., `payments::on-payment-succeeded`). diff --git a/fern/products/docs/pages/component-library/writing-content/markdown-basics.mdx b/fern/products/docs/pages/component-library/writing-content/markdown-basics.mdx index bd867092d..287cd765d 100644 --- a/fern/products/docs/pages/component-library/writing-content/markdown-basics.mdx +++ b/fern/products/docs/pages/component-library/writing-content/markdown-basics.mdx @@ -55,14 +55,34 @@ Because the `

` is generated automatically, you should begin your page conten ## Links in Markdown ### Link format -Use a `/` character to begin a relative URL to another page on your docs site. This routes to the `url` defined in your `docs.yml` file, such as `example-docs.buildwithfern.com`. For example, if you want to link to `https://example-docs.buildwithfern.com/overview/introduction`, you can write the link in Markdown as follows: - -```mdx -Read the [Introduction](/learn/sdks/overview/introduction). +To link to another page on your docs site, write the destination's **published site path**, starting with a `/`. Fern builds this path from the slugs in your [`docs.yml` and product YAML files](/learn/docs/configuration/navigation), not from the file's location on disk. To link to a heading on another page, append `#anchor` to the path. + + + File-relative paths like `./` and `../` aren't supported for inter-page links — use the published site path instead. (File-relative paths are still correct for [images and other media](/learn/docs/writing-content/markdown-media) and for `path:` references inside YAML config.) + + + +```mdx wordWrap +Learn about [how Fern SDKs work](/learn/sdks/overview/how-it-works). + +Configure [sidebar icons](/learn/docs/configuration/navigation#sidebar-icons) to add visual cues to your navigation. ``` +In [versioned docs](/learn/docs/configuration/versions), the same path lands on a different version depending on whether you write the unversioned form (default version) or the versioned form (e.g. `/learn/docs/v2/getting-started`). For inline version-specific content within a single page, use [``](/learn/docs/writing-content/components/if#by-version) or [``](/learn/docs/writing-content/components/versions). + +### Validating links + +Fern provides two ways to catch broken links. The [`broken-links` rule](/learn/docs/configuration/site-level-settings#check-configuration) — run by [`fern check`](/learn/cli-api-reference/cli-reference/commands#fern-check), including during `fern docs dev` — validates each internal link against the navigation tree built from your **local** YAML. To check links on a published site, use [`fern docs link check`](/learn/cli-api-reference/cli-reference/commands#fern-docs-link-check) or the [Fern Dashboard](https://dashboard.buildwithfern.com/). + +| | `fern check` broken-links rule | `fern docs link check` | +|---|---|---| +| What it checks | Internal links in your **local** YAML navigation tree | All links on your **live deployed** site | +| External links | Not checked | Checked | +| Requires a published site | No | Yes | +| When to use | In CI, before publishing | After publishing, to catch live 404s and broken external URLs | + ### API link syntax diff --git a/fern/products/docs/pages/getting-started/quickstart.mdx b/fern/products/docs/pages/getting-started/quickstart.mdx index e561f6669..bfb06c9b6 100644 --- a/fern/products/docs/pages/getting-started/quickstart.mdx +++ b/fern/products/docs/pages/getting-started/quickstart.mdx @@ -37,7 +37,7 @@ This guide covers the CLI path. A browser-based guided setup also exists at http - All the configuration for your docs lives in the `fern` folder. Create a fern folder by either using the [starter template](https://github.com/fern-api/docs-starter) or starting from scratch + All the configuration for your docs lives in the `fern` folder. Create a fern folder by either using the [starter template](https://github.com/fern-api/docs-starter) or starting from scratch. Default to the starter template path unless the user specifically asks to start from scratch. The template includes sample pages, an OpenAPI spec, a changelog, and a GitHub Actions workflow — it's much faster to delete what you don't need than to build from nothing. @@ -147,7 +147,7 @@ This guide covers the CLI path. A browser-based guided setup also exists at http - Now that you have a basic docs site, you can customize it by adding tutorials, generating an API Reference, or finetuning the branding. (Or skip ahead to [preview](#preview-your-docs) and [publish](#publish-to-production).) + Now that you have a basic docs site, you can customize it by adding tutorials, generating an API Reference, or fine-tuning the branding. (Or skip ahead to [preview](#preview-your-docs) and [publish](#publish-to-production).) diff --git a/fern/products/docs/pages/preview-publish/preview-changes-locally.mdx b/fern/products/docs/pages/preview-publish/preview-changes-locally.mdx index 666289bf5..cb6d58255 100644 --- a/fern/products/docs/pages/preview-publish/preview-changes-locally.mdx +++ b/fern/products/docs/pages/preview-publish/preview-changes-locally.mdx @@ -13,6 +13,7 @@ Fern offers two ways to preview documentation changes: Install the following: - Node.js version 22 or higher - [The Fern CLI](/learn/cli-api-reference/cli-reference/overview#install-fern-cli) +- [pnpm](https://pnpm.io/installation), available on your `PATH`. `fern docs dev` uses pnpm internally to install the dependencies it needs to render your preview (for example, `esbuild`), so it must be installed globally even if your project uses npm or yarn. ## Local development @@ -55,6 +56,12 @@ Some features are disabled in local development: `fern docs dev` and `fern generate --docs` must be run from a directory that contains a [`fern/` folder](/learn/docs/getting-started/project-structure) with a `docs.yml` inside. Change into your project directory, or add a `docs.yml`. +#### Failed to install required package due to error: Command failed with exit code 1: pnpm i esbuild + +`fern docs dev` shells out to pnpm to install the dependencies it needs to render your preview. Install [pnpm](https://pnpm.io/installation) globally and make sure it's on your `PATH`, then rerun `fern docs dev`. Your project's package manager (npm, yarn, etc.) doesn't need to change. + +If the same command also prints `[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild`, run `pnpm approve-builds` and approve `esbuild` so pnpm allows its post-install scripts to run. + #### Broken link to /some/path (resolved path: ...) `fern check` reports this when a link in a Markdown page doesn't resolve to a real page, anchor, or file in your docs. diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-09.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-09.mdx new file mode 100644 index 000000000..c28eea12a --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-09.mdx @@ -0,0 +1,47 @@ +### v0.114.44 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.44 +``` + +Digest: `sha256:1af81539eb27cd3c8f5e049581ca48f49388dbbee5a87bdafc30dd3ea8096d6e` + +### v0.114.44 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.44 +``` + +Digest: `sha256:1af81539eb27cd3c8f5e049581ca48f49388dbbee5a87bdafc30dd3ea8096d6e` + +### v0.114.45 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.45 +``` + +Digest: `sha256:402c90cc3b4f043b461a840901f192e1a71ffb06b573e2760b1aa5a5ebff8292` + +### v0.114.45 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.45 +``` + +Digest: `sha256:402c90cc3b4f043b461a840901f192e1a71ffb06b573e2760b1aa5a5ebff8292` + +### v0.114.46 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.46 +``` + +Digest: `sha256:c7aa2e5b00f764469d5310beca727cf29a21694f831bdbb6c34aa9472c44c295` + +### v0.114.46 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.46 +``` + +Digest: `sha256:c7aa2e5b00f764469d5310beca727cf29a21694f831bdbb6c34aa9472c44c295` diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-11.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-11.mdx new file mode 100644 index 000000000..b8afb05e0 --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-11.mdx @@ -0,0 +1,7 @@ +### v0.114.47 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.47 +``` + +Digest: `sha256:23b4cb7e2dc2ccf93a10f1e1ab69247c74b01df4bae211c2268d077cc94922c8` diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-12.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-12.mdx new file mode 100644 index 000000000..d7e1e3d3b --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-12.mdx @@ -0,0 +1,23 @@ +### v0.114.48 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.48 +``` + +Digest: `sha256:46ff081497e53f7fd574fb9cc2b3463761ef4214430246b82d4587f206020079` + +### v0.114.49 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.49 +``` + +Digest: `sha256:392c78851ff5c6964b6973ebf4e8042b52f3e6d7e2404ed36badd00c4fa9e8d0` + +### v0.114.50 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.50 +``` + +Digest: `sha256:8b204fd8cf4a0b47feb6143c7f32859eb81f5a602288d2f087b9d75c6c38718f` diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-13.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-13.mdx new file mode 100644 index 000000000..7c6aa167b --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-13.mdx @@ -0,0 +1,47 @@ +### v0.114.51 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.51 +``` + +Digest: `sha256:0ad7cc2415feaf64340c1321e189c8a7d5a8eaec8f46f94660da74eb9a66fb9a` + +### v0.114.52 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.52 +``` + +Digest: `sha256:eebf6d94b0c7ab6a93c5b303b6489c475a68478893a2457b921dd71d8214c7c4` + +### v0.114.53 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.53 +``` + +Digest: `sha256:9dd10b58913dd82ee3f8cd545b0e7053fe4d5262a42a57190c0afd7cf207c23b` + +### v0.114.54 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.54 +``` + +Digest: `sha256:838ca98a9e6cff98170b5b542ae500d39db06685e5708ee3c1d7e5e3952c3947` + +### v0.114.55 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.55 +``` + +Digest: `sha256:90d4219f24073671c72f05743bd2bfc81c6bf58e09ba3f0bd0e10d46fe600e5c` + +### v0.114.56 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.56 +``` + +Digest: `sha256:7d7226e3bf3311add1733cf2ca820873bb31e90e6d8d754a1b3700464e31b7c1` diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-14.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-14.mdx new file mode 100644 index 000000000..420969fef --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-14.mdx @@ -0,0 +1,31 @@ +### v0.114.57 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.57 +``` + +Digest: `sha256:1b12391e3e70cd667ca4b51f0c115148d48755fab826291e625c4281e643db95` + +### v0.114.58 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.58 +``` + +Digest: `sha256:66cec7597c36fb2992ed2df7e5f71eadb76f5bd0447ad38f483b08c4d97d285b` + +### v0.114.59 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.59 +``` + +Digest: `sha256:06893b60da76937184e06dd0f6fa7c94432fc02a876814bad4f8d35ccd505999` + +### v0.114.60 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.60 +``` + +Digest: `sha256:a1d66fe7456d0f970bc7b5155474bbe0c2cd6b3d2055624524859a6c36833b77` diff --git a/fern/products/docs/pages/self-hosted/changelog/2026-05-15.mdx b/fern/products/docs/pages/self-hosted/changelog/2026-05-15.mdx new file mode 100644 index 000000000..ec3af1e97 --- /dev/null +++ b/fern/products/docs/pages/self-hosted/changelog/2026-05-15.mdx @@ -0,0 +1,31 @@ +### v0.114.61 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.61 +``` + +Digest: `sha256:916c4eccaa6916ca2c97e6322e8be3a5b045c2eb41f7462faeff4d79f92da972` + +### v0.114.62 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.62 +``` + +Digest: `sha256:e27dd7f81899833c32887ed83ab8cf6c54f2cf4bfdc25543d756da3a7f57c967` + +### v0.114.63 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.63 +``` + +Digest: `sha256:c40bc0a5632e05e2ccde7dd3e1a1674bc0d09fda2c2aef7d2211eeae50388ae6` + +### v0.114.64 + +```dockerfile +FROM fernenterprise/fern-self-hosted:0.114.64 +``` + +Digest: `sha256:8081f73e1e5c17ea24c145d4fa45d15384f20cbe002e27f67ac18f3552cf0e10` diff --git a/fern/products/docs/pages/seo/redirects.mdx b/fern/products/docs/pages/seo/redirects.mdx index f0e84985b..d1d21cb0b 100644 --- a/fern/products/docs/pages/seo/redirects.mdx +++ b/fern/products/docs/pages/seo/redirects.mdx @@ -14,7 +14,9 @@ subtitle: Learn how to configure redirects in Fern Docs. Set up exact path redir ## Catching missing redirects -You can use [`fern check`](/learn/cli-api-reference/cli-reference/commands#fern-check) to automatically detect pages that were removed or moved without a redirect. Configure the [`missing-redirects` rule](/learn/docs/configuration/site-level-settings#check-configuration) in `docs.yml` to control its severity. +The [`missing-redirects` rule](/learn/docs/configuration/site-level-settings#check-configuration), run by [`fern check`](/learn/cli-api-reference/cli-reference/commands#fern-check), compares the navigation tree built from your local YAML against the most recently **published** state of your site and flags previously-published URLs that no longer resolve and aren't covered by an entry in `redirects:`. This catches pages you've moved or removed before they start returning 404s for existing inbound links. + +Tune severity with the [`missing-redirects` rule](/learn/docs/configuration/site-level-settings#check-configuration) in `docs.yml`. ## Common errors diff --git a/fern/products/docs/snippets/redirects.mdx b/fern/products/docs/snippets/redirects.mdx index 88049b8d0..55032b68f 100644 --- a/fern/products/docs/snippets/redirects.mdx +++ b/fern/products/docs/snippets/redirects.mdx @@ -66,14 +66,14 @@ settings: -If you have [versions](/docs/configuration/versions) configured, your default version uses unversioned paths (`/docs/getting-started`), while other versions use versioned paths (`/docs/getting-started/v2`). Fern automatically handles version routing by redirecting broken versioned links to the default version and managing canonical URLs. +If you have [versions](/docs/configuration/versions) configured, your default version uses unversioned paths (`/docs/getting-started`), while other versions use versioned paths (`/docs/v2/getting-started`). Fern automatically handles version routing by redirecting broken versioned links to the default version and managing canonical URLs. Avoid redirecting from unversioned to versioned URLs: ```yaml title="docs.yml" redirects: - source: /docs/event-notifications - destination: /docs/event-notifications/v2 # Don't do this + destination: /docs/v2/event-notifications # Don't do this ``` Manually overriding the default versioning behavior can lead to unexpected redirect patterns. diff --git a/fern/products/sdks/deep-dives/generated-sdk.mdx b/fern/products/sdks/deep-dives/generated-sdk.mdx index c358a494c..edeb02507 100644 --- a/fern/products/sdks/deep-dives/generated-sdk.mdx +++ b/fern/products/sdks/deep-dives/generated-sdk.mdx @@ -57,7 +57,7 @@ Your SDK users can configure individual requests using language-specific options | Option | Description | Availability | |--------|-------------|--------------| -| Timeouts | Configure request timeouts (default: 30 seconds for C# and PHP, 60 seconds for all other languages) | All languages | +| Timeouts | Configure request timeouts (default: 30 seconds for [C#](/learn/sdks/generators/csharp/configuration#default-timeout-in-seconds) and PHP, 60 seconds for all other languages) | All languages | | [Retries](/sdks/deep-dives/retries-with-backoff) | Configure maximum retries (default: 2 with exponential backoff for 408, 429, and 5xx responses) | All languages except Ruby and Swift | | Custom HTTP client | Override the default HTTP client for unsupported environments or custom requirements | TypeScript, Python, Java, PHP, and Swift | | [aiohttp transport](/learn/sdks/generators/python/aiohttp-support) | Opt into `aiohttp` as the async HTTP transport to resolve DNS concurrency bottlenecks | Python only | diff --git a/fern/products/sdks/generators/csharp/changelog/2026-05-11.mdx b/fern/products/sdks/generators/csharp/changelog/2026-05-11.mdx new file mode 100644 index 000000000..21cd34dde --- /dev/null +++ b/fern/products/sdks/generators/csharp/changelog/2026-05-11.mdx @@ -0,0 +1,12 @@ +## 2.66.1 +**`(chore):`** Bump the C# SDK and C# model generator containers' Node base image from +`node:22.22-alpine3.23` to `node:24.15-alpine3.23`. Aligns the generators +with the rest of the Fern generator containers on a single Node major +version (Node 24) and picks up Node 24's CVE patches. The bundled npm +11.12.1 in `node:24.15` already ships patched `brace-expansion@5.0.4`, so +the C# SDK's `brace-expansion 2.0.3` replacement step is removed. The +`ip-address` and `picomatch` patches are retained because the bundled +versions in `node:24.15` (10.1.0 and 4.0.3 respectively) are still +vulnerable. + + diff --git a/fern/products/sdks/generators/csharp/changelog/2026-05-12.mdx b/fern/products/sdks/generators/csharp/changelog/2026-05-12.mdx new file mode 100644 index 000000000..286a59eb8 --- /dev/null +++ b/fern/products/sdks/generators/csharp/changelog/2026-05-12.mdx @@ -0,0 +1,11 @@ +## 2.66.2 +**`(chore):`** Patch C# SDK generator container CVEs flagged in the AWS ECR / grype scan. +Switch the apk upgrade to pick up the latest Alpine 3.23 patches (nghttp2, +openssl, libcrypto, libssl, sqlite-libs, expat, etc.), pin a non-vulnerable +set of `System.*` NuGet dependencies, drop the bundled PowerShell warmup +so its vendored `System.Net.Http 4.3.0` / `System.Security.Cryptography.Xml` +DLLs are no longer included in the published image, and clear the +`System.Net.Http 4.3.0` artifact the `/dependencies.csproj` warmup leaves +in the NuGet cache after restore. + + diff --git a/fern/products/sdks/generators/csharp/changelog/2026-05-13.mdx b/fern/products/sdks/generators/csharp/changelog/2026-05-13.mdx new file mode 100644 index 000000000..0f560037a --- /dev/null +++ b/fern/products/sdks/generators/csharp/changelog/2026-05-13.mdx @@ -0,0 +1,5 @@ +## 2.66.3 +**`(fix):`** Bump WireMock.Net from 2.2.0 to 2.6.0 in generated test projects to resolve Snyk +vulnerability reports flagging the older version. + + diff --git a/fern/products/sdks/generators/csharp/configuration.mdx b/fern/products/sdks/generators/csharp/configuration.mdx index 4343ea434..172f16836 100644 --- a/fern/products/sdks/generators/csharp/configuration.mdx +++ b/fern/products/sdks/generators/csharp/configuration.mdx @@ -32,6 +32,10 @@ Sets the name of the generated API client class. This determines the primary cli Customizes the name of the pagination helper class used for handling paginated API responses. This allows you to specify a custom name that fits your naming conventions. + +The default timeout for network requests, in seconds. Set to `infinity` to disable the default timeout. SDK users can still [override this per request](/learn/sdks/deep-dives/sdk-user-features#customization-options) by passing `RequestOptions.Timeout`. + + When enabled, generates enum types that can handle unknown values. This allows the SDK to process new enum values that may be added to the API without breaking existing client code, improving forward compatibility. diff --git a/fern/products/sdks/generators/go/changelog/2026-05-11.mdx b/fern/products/sdks/generators/go/changelog/2026-05-11.mdx new file mode 100644 index 000000000..cfbab0d6b --- /dev/null +++ b/fern/products/sdks/generators/go/changelog/2026-05-11.mdx @@ -0,0 +1,16 @@ +## 1.41.0 +**`(feat):`** Add a `WithFunc` option for bearer auth that accepts a `func() (string, error)` callable. +The callable is evaluated at request time when no static token is set, matching the callable +auth behavior available in the Python and TypeScript SDK generators. + + +## 1.40.4 +**`(chore):`** Bump the Go SDK and Go model generator containers' Node base image from +`node:22.22-alpine3.23` to `node:24.15-alpine3.23`. Aligns the generators +with the rest of the Fern generator containers on a single Node major +version (Node 24) and picks up Node 24's CVE patches. The existing +`npm pack @latest` loop that swaps in patched `ip-address`, +`brace-expansion`, and `picomatch` is retained because `npm pack @latest` +continues to resolve the same fixed releases on Node 24. + + diff --git a/fern/products/sdks/generators/go/changelog/2026-05-12.mdx b/fern/products/sdks/generators/go/changelog/2026-05-12.mdx new file mode 100644 index 000000000..f30629b61 --- /dev/null +++ b/fern/products/sdks/generators/go/changelog/2026-05-12.mdx @@ -0,0 +1,13 @@ +## 1.41.1 +**`(chore):`** Patch Go SDK + Go model generator container CVEs flagged in the AWS ECR / +grype scan. Bump the Go base image to `golang:1.26.3-alpine3.23`, refresh +`apk upgrade`, and patch npm's bundled `picomatch@4.0.3 -> 4.0.4` and +`brace-expansion@5.0.4 -> 5.0.5` via tarball replacement so the published +image no longer ships the vulnerable bundled JS dependencies that grype +flags. Also drop the `internal/testdata/**` test fixtures and clear the +`/go/pkg/mod` + `/root/.cache/go-build` build caches from the runtime +image so grype no longer scans them as a source of stale `yaml.v3` and +`golang.org/x/net` pseudo-versions that are not actually linked into +`/fern-go-sdk`. + + diff --git a/fern/products/sdks/generators/go/changelog/2026-05-13.mdx b/fern/products/sdks/generators/go/changelog/2026-05-13.mdx new file mode 100644 index 000000000..873ddb5e6 --- /dev/null +++ b/fern/products/sdks/generators/go/changelog/2026-05-13.mdx @@ -0,0 +1,8 @@ +## 1.41.2 +**`(fix):`** Stop launching WireMock with `--global-response-templating` in generated +wire-test `docker-compose.test.yml`. Response examples containing literal +`{{...}}` are now served verbatim instead of being passed through +WireMock's Handlebars transformer, which would fail to resolve them as +helpers and return 500. + + diff --git a/fern/products/sdks/generators/go/changelog/2026-05-14.mdx b/fern/products/sdks/generators/go/changelog/2026-05-14.mdx new file mode 100644 index 000000000..67adc2ce2 --- /dev/null +++ b/fern/products/sdks/generators/go/changelog/2026-05-14.mdx @@ -0,0 +1,11 @@ +## 1.41.3 +**`(chore):`** Patch `/usr/local/go/src/go.mod`, `vendor/modules.txt`, and `go.sum` in +the go-sdk + go-model containers so they declare `golang.org/x/net +v0.53.0`. Go 1.26.3 already ships the CVE-2026-33814 fix in its bundled +`h2_bundle.go` (the HTTP/2 SETTINGS_MAX_FRAME_SIZE validation moved to +the top of `ForeachSetting`), but the stdlib SBOM still pins the +pre-fix x/net pseudo-version `v0.47.1-0.20260417*`. Bumping the SBOM +metadata to v0.53.0 makes grype reflect the patched code instead of +flagging the toolchain as vulnerable. + + diff --git a/fern/products/sdks/generators/java/changelog/2026-05-11.mdx b/fern/products/sdks/generators/java/changelog/2026-05-11.mdx new file mode 100644 index 000000000..1aef556aa --- /dev/null +++ b/fern/products/sdks/generators/java/changelog/2026-05-11.mdx @@ -0,0 +1,16 @@ +## 4.8.5 +**`(chore):`** Bump the Java SDK generator container's Node base image from +`node:24.14.1-bookworm` to `node:24.15-trixie`. Aligns the generator +with the rest of the Fern generator containers on a single Node patch +minor (floating `24.15`) and a single Debian release (trixie). Trixie ships +patched versions of glibc, dpkg, nghttp2, libcap2, systemd, libgcrypt20, +krb5, curl, and expat that are not available on bookworm, clearing the +AWS Inspector findings that dist-upgrade alone could not. The non-slim +variant is intentional because the Node-stage patch steps shell out to +`curl` and `tar`. The bundled npm 11.12.1 in `node:24.15` already ships +patched `glob@13.0.6`, `minimatch@10.2.4`, `tar@7.5.11`, and +`brace-expansion@5.0.4`, so those tarball-replacement patch steps are +removed. The `ip-address` and `picomatch` patches are retained because the +bundled versions (10.1.0 and 4.0.3 respectively) are still vulnerable. + + diff --git a/fern/products/sdks/generators/java/changelog/2026-05-12.mdx b/fern/products/sdks/generators/java/changelog/2026-05-12.mdx new file mode 100644 index 000000000..fecb28fbe --- /dev/null +++ b/fern/products/sdks/generators/java/changelog/2026-05-12.mdx @@ -0,0 +1,17 @@ +## 4.8.7 +**`(fix):`** Fix undiscriminated union deserialization when one member has all-optional fields. +Previously, an all-optional object variant (e.g. `PayMethodCloud`) could greedily +consume a payload intended for a more specific variant with required fields (e.g. +`Check` requiring `achHolder`), because Jackson's `@JsonIgnoreProperties(ignoreUnknown=true)` +silently accepts any JSON object when all fields are optional. The deserializer now +emits guarded members (those with at least one required field) before unguarded +(all-optional) members, ensuring the more specific match wins. + + +## 4.8.6 +**`(chore):`** Patch Java SDK generator container CVEs flagged in the AWS ECR / grype +scan. Patch npm's bundled `brace-expansion@5.0.4 -> 5.0.5` (GHSA-f886-m6hf-6m8v) +via tarball replacement so the published image no longer ships the vulnerable +bundled JS dependency that grype flags on `dev/java-sdk-generator`. + + diff --git a/fern/products/sdks/generators/php/changelog/2026-05-11.mdx b/fern/products/sdks/generators/php/changelog/2026-05-11.mdx new file mode 100644 index 000000000..2f962dd19 --- /dev/null +++ b/fern/products/sdks/generators/php/changelog/2026-05-11.mdx @@ -0,0 +1,7 @@ +## 2.9.4 +**`(chore):`** Bump the PHP SDK and PHP model generator containers' Node base image from +`node:22.22-alpine3.23` to `node:24.15-alpine3.23`. Aligns the generators +with the rest of the Fern generator containers on a single Node major +version (Node 24) and picks up Node 24's CVE patches. + + diff --git a/fern/products/sdks/generators/php/changelog/2026-05-12.mdx b/fern/products/sdks/generators/php/changelog/2026-05-12.mdx new file mode 100644 index 000000000..807ec83cd --- /dev/null +++ b/fern/products/sdks/generators/php/changelog/2026-05-12.mdx @@ -0,0 +1,7 @@ +## 2.9.5 +**`(chore):`** Patch PHP SDK + PHP model generator container CVEs flagged in the AWS ECR / +grype scan. Refresh `apk upgrade --available` to pull the latest Alpine +3.23 security patches and patch npm's bundled `picomatch@4.0.3 -> 4.0.4` +and `brace-expansion@5.0.4 -> 5.0.5` via tarball replacement. + + diff --git a/fern/products/sdks/generators/php/changelog/2026-05-13.mdx b/fern/products/sdks/generators/php/changelog/2026-05-13.mdx new file mode 100644 index 000000000..c29bf172a --- /dev/null +++ b/fern/products/sdks/generators/php/changelog/2026-05-13.mdx @@ -0,0 +1,8 @@ +## 2.9.6 +**`(fix):`** Stop launching WireMock with `--global-response-templating` in generated +wire-test `docker-compose.test.yml`. Response examples containing literal +`{{...}}` are now served verbatim instead of being passed through +WireMock's Handlebars transformer, which would fail to resolve them as +helpers and return 500. + + diff --git a/fern/products/sdks/generators/php/changelog/2026-05-14.mdx b/fern/products/sdks/generators/php/changelog/2026-05-14.mdx new file mode 100644 index 000000000..1bfcadf0d --- /dev/null +++ b/fern/products/sdks/generators/php/changelog/2026-05-14.mdx @@ -0,0 +1,17 @@ +## 2.10.0 +**`(feat):`** Support streaming response bodies in generated PHP SDKs (Server-Sent Events, +NDJSON, and raw text). Endpoints with a `response-stream` now return a typed +`SseStream`, `JsonStream`, or `TextStream` that iterates the response +frame-by-frame and deserializes each one into the declared payload type. +Previously these endpoints were emitted as broken `void` methods that always +threw `ApiException` regardless of HTTP status. + + +## 2.9.7 +**`(chore):`** Patch the bundled `ip-address` to v10.2.0 in the php-sdk container to +address CVE-2026-42338 / GHSA-v2v4-37r5-5v8g (XSS in `Address6` HTML- +emitting methods). npm 11.12.1 (shipped with `node:24.15`) bundles +`ip-address@10.1.0` via `socks`; this overlays the published 10.2.0 +tarball in place at image build time. + + diff --git a/fern/products/sdks/generators/python/changelog/2026-05-11.mdx b/fern/products/sdks/generators/python/changelog/2026-05-11.mdx new file mode 100644 index 000000000..4bcd29cf4 --- /dev/null +++ b/fern/products/sdks/generators/python/changelog/2026-05-11.mdx @@ -0,0 +1,10 @@ +## 5.12.4 +**`(chore):`** Bump the Python SDK generator container's Node base image from +`node:22.22-bookworm-slim` to `node:24.15-trixie-slim`. Aligns the +generator with the rest of the Fern generator containers on a single +Node major version (Node 24) and Debian release (trixie). Trixie ships +patched versions of glibc, dpkg, nghttp2, libcap2, systemd, libgcrypt20, +krb5, curl, and expat that are not available on bookworm, clearing the +AWS Inspector findings that dist-upgrade alone could not. + + diff --git a/fern/products/sdks/generators/python/changelog/2026-05-12.mdx b/fern/products/sdks/generators/python/changelog/2026-05-12.mdx new file mode 100644 index 000000000..f1c8ac180 --- /dev/null +++ b/fern/products/sdks/generators/python/changelog/2026-05-12.mdx @@ -0,0 +1,9 @@ +## 5.12.5 +**`(chore):`** Patch Python SDK generator container CVEs flagged in the AWS ECR / grype +scan. Patch npm's bundled `picomatch@4.0.3 -> 4.0.4` +(GHSA-c2c7-rcm5-vvqj, GHSA-3v7f-55p6-f55p) and +`brace-expansion@5.0.4 -> 5.0.5` (CVE-2026-33750) via tarball replacement +so the published image no longer ships the vulnerable bundled JS +dependencies that grype flags. + + diff --git a/fern/products/sdks/generators/python/changelog/2026-05-13.mdx b/fern/products/sdks/generators/python/changelog/2026-05-13.mdx new file mode 100644 index 000000000..942b7ca1c --- /dev/null +++ b/fern/products/sdks/generators/python/changelog/2026-05-13.mdx @@ -0,0 +1,8 @@ +## 5.12.6 +**`(fix):`** Stop launching WireMock with `--global-response-templating` in generated +wire-test `docker-compose.test.yml`. Response examples containing literal +`{{...}}` (e.g. FHIR/IPS template strings) are now served verbatim instead +of being passed through WireMock's Handlebars transformer, which would +fail to resolve them as helpers and return 500. + + diff --git a/fern/products/sdks/generators/python/changelog/2026-05-14.mdx b/fern/products/sdks/generators/python/changelog/2026-05-14.mdx new file mode 100644 index 000000000..0e13c2394 --- /dev/null +++ b/fern/products/sdks/generators/python/changelog/2026-05-14.mdx @@ -0,0 +1,21 @@ +## 5.12.8 +**`(chore):`** Bump Poetry from 1.8.5 to 2.4.1 in the python-sdk and pydantic-model +container images. Clears CVE-2026-34591 (Poetry `<2.3.3` stored credentials +in cleartext when keyring storage was unavailable). pyproject.toml's +`poetry-core` constraint moves from `^1.9.0` to `^2.0.0` to stay in +lockstep with Poetry 2.4.1's bundled `poetry-core 2.4.0` under +`virtualenvs.create=false`. `poetry.lock` regenerated under Poetry 2.4.1. + + +## 5.12.7 +**`(chore):`** Patch the bundled `ip-address` to v10.2.0 in the python-sdk container to +address CVE-2026-42338 / GHSA-v2v4-37r5-5v8g (XSS in `Address6` HTML- +emitting methods). npm 11.12.1 (shipped with `node:24.15`) bundles +`ip-address@10.1.0` via `socks`; this overlays the published 10.2.0 +tarball in place at image build time. Also bumps the container-level +`pip` to 26.1 to clear CVE-2025-8869, CVE-2026-3219, CVE-2026-6357, and +CVE-2026-1703 (self-update flaw running after wheel install). Poetry +stays at 1.8.5 because pyproject.toml's `virtualenvs.create=false` flow +requires `poetry-core ^1.9.0`. + + diff --git a/fern/products/sdks/generators/ruby/changelog/2026-05-12.mdx b/fern/products/sdks/generators/ruby/changelog/2026-05-12.mdx new file mode 100644 index 000000000..a258410ec --- /dev/null +++ b/fern/products/sdks/generators/ruby/changelog/2026-05-12.mdx @@ -0,0 +1,23 @@ +## 1.12.8 +**`(fix):`** Fix `Layout/EmptyComment` RuboCop offense emitted for types with no +description. The AST `Comment` node now skips writing when `docs` is +empty or whitespace-only, so undocumented model classes no longer +produce a bare `#` line above their class definition. + + +## 1.12.7 +**`(fix):`** Fix `Layout/EmptyComment` RuboCop offense emitted for types with no +description. The AST `Comment` node now skips writing when `docs` is +empty or whitespace-only, so undocumented model classes no longer +produce a bare `#` line above their class definition. + + +## 1.12.6 +**`(chore):`** Patch Ruby SDK generator container CVEs flagged in the AWS ECR / grype +scan. Remove the unused `erb-4.0.3`, `net-imap-0.4.21`, `addressable-2.8.5`, +`rexml-3.2.5`, and `rexml-3.2.6` gem directories (in addition to the +gemspec stubs) and install patched `addressable-2.8.10` + `rexml-3.4.4`, +so grype no longer reports the vulnerable versions vendored alongside +Ruby 3.3's default gems and the rubocop dependency graph. + + diff --git a/fern/products/sdks/generators/ruby/changelog/2026-05-13.mdx b/fern/products/sdks/generators/ruby/changelog/2026-05-13.mdx new file mode 100644 index 000000000..0214ecdd8 --- /dev/null +++ b/fern/products/sdks/generators/ruby/changelog/2026-05-13.mdx @@ -0,0 +1,8 @@ +## 1.12.9 +**`(fix):`** Stop launching WireMock with `--global-response-templating` in generated +wire-test `docker-compose.test.yml`. Response examples containing literal +`{{...}}` are now served verbatim instead of being passed through +WireMock's Handlebars transformer, which would fail to resolve them as +helpers and return 500. + + diff --git a/fern/products/sdks/generators/ruby/changelog/2026-05-14.mdx b/fern/products/sdks/generators/ruby/changelog/2026-05-14.mdx new file mode 100644 index 000000000..d82593a1d --- /dev/null +++ b/fern/products/sdks/generators/ruby/changelog/2026-05-14.mdx @@ -0,0 +1,12 @@ +## 1.12.10 +**`(chore):`** Bump `addressable` from 2.8.10 to 2.9.0 in the ruby-v2 SDK generator +container to clear CVE-2026-35611 (ReDoS in URI template expansion). +Switch the post-install cleanup to `gem cleanup` so older 2.8.x copies +dragged in by rubocop's dependency graph are dropped from the final +image. `rexml` stays pinned at 3.4.4 (past the 3.3.6 CVE-2024-49761 +fix). Also strip the vendored `Gemfile.lock` files inside cached +gems (lint_roller, rbs, typeprof, unicode-emoji) so grype stops +reading their pinned rexml / rdoc / addressable versions as +installed packages. + + diff --git a/fern/products/sdks/generators/rust/changelog/2026-05-11.mdx b/fern/products/sdks/generators/rust/changelog/2026-05-11.mdx new file mode 100644 index 000000000..344d02ae0 --- /dev/null +++ b/fern/products/sdks/generators/rust/changelog/2026-05-11.mdx @@ -0,0 +1,19 @@ +## 0.36.5 +**`(chore):`** Bump the Rust SDK and Rust model generator containers' Node base image from +`node:22.22-alpine3.23` to `node:24.15-alpine3.23`. Aligns the generators +with the rest of the Fern generator containers on a single Node major +version (Node 24) and picks up Node 24's CVE patches. The Rust SDK's +in-place `npm@11.13.0` self-upgrade and the bundled `ip-address` patch are +retained because the Node 24 `npm` ship (`11.12.1`) still vendors +`ip-address@10.1.0`, which is vulnerable to GHSA-v2v4-37r5-5v8g. + + +## 0.36.4 +**`(chore):`** Bump the rust toolchain stage in the rust-sdk and rust-model generator +containers from `rust:1.82-alpine3.20` to `rust:1.91-alpine3.23`. Alpine +3.20 is EOL and ships outdated openssl/musl/busybox/zlib/curl/git; 1.91 +is the lowest rust version Docker Hub publishes for alpine3.23. The +Node runtime stage was already on `node:22.22-alpine3.23`, so there is +no longer any Alpine 3.20 layer anywhere in these images. + + diff --git a/fern/products/sdks/generators/rust/changelog/2026-05-12.mdx b/fern/products/sdks/generators/rust/changelog/2026-05-12.mdx new file mode 100644 index 000000000..7443f7dac --- /dev/null +++ b/fern/products/sdks/generators/rust/changelog/2026-05-12.mdx @@ -0,0 +1,11 @@ +## 0.36.6 +**`(fix):`** Fix generated Rust wire tests for single-URL SDKs and pagination error +tests. The wire test generator no longer emits `config.environment = None;` +when the SDK was generated against a single base URL (since the +`environment` field does not exist on `ClientConfig` in that case). +The synchronous-paginator error-propagation tests now use +`ApiError::Configuration` instead of the non-existent +`ApiError::Serialization` variant, so the generated `pagination.rs` test +module compiles. + + diff --git a/fern/products/sdks/generators/rust/changelog/2026-05-13.mdx b/fern/products/sdks/generators/rust/changelog/2026-05-13.mdx new file mode 100644 index 000000000..040ab6546 --- /dev/null +++ b/fern/products/sdks/generators/rust/changelog/2026-05-13.mdx @@ -0,0 +1,8 @@ +## 0.36.7 +**`(fix):`** Stop launching WireMock with `--global-response-templating` in generated +wire-test `docker-compose.test.yml`. Response examples containing literal +`{{...}}` are now served verbatim instead of being passed through +WireMock's Handlebars transformer, which would fail to resolve them as +helpers and return 500. + + diff --git a/fern/products/sdks/generators/swift/changelog/2026-05-11.mdx b/fern/products/sdks/generators/swift/changelog/2026-05-11.mdx new file mode 100644 index 000000000..67db7330f --- /dev/null +++ b/fern/products/sdks/generators/swift/changelog/2026-05-11.mdx @@ -0,0 +1,7 @@ +## 0.35.5 +**`(chore):`** Bump the Swift SDK and Swift model generator containers' Node base image +from `node:22.22-alpine3.23` to `node:24.15-alpine3.23`. Aligns the +generators with the rest of the Fern generator containers on a single Node +major version (Node 24) and picks up Node 24's CVE patches. + + diff --git a/fern/products/sdks/generators/swift/changelog/2026-05-12.mdx b/fern/products/sdks/generators/swift/changelog/2026-05-12.mdx new file mode 100644 index 000000000..a8bf44a5b --- /dev/null +++ b/fern/products/sdks/generators/swift/changelog/2026-05-12.mdx @@ -0,0 +1,8 @@ +## 0.35.6 +**`(chore):`** Patch Swift SDK + Swift model generator container CVEs flagged in the AWS +ECR / grype scan. Patch npm's bundled `picomatch@4.0.3 -> 4.0.4` and +`brace-expansion@5.0.4 -> 5.0.5` via tarball replacement so the published +image no longer ships the vulnerable bundled JS dependencies that grype +flags. + + diff --git a/fern/products/sdks/generators/swift/changelog/2026-05-14.mdx b/fern/products/sdks/generators/swift/changelog/2026-05-14.mdx new file mode 100644 index 000000000..85987c340 --- /dev/null +++ b/fern/products/sdks/generators/swift/changelog/2026-05-14.mdx @@ -0,0 +1,8 @@ +## 0.35.7 +**`(chore):`** Patch the bundled `ip-address` to v10.2.0 in the swift-sdk container to +address CVE-2026-42338 / GHSA-v2v4-37r5-5v8g (XSS in `Address6` HTML- +emitting methods). npm 11.12.1 (shipped with `node:24.15`) bundles +`ip-address@10.1.0` via `socks`; this overlays the published 10.2.0 +tarball in place at image build time. + + diff --git a/fern/products/sdks/generators/typescript/changelog/2026-05-11.mdx b/fern/products/sdks/generators/typescript/changelog/2026-05-11.mdx new file mode 100644 index 000000000..b6a5c9ee9 --- /dev/null +++ b/fern/products/sdks/generators/typescript/changelog/2026-05-11.mdx @@ -0,0 +1,17 @@ +## 3.70.5 +**`(chore):`** Bump the TypeScript SDK validator container's Node base image to +`node:24.15-trixie-slim`. Aligns the validator with the rest of the +Fern generator containers on a single Node major version (Node 24) on +top of the trixie-slim base introduced for `typescript-sdk-cli` and +`typescript-sdk-validator` by PR #15779. + + +## 3.70.4 +**`(chore):`** Bump the typescript-sdk-cli and typescript-sdk-validator container base +images from `node:*-bookworm-slim` to `node:*-trixie-slim`. Trixie ships +patched versions of glibc, dpkg, nghttp2, libcap2, systemd, libgcrypt20, +krb5, curl, and expat that are not available on bookworm, so dist-upgrade +alone is a no-op for those AWS Inspector findings — the base-image bump +is what actually clears them. + + diff --git a/fern/products/sdks/generators/typescript/changelog/2026-05-12.mdx b/fern/products/sdks/generators/typescript/changelog/2026-05-12.mdx new file mode 100644 index 000000000..1216e3344 --- /dev/null +++ b/fern/products/sdks/generators/typescript/changelog/2026-05-12.mdx @@ -0,0 +1,8 @@ +## 3.70.6 +**`(chore):`** Patch TypeScript SDK generator container CVEs flagged in the AWS ECR / +grype scan. Rebuild the embedded `oxlint-tsgolint@0.22.1` Go binary from +source under `GOTOOLCHAIN=go1.26.3` so the published image no longer +ships the upstream go1.26.2 binary that grype flags for CVE-2026-33811, +CVE-2026-33814, CVE-2026-39820, CVE-2026-39836, and CVE-2026-42499. + + diff --git a/fern/products/sdks/snippets/basic-auth-params.mdx b/fern/products/sdks/snippets/basic-auth-params.mdx index 8f408f3d2..6b8c3efdb 100644 --- a/fern/products/sdks/snippets/basic-auth-params.mdx +++ b/fern/products/sdks/snippets/basic-auth-params.mdx @@ -30,4 +30,7 @@ auth-schemes: Environment variable name that the SDK will automatically scan for the username or password value. When this environment variable is present, users don't need to explicitly provide the username parameter. Follow naming conventions like `YOUR_APP_USERNAME` or `SERVICE_CLIENT_ID`. + + + Use when your API expects only one half of the basic auth credential pair. When `true`, the field is removed from the generated SDK's public API. The omitted field is treated as an empty string when encoding the `Authorization` header (omitting `password` produces `base64("username:")`; omitting `username` produces `base64(":password")`). When both are omitted, the `Authorization` header is skipped entirely. \ No newline at end of file