Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ The project uses Semantic Versioning. Each release contains the same three chang

### New Features

- None.
- `cortex docs build` now exports static HTML, CSS, JavaScript, and documentation data for deployment to a static web host.

### Bug Fixes

- None.
- Fixed the documentation layout and navigation on mobile screens.
- Fixed MCP tool links that scrolled to the wrong position after the setup guide loaded.
- Excluded workspace test dependencies from the CLI release package to prevent dependency conflicts during CI packaging.

### Improvements

- None.
- Removed `cortex docs start`. Use `cortex docs serve` for a local preview with file watching. Host production output as static files without a Node.js server.

## [0.1.30] - 2026-08-31

Expand Down
21 changes: 16 additions & 5 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,24 @@ npm run --workspace=@cortex-docs/docs-ui dev:next

### Cloudflare demo

The public demo uses two Cloudflare Workers:
The public demo uses a Worker for the API and static hosting for the documentation:

- `api.demo.cortexdocs.dev` serves the REST, GraphQL, WebSocket, OpenRPC, and HTTP bridge endpoints.
- `demo.cortexdocs.dev` serves the Next.js documentation UI through OpenNext.
- `demo.cortexdocs.dev` serves the exported documentation through Cloudflare Static Assets.

Run the API Worker without the docs UI:

```bash
npm run --workspace=@cortex-docs/demo-api dev
```

Build the docs UI for the Cloudflare runtime:
Build the static documentation for Cloudflare:

```bash
npm run --workspace=@cortex-docs/docs-ui demo:build
```

Preview the complete docs UI Worker locally:
Preview the static documentation locally:

```bash
npm run --workspace=@cortex-docs/docs-ui demo:preview
Expand Down Expand Up @@ -344,7 +344,18 @@ The spec is served via the `/api/spec` route, which reads the file path from the
npm run --workspace=@cortex-docs/docs-site dev
```

Starts the product documentation site locally on `:3200` with hot reload. Edit a Markdown file in `packages/docs-site/docs/` to update a page.
The command starts the product documentation site locally on `:3200` with hot reload. Edit a Markdown file in `packages/docs-site/docs/` to update a page.

Build the product documentation as static files:

```bash
npm run --workspace=@cortex-docs/docs-site build
```

This command runs `cortex docs build --output .cortex/docs` in the product docs workspace. The output directory is `packages/docs-site/.cortex/docs`.

Deploy the output directory to a static web host. Configure page URLs such as `/docs/quickstart` to resolve to `/docs/quickstart.html`.
The deployed site needs no Node.js server or access to the original configuration and specifications. Rebuild the site after source changes.

## Modifying the Docs Site

Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ mcp-server → generated/mcp-server

The generated MCP server gives AI agents typed tools, specifications, SDK guides, and project documentation.

Generate the files. Then start the documentation server:
Generate the files. Then start the local documentation preview:

```bash
cortex generate
Expand All @@ -82,7 +82,7 @@ Open `http://localhost:3012`. Press `Ctrl+C` to stop the server.
- Generate SDKs for TypeScript, Python, Go, Java, Kotlin, Ruby, PHP, C#, Rust, C++, and C.
- Combine multiple specification files in one generated SDK.
- Generate HTTP, WebSocket, GraphQL, gRPC, and JSON-RPC clients.
- Generate a production documentation server with interactive API reference pages.
- Build static HTML documentation with interactive API reference pages.
- Generate an MCP server with typed tools, embedded specifications, SDK guides, and project documentation for AI agents.
- Add Markdown pages, SDK guides, and all API specifications to the MCP server.
- Customize generated output with sparse Eta template overrides.
Expand Down Expand Up @@ -184,8 +184,7 @@ See the [configuration reference](packages/docs-site/docs/configuration.md) for
| `cortex generate --language typescript` | Generate one configured language. |
| `cortex generate --dry-run` | Show planned output without writing files. |
| `cortex docs serve` | Start the development server and watch project files. |
| `cortex docs build --output .cortex/docs` | Create a production Node.js documentation build. |
| `cortex docs start --output .cortex/docs` | Start a production documentation build. |
| `cortex docs build --output .cortex/docs` | Build static HTML documentation. |
| `cortex mcp generate` | Generate only the MCP server. |
| `cortex publish --dry-run` | Check package publication without uploading. |
| `cortex publish` | Publish enabled generated packages. |
Expand All @@ -204,14 +203,15 @@ The generated MCP server does not call gRPC methods. It exposes Protocol Buffer

