Skip to content

docs: add a documentation site for Forge - #52

Open
dimitropoulos wants to merge 1 commit into
dimitri/mcp-rustfrom
dimitri/docs
Open

dimitropoulos wants to merge 1 commit into
dimitri/mcp-rustfrom
dimitri/docs

Conversation

@dimitropoulos

Copy link
Copy Markdown
Collaborator

Adds packages/docs, a documentation site for Forge itself, built with Astro and Nimbus.

What's in it

  • Start Here: introduction, installation, quickstart.
  • Core Concepts: the pipeline, the model, groups and methods, requests and responses, types, names, model placement, sandboxing.
  • Writing Plugins: TypeScript plugins, the TypeScript printer, Rust (as a WebAssembly component or as a library), other languages, testing, designing a target. The built-in targets are presented as plugins like any other.
  • Targets: the TypeScript SDK and the MCP server.
  • Authoring OpenAPI: naming methods, extensions, the support matrix, errors.
  • Compatibility Modes: one page for the Fern extensions Forge reads.
  • Guides: generating in CI, adopting Forge on an existing API, contributing.
  • Reference: CLI, Rust API, plugin API, TypeScript printer, WIT.

Examples and output on the pages come from real runs of forge, and claims were checked against the source.

Naming

The docs describe methods as named by a dotted operationId (pets.list, accounts.members.list). That behavior is implemented in #51 (issue #50); this PR should land after it. The Fern extensions, including how they take precedence over operationId, are described only on the Compatibility Modes page.

Other changes

  • AGENTS.md: every change should check and update the docs it affects.
  • .oxfmtrc.json: page content is excluded, since its code blocks show generated output byte for byte.
  • .oxlintrc.json: curly is off for packages/docs, as for the other Astro sites.

Checks

pnpm --filter forge-docs build and check pass, root pnpm check passes, and every internal link and anchor resolves.

Stacked on #49, since the docs cover the MCP target.

packages/docs is an Astro and Nimbus site covering Forge end to end:
getting started, the model, writing plugins in TypeScript, Rust and
other languages, the built-in TypeScript and MCP targets, authoring
OpenAPI, guides, and reference pages for the CLI, the Rust API, the
plugin API, the TypeScript printer and the WIT.

Methods are documented as named by a dotted operationId. The extensions
Forge reads for compatibility with Fern are described on one page,
under Compatibility Modes, and nowhere else.

AGENTS.md now asks for the docs to be updated with every change that
affects them. Page content is excluded from oxfmt, since its code
blocks show real generated output byte for byte.
Copilot AI balanced review requested due to automatic review settings October 19, 2026 00:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

4 open issues
1 file not reviewed
  • pnpm-lock.yaml: Generated file
What changed in this PR

Adds an Astro/Nimbus documentation site for Forge itself, complementing the existing API documentation site. Content covers the MCP target from #49 and depends on the naming changes in #51.

Changes:

  • Adds generator concepts, plugin guides, OpenAPI guidance and reference pages.
  • Implements documentation navigation, search, Markdown/LLM endpoints and social cards.
  • Adds static deployment configuration and updates repository documentation conventions.
