Repository navigation
Add hidden Fern instructions pages for coding agents - #7723
michaelpratt-postman wants to merge 4 commits into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
|
||
| ## Rules | ||
|
|
||
| - Pass `--no-prompt` or `--force` to anything that can prompt. Prompts fail immediately when stdin isn't a TTY or `CI` is set. |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Acronyms> reported by reviewdog 🐶
'TTY' has no definition.
| - Docs from scratch: `fern init --docs --organization <org>`. This creates only `docs.yml` and `fern.config.json`. | ||
| - SDKs or an API definition: `fern init --openapi <path-or-url> --organization <org>`. Without `--openapi`, `fern init` writes a sample `openapi.yml`. `fern init` also creates `sdk-config.yml` with one TypeScript target. | ||
| - Migrating docs: `fern init --docs --mintlify <path/to/mint.json>` or `fern init --docs --readme <readme-site-url>`. | ||
| 5. Pass `--organization` in non-interactive shells. Without it `fern init` prompts for the organization name, and prompts fail immediately with a non-zero exit code when stdin isn't a TTY or `CI` is set. |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Acronyms> reported by reviewdog 🐶
'TTY' has no definition.
| @@ -0,0 +1,30 @@ | |||
| --- | |||
| title: Generate a PHP SDK with Fern | |||
There was a problem hiding this comment.
📝 [vale] <Microsoft.Uppercase> reported by reviewdog 🐶
Don't use all uppercase for emphasis.
| --- | ||
| title: Generate a PHP SDK with Fern | ||
| slug: fern-instructions/sdks/php | ||
| description: Add, configure, and publish a PHP SDK generated by Fern. |
There was a problem hiding this comment.
📝 [vale] <Microsoft.Uppercase> reported by reviewdog 🐶
Don't use all uppercase for emphasis.
|
|
||
| ## Rules | ||
|
|
||
| - Fern silently ignores unknown `x-` keys. A misspelled extension does nothing and raises no error. Copy names from the extension pages. |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Adverbs> reported by reviewdog 🐶
Remove 'silently' if it's not important to the meaning of the statement.
| - Fern silently ignores unknown `x-` keys. A misspelled extension does nothing and raises no error. Copy names from the extension pages. | |
| - Fern ignores unknown `x-` keys. A misspelled extension does nothing and raises no error. Copy names from the extension pages. |
|
|
||
| ## Verify | ||
|
|
||
| - `fern check` passes. Generated method names, groups and types read naturally, and the API Reference shows examples for every endpoint. |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Adverbs> reported by reviewdog 🐶
Remove 'naturally' if it's not important to the meaning of the statement.
| - `fern check` passes. Generated method names, groups and types read naturally, and the API Reference shows examples for every endpoint. | |
| - `fern check` passes. Generated method names, groups and types read , and the API Reference shows examples for every endpoint. |
| | Invalid docs URL | The `instances` URL includes `https://` or doesn't end in `docs.buildwithfern.com` | | ||
| | MDX parse error | Unclosed tag, or a bare `<` or `{` in prose. Escape it or wrap it in backticks. | | ||
| | API Reference is empty or stale | The spec isn't listed in the `api` entry or `generators.yml`, or `fern api update` hasn't pulled the current spec | | ||
| | `fern docs dev` fails on Windows | Long path support is off. Enable it or use WSL. | |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Acronyms> reported by reviewdog 🐶
'WSL' has no definition.
| | Symptom | Cause and fix | | ||
| |---|---| | ||
| | `No fern directory found` | Wrong working directory. Run from the folder that contains `fern/`. | | ||
| | Job stops responding, then times out | A prompt is waiting. Add `--no-prompt` (or `--force` for preview `--id` overwrites). Prompts fail immediately when stdin isn't a TTY or `CI` is set. | |
There was a problem hiding this comment.
📝 [vale] <FernStyles.Acronyms> reported by reviewdog 🐶
'TTY' has no definition.
|
Hidden pages will go out of date, and nobody will see it. The 42 pages are short copies of the main docs. Think of a copy of a map that nobody looks at. When the roads change, nobody tells you the copy is wrong.
|
|
@adiophir Thanks, that's a fair point. I checked fern-api/fern#18755. It keeps On the general fix, these are the options I see:
I'm checking with @michaelpratt-postman which of these to do in this PR and which to file as follow-ups. |
|
list only the index page in llms.txt as "agent instructions." Humans still won't see the pages, and agents can discover them. |
|
|
@adiophir Re: listing only the index in |
|
@adiophir Re: "documented here for the first time". I meant the first docs page, not the first release. The commands shipped in CLI 5.179.0–5.183.2 ( |
|
The URL couples the CLI to the docs site layout.
|
|
@adiophir Agreed. Deriving the URL from the topic words couples released CLIs to the
I'm checking with @michaelpratt-postman which one to use. |
|
The index points to the docs MCP server and llms.txt, and docs ai mentions site "skills." The PR doesn't say why a third channel beats, for example, shipping these pages as MCP prompts or resources, or as a skills bundle. The CLI command may be the right answer, but the comparison should be written down. |
|
@adiophir Good call. I've added a "Why a CLI command, and not only MCP,
Happy to change the comparison if you see another trade-off. |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@adiophir Re: hidden pages going out of date. fab47dc adds an "Agent instruction pages" section to This only covers changes made in this repo. CLI behavior changes such as fern-api/fern#18755 reach this repo through the canonical docs update, at which point the rule applies. A CI check that the commands and flags on these pages still exist in the CLI is still a possible follow-up. |
…, mark index as CLI contract Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@adiophir Following up on the URL coupling: we're going with redirects. I tested redirects that are already live on buildwithfern.com, and they also cover
So the CLI can still build the URL from the topic words and follow redirects, with one request per topic and no index lookup. If a page or folder moves, a To make sure this happens, fdfcebd adds a rule to the "Agent instruction pages" section of |
|
@adiophir Here's where the remaining threads stand after talking with @michaelpratt-postman:
|
Summary
Adds 42 hidden, agent-facing instruction pages under
/learn/home/fern-instructions/.... They're the content for a proposedfern instructions <topic>CLI command (modeled on Mintlify'smint instructions). The command would fetch<topic>.mdand print it, so an agent gets curated, task-scoped guidance without first hitting a 404.mdpage. The CLI command isn't part of this PR. The pages are useful on their own because any agent can fetch them directly.Why the pages are hidden. Every page is
hidden: trueinfern/products/home/home.yml, and no visible page links to them. That keeps them out of the sidebar, site search, the sitemap, andllms.txt, and gives the HTMLnoindex, nofollow. Direct.mdURLs still work, which is all the CLI needs. They don't use<llms-only>because that would also hide them from Ask Fern.Why a CLI command, and not only MCP,
llms.txtor skills. These pages are meant to be the single source of content; the delivery channel is a separate choice, and other channels can point to the same pages.fern instructions <topic>(proposed)/learn/_mcp/server)searchDocs/fetchPageonly, and hidden pages are excluded from searchfern-platformchange, so it's a good follow-up rather than an alternativellms.txtfern-api/skillsnpx skills add, per repofern instructionsTopics. The index page (
/learn/home/fern-instructions) lists every topic with a "when to use" line:overview,new-site,troubleshootdocs write,docs write components,docs configure,docs configure navigation,docs configure customization,docs configure seo,docs configure localization,docs api-reference,docs publish,docs publish domain,docs access,docs ai,docs analyticsspec,spec extensions,spec overrides,spec auth,spec sync,spec formatssdks, one page per language (typescript,python,go,java,csharp,php,ruby,swift,rust),sdks publish,sdks custom-code,sdks features,sdks local,sdks migrateautomate,access team,migrate,cli-generatorTopic words map to URL paths. For example,
docs publish domainmaps to/learn/home/fern-instructions/docs/publish/domain.md. Released CLIs would depend on these paths, so moved pages get adocs.ymlredirect instead of a manifest lookup. Redirects already apply to.mdURLs on the live site:/learn/docs/ai/llms-txt.mdreturns 308 to/learn/docs/ai-features/llms-txt.md, and:slug*wildcards preserve.mdthe same way. A topic fetch is one request that follows redirects. Onlyfern instructionswith no topic fetches the index.AGENTS.mdrequires a redirect whenever an instruction page moves or is renamed.Guest, claim and identity commands (in
new-site.mdx, checked against the CLI source infern-api/fern). These shipped in CLI 5.179.0–5.183.2; until now the only docs were the CLI changelog entries from 2026-10-27 and 2026-10-28.fern generate --docs --guest(and--new-session), which publishes to a temporarydrop-<id>site. Guests can't generate SDKs yet, and every page that mentions--guestsays so.fern claimandfern claim --org <name>fern whoamiandfern whoami --jsonfern loginandFERN_TOKENfern/.guest-sessionand~/.fern/guest-sessions/Each page condenses existing canonical docs and links back to them. Pages follow one structure: workflow steps, the rules agents most often get wrong, and how to verify the result.
Discovery.
agents.page-directiveindocs.ymlnow adds "For task-scoped instructions for coding agents working in a Fern project, see https://buildwithfern.com/learn/home/fern-instructions.md" to every.mdpage. Fern can't list a single hidden page inllms.txt: the only override,agents.llms-txt, replaces the whole generated file.Keeping the pages current. Hidden pages don't get noticed when they go stale, so
AGENTS.mdhas a new "Agent instruction pages" section. It tells anyone editing a canonical page, or documenting a CLI command change, to searchfern-instructions/for pages that cite it and update them in the same PR. Each instruction page's## Referencesection lists the canonical pages it condenses, which is what makes that search work. The index (topics.mdx) has a frontmatter comment saying it powersfern instructionsand must not move, change slug, or change its table format without a matching CLI change.Reviewer note. The SDK examples use
output.path: ../sdks/<language>, the same as the canonical SDK quickstarts. However,sdk-config-reference.mdxsays paths with..segments are rejected, yet its own examples use them. One of the two needs fixing; that's outside this PR.Testing
grep -rl "docs/preview-publish/publishing-your-docs" fern/products/home/pages/fern-instructions/(the example inAGENTS.md) returnsautomate.mdxanddocs/publish.mdx.fern check: 0 errors. The 10 warnings were already onmain.TTY/WSL, uppercasePHP, and adverbs.fern docs dev: all 42 slugs return 200./learn/homehas nofern-instructionslinks. Hidden pages render with<meta name="robots" content="noindex, nofollow"/>.<slug>.mdURLs return 200text/markdown./home/fern-instructionsappears 0 times inllms.txt,home/llms.txt,llms-full.txt,sitemap-en.xmland the/learn/homeHTML. Pages render withnoindex, nofollow..md, checked on the live site:curl -sI https://buildwithfern.com/learn/docs/ai/llms-txt.mdreturns 308 withlocation: /learn/docs/ai-features/llms-txt.md. The wildcard rule/learn/sdks/guides/publish-to-package-managers/:slug*redirectstypescript.mdto/learn/sdks/generators/typescript.md.To verify on the preview deployment:
curl -sI <preview>/learn/home/fern-instructions/new-site.mdshould returncontent-type: text/markdown.curl -s <preview>/learn/llms.txt | grep -c /home/fern-instructionsshould print0. Grep for the path, not justfern-instructions, because the preview hostname contains the branch name. The Home sidebar should also show no instruction pages.Link to Devin session: https://app.devin.ai/sessions/c3611c1a7c044b1693dec7cd5e990086
Open in Devin Desktop: https://app.devin.ai/desktop/session/c3611c1a7c044b1693dec7cd5e990086?variant=devin
Requested by: @michaelpratt-postman