SKILL PROCEDURE

Fern

Use when defining an API once and generating client SDKs, a CLI, and a documentation site from that single definition — choosing between an OpenAPI spec and Fern's own API Definition format, configuring generators.yml or docs.yml, deciding what requires regenerating versus hand-editing, or versioning generated SDKs across languages. Published by HardGraph, a curated graph of provenance-backed knowledge for AI agents.

fernapi-definitionssdk-generationopenapideveloper-docs
BEGINNER GUIDE

Understand Fern before using it

CATEGORY

Fern is catalogued under Backend and data.

START HERE WHEN

Your work repeatedly involves the concepts tagged above. Open the full procedure below when the current task matches them.

Compare related skills

SKILLCATEGORYSHARED CONCEPTSEXPLANATION
FernBackend and dataCurrent skillUse when defining an API once and generating client SDKs, a CLI, and a documentation site from that single definition — choosing between an OpenAPI spec and Fern's own API Definition format, configuring generators.yml or docs.yml, deciding what requires regenerating versus hand-editing, or versioning generated SDKs across languages. Published by HardGraph, a curated graph of provenance-backed knowledge for AI agents.
AppwriteBackend and dataSame categoryAppwrite — an open-source backend-as-a-service (self-hosted or Cloud) providing Auth, Databases, Storage, Functions, Messaging, and Realtime. Use when adding user authentication and sessions, modelling data in the document database with attributes/permissions, uploading and serving files, running serverless Functions (Node, Python, Ruby, PHP, Dart) triggered by events or schedules, sending push/email/SMS, subscribing to realtime document changes, or integrating the Web/Flutter/Apple/Android/React Native SDKs and server SDKs. Published by HardGraph, a curated graph of provenance-backed knowledge for AI agents.
MedusaBackend and dataSame categoryUse when building or customizing a Medusa headless commerce backend — deciding whether custom logic belongs in a commerce module, a workflow, or a plugin, choosing between the Admin and Store APIs, designing a multi-step business process that must survive a partial failure, or deciding between self-hosting and Medusa Cloud. Published by HardGraph, a curated graph of provenance-backed knowledge for AI agents.
MilvusBackend and dataSame categoryUse when storing and searching dense vector embeddings for similarity search, RAG retrieval, or recommendation — choosing an ANN index type, designing a collection schema, deciding between self-hosted Milvus, Zilliz Cloud, and pgvector, or reasoning about consistency levels for search-after-write. Published by HardGraph, a curated graph of provenance-backed knowledge for AI agents.

Fern

Fern treats an API definition as the one artifact everything else derives from: SDKs in multiple languages, a CLI, and a documentation site are all generated outputs of the same source, not three things maintained by hand and kept in sync by discipline. The definition lives in a fern/ directory alongside fern.config.json (workspace identity, not the API shape itself) and generators.yml (which generators run, against which output targets and versions).

The format choice that decides everything downstream

An API can be defined two ways: import an existing OpenAPI spec, or author it directly in Fern's own Intermediate Representation (the "Fern Definition," YAML files under fern/apis/). These are not equivalent inputs producing identical output. OpenAPI import is lower-effort when a spec already exists, but Fern's IR carries constructs OpenAPI expresses awkwardly — discriminated unions, more precise auth schemes, examples tied to types rather than only to operations — so a spec leaning on OpenAPI extensions to work around those gaps generates rougher SDKs than a Fern Definition authored natively. A team that hand-wrote an OpenAPI spec plus a separate docs site (Redoc, Docusaurus) and now wants SDKs is choosing between reformatting that spec for Fern or re-authoring in Fern's IR; the second costs more upfront and produces better-shaped generated code.

Generated code is not a starting point to edit

SDK output is meant to be regenerated on every definition change, not patched by hand — a hand-edit is silently overwritten by the next fern generate, with no merge step that preserves it. Fern's answer to "I need custom logic in the generated client" is explicit extension points (custom code injected via configured hooks), a different mental model from a scaffolded project meant to be customized in place. Docs content under fern/docs.yml and referenced markdown, by contrast, is hand-authored and never regenerates — the generated/authored split is per-directory, not uniform, and getting it backwards either loses edits silently or blocks the definition from updating cleanly.

Versioning is per-language, not per-repo

Each SDK generator target (TypeScript, Python, Go, Java, Ruby, ...) has its own version and release cadence in generators.yml, independent of the API definition's own version and of each other — a breaking API change does not imply every language SDK bumps together, and generator versions themselves receive updates independent of the API surface. Treat "the SDK version" as a per-language question, not a single number.

What to verify rather than recall

Exact generators.yml and docs.yml keys, which OpenAPI extensions Fern currently reads, supported generator languages and their individual versioning schemes, and CLI command syntax all move across releases. Confirm these against the mirrored corpus under references/vendor/ rather than asserting a remembered value.

References

Hardgraph / curated knowledge for agents.

STATIC EXPORT · CANONICAL SOURCE