File Description
packages/​docs/​wrangler.jsonc Updated as part of this pull request.
packages/​docs/​tsconfig.json Updated as part of this pull request.
packages/​docs/​src/​utils/​agent-endpoint-response.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​robots.txt.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​og/​[...slug].ts Updated as part of this pull request.
packages/​docs/​src/​pages/​og/​_og-card-config.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​og.png.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​llms.txt.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​llms-full.txt.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​404.astro Updated as part of this pull request.
packages/​docs/​src/​pages/​[section]/​llms.txt.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​[...slug]/​index.mdx.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​[...slug]/​index.md.ts Updated as part of this pull request.
packages/​docs/​src/​pages/​[...slug].astro Updated as part of this pull request.
packages/​docs/​src/​lib/​cn.ts Updated as part of this pull request.
packages/​docs/​src/​content/​partials/​.gitkeep Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​targets/​overview.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​start/​introduction.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​start/​installation.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​reference/​wit.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​reference/​ts-printer.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​reference/​cli.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​plugins/​testing.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​plugins/​overview.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​plugins/​other-languages.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​openapi/​support.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​openapi/​overview.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​openapi/​naming.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​openapi/​extensions.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​openapi/​errors.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​index.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​guides/​contributing.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​guides/​ci.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​guides/​adopting.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​concepts/​sandbox.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​concepts/​pipeline.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​concepts/​names.mdx Updated as part of this pull request.
packages/​docs/​src/​content/​docs/​concepts/​models.mdx Updated as part of this pull request.
packages/​docs/​src/​content.config.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​toc/​TOC.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​toc/​MobileTOC.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​toc/​mobile-toc.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​toc/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​theme-toggle/​ThemeToggle.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​theme-toggle/​theme-toggle.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​theme-toggle/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​TabsTrigger.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​TabsList.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​TabsContent.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​tabs.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​Tabs.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​TabItem.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​tabs/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​steps/​steps.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​steps/​Steps.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​steps/​Step.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​steps/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​sidebar/​SidebarLink.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​sidebar/​SidebarFilter.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​sidebar/​Sidebar.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​sidebar/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​search/​SearchTrigger.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​search/​SearchDialog.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​search/​search-trigger.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​search/​providers/​pagefind.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​search/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​pagination/​Pagination.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​pagination/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​page-actions/​PageActions.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​page-actions/​page-actions.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​page-actions/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​package-managers/​PackageManagers.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​package-managers/​package-managers.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​package-managers/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​link-card/​LinkCard.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​link-card/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​link-button/​LinkButton.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​link-button/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​layer-card/​LayerCardHeader.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​layer-card/​LayerCardContent.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​layer-card/​LayerCard.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​layer-card/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​DialogContent.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​DialogClose.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​dialog.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​Dialog.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​dialog/​dialog-close.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​collapsible/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​collapsible/​CollapsibleTrigger.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​collapsible/​CollapsibleContent.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​collapsible/​collapsible.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​collapsible/​Collapsible.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​code/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​code/​Code.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​card/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​card/​Card.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​card-grid/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​card-grid/​CardGrid.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​button/​variants.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​button/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​button/​Button.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​breadcrumbs/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​breadcrumbs/​Breadcrumbs.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​banner/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​banner/​banner.client.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​banner/​Banner.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​badge/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​badge/​Badge.astro Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​aside/​index.ts Updated as part of this pull request.
packages/​docs/​src/​components/​ui/​aside/​Aside.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Render.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Prose.astro Updated as part of this pull request.
packages/​docs/​src/​components/​NavList.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Logo.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Hero.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Header.astro Updated as part of this pull request.
packages/​docs/​src/​components/​Features.astro Updated as part of this pull request.
packages/​docs/​src/​components/​AgentDirective.astro Updated as part of this pull request.
packages/​docs/​src/​components.ts Updated as part of this pull request.
packages/​docs/​README.md Updated as part of this pull request.
packages/​docs/​public/​favicon.svg Updated as part of this pull request.
packages/​docs/​public/​_headers Updated as part of this pull request.
packages/​docs/​package.json Updated as part of this pull request.
packages/​docs/​og-assets/​og-mark.svg Updated as part of this pull request.
packages/​docs/​nimbus.json Updated as part of this pull request.
packages/​docs/​astro.config.ts Updated as part of this pull request.
packages/​docs/​.gitignore Updated as part of this pull request.
AGENTS.md Updated as part of this pull request.
.oxlintrc.json Updated as part of this pull request.
.oxfmtrc.json Updated as part of this pull request.

Review effort: Balanced

Comment on lines +19 to +23
localStorage.setItem('ui-mode', isDark ? 'light' : 'dark');
} catch {
// Ignore storage errors (private mode / restricted contexts).
}
window.__nbApplyTheme?.();
// 30%] of the viewport height; BAND_TOP is its upper edge, reused by the
// first/last clamp below.
const BAND_TOP = 0.1;
const ROOT_MARGIN = '-10% 0px -70% 0px';