## Production documentation

The build command creates a self-contained Next.js server. It is not a static HTML export.
The build command exports the documentation as static HTML, CSS, JavaScript, and data files.

```bash
cortex docs build --output .cortex/docs
NODE_ENV=production cortex docs start --output .cortex/docs --port 3000
```

Deploy the output directory to a service that can run Node.js. Keep `cortex.config.yml` and its referenced specifications available at runtime.
Deploy the output directory to a static web host. Configure the host to resolve page URLs such as `/docs/quickstart` to `/docs/quickstart.html`.

The deployed site needs no Node.js server or access to the original configuration and specifications. Rebuild the site after source changes. Use `cortex docs serve` for a local preview with file watching.

## MCP output

Expand Down
4 changes: 2 additions & 2 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ Run this command to calculate the next version without file changes:
node scripts/set-release-version.mjs --check
```

Run this command to build the demo for the Cloudflare runtime:
Run this command to build the demo documentation as static files for Cloudflare:

```bash
npm run --workspace=@cortex-docs/docs-ui demo:build
```

Run this command to build the product docs for the Cloudflare runtime:
Run this command to build the product documentation as static files for Cloudflare:

```bash
npm run --workspace=@cortex-docs/docs-ui docs:build
Expand Down
45 changes: 38 additions & 7 deletions e2e/docs-ui-static.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,49 @@ test.describe('Cloudflare Static Assets export', () => {
});

test('serves generated MCP and SDK deep links', async ({ page }) => {
await page.goto('/mcp/docs_quickstart');
await expect(page.getByText('docs_quickstart').first()).toBeVisible();

await page.goto('/mcp/sdk_typescript_petstore_typescript_client_sdk');
await expect(
page.getByText('sdk_typescript_petstore_typescript_client_sdk').first(),
).toBeVisible();
const mcp = await (await page.request.get('/api/mcp')).json();
for (const tool of [
'docs_quickstart',
'sdk_typescript_petstore_typescript_client_sdk',
mcp.tools.at(-1).name,
]) {
await page.goto(`/mcp/${tool}`);
await page.waitForLoadState('networkidle');
await expect(page.locator(`[id="mcp-${tool}"]`)).toBeInViewport({ ratio: 1 });
await expect(page.getByRole('navigation', { name: 'breadcrumb' })).toContainText(tool);
await expect(page).toHaveURL(new RegExp(`/mcp/${tool}$`));
}

await page.goto('/sdks/typescript');
await expect(page.getByText('TypeScript').first()).toBeVisible();
});

for (const width of [320, 390]) {
test(`keeps documentation readable and navigation usable at ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 844 });
await page.goto('/docs/quickstart');
await expect(page.getByRole('heading', { name: 'Quickstart', exact: true })).toBeVisible();
const article = await page.locator('article').boundingBox();
expect(article?.width).toBeGreaterThanOrEqual(width - 40);
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBe(width);
await expect(page.getByRole('button', { name: 'Toggle theme' })).toBeInViewport({ ratio: 1 });
await expect(page.getByRole('button', { name: 'Search documentation' })).toBeInViewport({
ratio: 1,
});

await page.getByRole('button', { name: 'Open documentation navigation' }).click();
const navigation = page.getByRole('dialog', { name: 'Documentation', exact: true });
await expect(navigation).toBeVisible();
await navigation.getByRole('link', { name: 'Quickstart', exact: true }).click();
await expect(navigation).not.toBeVisible();

await page.getByRole('button', { name: 'Search documentation' }).click();
await expect(page.getByRole('dialog')).toBeVisible();
await page.keyboard.press('Escape');
await expect(page.getByRole('dialog')).not.toBeVisible();
});
}

test('matches the local demo documentation and MCP SDK tools', async ({ request }) => {
const docsResponse = await request.get('/api/docs');
const docs = await docsResponse.json();
Expand Down
Loading