<BaseLayout title="Page not found" description="The page you're looking for doesn't exist." noindex>
<div class="flex flex-col min-h-screen">
<Header />
{
icon: 'ph:shield-check',
title: 'Sandboxed by construction',
body: 'A WebAssembly plugin gets no files, network, environment or clock. It reads the model and returns files; the host checks every path before writing.',

@srikrsna srikrsna left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we open this against main?

@srikrsna srikrsna left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just for the code, not for the content. I'll do that in a second pass.

I haven't read all of the code. I left some comments on the high level components.

Do we need to create our own generic UI components? Can't we an existing one that is better maintained?

Comment on lines +1 to +29
# Cache policy for the asset store. Parsed by Workers, never served itself.
#
# Workers' default for every static asset is `public, max-age=0,
# must-revalidate`, which is a safe default and the wrong one here in two ways.
#
# It made the hover prefetch useless. A response that must be revalidated
# cannot be reused from cache, so the document Astro had already fetched was
# thrown away and refetched on the click. Meanwhile the stylesheet -- also
# revalidated, but tiny and answered with a 304 -- was ready first, so the
# browser had enough to paint a styled header over bare background while the
# body was still arriving. That frame is the flash of black between pages.
#
# It also revalidates fingerprinted files on every navigation. Those URLs
# change whenever their content does, so the round trip can never do anything
# except confirm what the URL already promised.

# Everything, unless overridden below. A minute of freshness is what makes a
# prefetched page reusable on the click; `must-revalidate` then forbids serving
# it stale, so a deploy is picked up a minute later at the outside.
/*
Cache-Control: public, max-age=60, must-revalidate

# Astro fingerprints everything it emits here, so these are safe to keep for a
# year and never revalidate. The detach is deliberate: a request matching two
# rules inherits both, and a header set twice is joined with a comma rather
# than replaced, so the broader rule above has to be removed first.
/_astro/*
! Cache-Control
Cache-Control: public, max-age=31536000, immutable

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +3 to +12
buttonVariants,
buttonBase,
buttonVariantClasses,
buttonSizeText,
buttonSizeCompact,
buttonIconSize,
type ButtonVariant,
type ButtonSize,
type ButtonShape,
type ButtonVariantsOptions,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these exported?

</div>
</aside>

<style>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are mixing both tailwind and regular css that astro scopes. I think we should just stick to tailwind

href?: string;
}

const features: Feature[] = [

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use markup here instead. The body being a text is a bit weird. If we want to keep it dry we can always define a smaller component.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different from the astro page. I think we should loose the directory and place them as siblings to the html page like [...slug].md.ts and [...slug].mdx.ts

@srikrsna srikrsna left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a partial read of the docs. Left some comments.

Comment on lines +36 to +37
That writes a TypeScript SDK: one directory per group, a typed client per directory, and a small
runtime. Swap `--target ts` for `--target mcp` and you get a Rust crate for an MCP server instead.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users reading the home page are not aware of a group, so we should loose that. Same goes for "per directory"

We don't have the mcp target yet so we should loose that for now.

Comment on lines +41 to +42
A plugin is two functions: one called once for the whole document, and one called for each group,
in parallel. Here is a complete plugin, in TypeScript, that writes a Markdown file per group:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, they wouldn't know what a group is here so I would start with the common generate function that we have overall.

Comment on lines +25 to +27
- **The shared part** is done once, in Forge's core. It parses the document, follows every `$ref`,
decides which operations are methods and how they are grouped, turns schemas into types, places
each model in the group that uses it, and reports every problem in the document at once.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also highlight the subtle differences in OpenAPI 3.0 to 3.2 and that forge normalizes.

Comment on lines +37 to +43
You can write a plugin three ways:

| How | Language | Runs as |
| ------------------------ | ---------------------------- | ---------------------------------------------------------------------- |
| A WebAssembly component | TypeScript or JavaScript | `--target wasm://plugin.wasm`, built with `forge-plugin build` |
| A WebAssembly component | Rust, or any component language | `--target wasm://plugin.wasm`, built for `wasm32-wasip2` |
| Native, in Rust | Rust | A built-in `--target`, or your own binary that uses Forge as a library |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is really just two ways, the first two are the same. We just happen to provide an easy way to compile TS plugins.

Comment on lines +45 to +46
A WebAssembly plugin is a single file. It runs sandboxed, with no access to files, the network or
the environment, so you can run one you did not write. See [writing plugins](/plugins/overview/).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be better worded. I don't understand the part that says, you can run one you did not write. I think it is too general.

Comment on lines +49 to +55
The package also has the `forge-plugin` command and the libraries for
[writing plugins in TypeScript](/plugins/typescript/). Plugin authors need one more package, which
is an optional peer dependency because nobody else does:

```sh
npm install --save-dev @bytecodealliance/jco
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can omit anything to with plugins from this page.

Comment on lines +80 to +85
To run a local build through the npm launcher, for example from a project that already depends on
`@cloudflare/forge`, point `FORGE_BINARY` at it:

```sh
FORGE_BINARY=../forge/target/release/forge npx forge openapi.json --target ts --out sdk
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would anyone do this?

@@ -0,0 +1,219 @@
---
title: Quickstart
description: Write a small OpenAPI document, generate a TypeScript SDK and an MCP server from it, and run a plugin of your own.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this quick start is targeting vasty different personas. Majority of users will just run an existing target. We should split these quick starts.

Comment on lines +8 to +10
Forge reads the OpenAPI extensions of [Fern](https://buildwithfern.com), another SDK generator, so a
document already annotated for Fern needs no changes to generate with Forge. This mode is always on;
there is nothing to enable. A document without any of these extensions loses nothing.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We read a subset of fern extensions and not all of them. Same goes for another SDK generator (which we plan to remove) so I think we shouldn't call it out here.

Comment on lines +12 to +13
This page is the only place the Fern extensions are described. Everywhere else, the docs describe
Forge's own conventions: methods named by `operationId`, models by schema name, fields by wire name.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed for the user reading the doc.

@ndisidore

Copy link
Copy Markdown
Member

@clanky-the-clanker review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants