diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ecff98..dc2f30e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 24 cache: npm - run: npm ci @@ -49,3 +49,24 @@ jobs: # Transitive dep vulnerabilities (postcss, sharp, @hono/node-server) # are pinned via root package.json overrides — see commit history. - run: npm audit --audit-level=high + + # The Astro example's Playwright suite: builds the example, serves it, and + # drives a real browser. Unlike the PokeAPI suite above it makes no outside + # requests (it blocks them), so it runs on every push. + astro-e2e: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: npm + + - run: npm ci + + - run: npx playwright install --with-deps chromium + working-directory: examples/astro-docs + + - run: npm run test:e2e --workspace=@inkform/example-astro-docs + diff --git a/.github/workflows/openapi-breaking-changes.yml b/.github/workflows/openapi-breaking-changes.yml index 00f7d72..ed42a83 100644 --- a/.github/workflows/openapi-breaking-changes.yml +++ b/.github/workflows/openapi-breaking-changes.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 24 - run: npm ci diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4785ce..94db100 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ name: Release -# Publishes @inkform/framework or @inkform/cli to public npm. +# Publishes @inkform/framework, @inkform/cli or @inkform/astro to public npm. # # Authentication is npm Trusted Publishing (OIDC) — there is NO npm token # stored in this repository's secrets. GitHub mints a short-lived OIDC token @@ -16,6 +16,7 @@ name: Release # # framework-v0.5.0 → publishes packages/framework # cli-v0.5.0 → publishes packages/cli +# astro-v0.1.0 → publishes packages/astro # # The tag's version MUST equal the version already committed in that # package's package.json — the job refuses to guess. Bump, commit, push, @@ -27,13 +28,14 @@ on: tags: - 'framework-v*' - 'cli-v*' + - 'astro-v*' workflow_dispatch: inputs: package: description: 'Which package to release' required: true type: choice - options: [framework, cli] + options: [framework, cli, astro] dry_run: description: 'Dry run (pack and validate, publish nothing)' required: true @@ -63,7 +65,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 24 cache: npm registry-url: 'https://registry.npmjs.org' @@ -101,6 +103,7 @@ jobs: case "$SLUG" in framework) DIR='packages/framework' ;; cli) DIR='packages/cli' ;; + astro) DIR='packages/astro' ;; *) echo "::error::Unrecognized release target '$SLUG'"; exit 1 ;; esac diff --git a/.gitignore b/.gitignore index c5ebfa2..9bbc216 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ yarn-error.log* .turbo/ *.tsbuildinfo .vercel +.astro/ diff --git a/CHANGELOG.md b/CHANGELOG.md index b3d2c1e..7ed1f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,51 @@ All notable changes to this project are documented here. Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions track `packages/framework`'s own `package.json`. +## [Unreleased] + +## [0.8.0] — 2026-10-23 + +### Added + +- **`@inkform/astro`** (new package, 0.1.0): an Astro 7 integration that + serves a content folder from any Astro site under one base path: docs pages + from docs.json, the native API Reference, blog, changelog, `llms.txt`, and + Pagefind search. React renders the framework's components at build time + only. See [`packages/astro`](./packages/astro/README.md) and its + [CHANGELOG](./packages/astro/CHANGELOG.md). +- **`@inkform/framework/mdx-options`**: the remark/rehype plugin lists and + next-mdx-remote options `` renders with, plus `compileMdx(source, + components)` for hosts that render MDX to a React element themselves. Unlike + passing the component map straight to compiled MDX, `compileMdx` resolves + every capitalized component the source uses through the map, so a + `mdxComponents()` map's fallback renders unknown components instead of + failing. +- **`@inkform/framework/routes`**: `apiTab(config)`, `apiTabSlug(config)` + (`"API Reference"` → `api-reference`, the rule every theme's `apiBasePath()` + uses), `docRouteSlugs(config)` and `joinHref(base, slug)`. Pure, no IO. +- **`basePath` option for `buildLlmsTxt()`**: prefixes doc, blog and changelog + links for a site that serves its docs under a path (`/docs/quickstart`). + Defaults to `''`, so existing output is unchanged. +- Subpath exports for browser code outside React: `./mermaid/render` + (`renderDiagram`, `themeConfig`), `./openapi-render/try-it` (the Try It + request executor) and `./openapi-render/sample` (`sampleFromSchema`). + +### Changed + +- `next` is an optional peer dependency. Nothing in the framework imports it, + and npm no longer installs Next.js into a site that only uses the Astro + integration or the framework's loaders. +- `` reads its plugins and options from `./mdx-options`; its output is + unchanged. +- `slugify` lives in a pure `./slug` module; `./content` re-exports it. +- The root `vite` override now applies to `vitest` only (`^7.3.7`), since + Astro 7 needs Vite 8. +- Templates and examples move to Next.js 16.4.2, for the critical advisories + in 16.0.0–16.4.0 (GHSA-2464-fhr4-w9xw, GHSA-673q-mjm6-r5xr) and the Server + Actions denial of service (GHSA-p3m5-59mp-jv5r). Lockfile fixes for + DOMPurify (GHSA-cg2g-xh64-v4q7 and two more) and `ip-address` + (GHSA-rxp7-6hxx-x8q5). `npm audit --audit-level=high` is clean again. + ## [0.7.0] — 2026-10-22 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3df7a5..0de415d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,6 +42,7 @@ npm install packages/ framework/ @inkform/framework — the MDX + OpenAPI engine (published) cli/ @inkform/cli — the npx scaffolder (published) + astro/ @inkform/astro — Astro 7 integration (published) templates/ canopy/ @inkform/theme-canopy — dark, green accent (default) @@ -52,13 +53,15 @@ examples/ pokeapi-docs/ Full PokéAPI docs site + Playwright e2e tests markdown-docs/ Markdown/MDX feature reference inkform-docs/ This framework's own documentation (dogfooded) + astro-docs/ An Astro host app using @inkform/astro + Playwright tests archive/templates/ Legacy themes (aurora, fern, cedar, mono, base, galley) preserved for reference — not scaffoldable via CLI ``` -Only `@inkform/framework` and `@inkform/cli` are published to npm. Themes and -examples are private workspace packages used for development and demos. +Only `@inkform/framework`, `@inkform/cli` and `@inkform/astro` are published +to npm. Themes and examples are private workspace packages used for +development and demos. --- @@ -67,7 +70,7 @@ examples are private workspace packages used for development and demos. ```bash npm install # install every workspace + run postinstall prune npm run typecheck # typecheck all packages -npm test # framework unit tests (Vitest) +npm test # framework + Astro integration unit tests (Vitest) npm run build # next build across every theme + example npm run build:examples # build the three demo sites only ``` @@ -100,15 +103,17 @@ cd /tmp/test-docs && npm install && npm run dev Override the GitHub ref the CLI downloads from with `INKFORM_DOCS_REF=` when testing against a fork or feature branch. -**End-to-end tests** (manual — deliberately excluded from CI): +**End-to-end tests:** ```bash -npm run test:e2e --workspace=@inkform/example-pokeapi +npm run test:e2e --workspace=@inkform/example-pokeapi # manual, not in CI +npm run test:e2e --workspace=@inkform/example-astro-docs # also runs in CI ``` -The e2e suite makes one real request to the live PokéAPI per run. Fine for a +The PokéAPI suite makes one real request to the live PokéAPI per run. Fine for a developer running it locally once, but not wired into CI to avoid hammering a -free, community-funded API on every push. +free, community-funded API on every push. The Astro suite builds and serves its +own example and blocks every request that leaves it, so CI runs it. --- diff --git a/README.md b/README.md index 73c7035..aec5acb 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,14 @@ The binary is also available as `inkform-docs` when installed globally. To embed the engine in an existing Next.js app or build a custom theme from scratch, see [`packages/framework`](./packages/framework) and [`packages/framework/ARCHITECTURE.md`](./packages/framework/ARCHITECTURE.md). +**On Astro?** [`@inkform/astro`](./packages/astro) serves the same content folder from any Astro 7 site, under a path like `/docs`, with no Next.js and no React in the browser: + +```ts +// astro.config.ts +import inkform from '@inkform/astro'; +export default defineConfig({ integrations: [inkform({ base: '/docs' })] }); +``` + ## Features | | | @@ -106,12 +114,14 @@ This repository is an npm workspaces monorepo. Published packages ship to npm; e | --- | --- | :---: | --- | | [`packages/framework`](./packages/framework) | `@inkform/framework` | ✓ | The MDX + OpenAPI rendering engine | | [`packages/cli`](./packages/cli) | `@inkform/cli` | ✓ | `npx` scaffolder (`inkform-docs` binary) | +| [`packages/astro`](./packages/astro) | `@inkform/astro` | ✓ (not yet released) | Astro 7 integration: the same content, served from an Astro site | | [`templates/canopy`](./templates/canopy) | `@inkform/theme-canopy` | | Canopy theme | | [`templates/shadcn`](./templates/shadcn) | `@inkform/theme-shadcn` | | Shadcn theme | | [`templates/galley`](./templates/galley) | `@inkform/theme-galley` | | Galley theme | | [`examples/pokeapi-docs`](./examples/pokeapi-docs) | `@inkform/example-pokeapi` | | Full PokéAPI docs site (OpenAPI + e2e tests) | | [`examples/markdown-docs`](./examples/markdown-docs) | `@inkform/example-markdown` | | Markdown/MDX feature reference | | [`examples/inkform-docs`](./examples/inkform-docs) | `@inkform/example-inkform-docs` | | This framework's own docs (dogfooded) | +| [`examples/astro-docs`](./examples/astro-docs) | `@inkform/example-astro-docs` | | An Astro host app with docs under `/docs` (Playwright tests) | ## Develop in this repo @@ -122,7 +132,7 @@ git clone https://github.com/inkform-dev/framework.git cd framework npm install # installs all workspaces npm run typecheck # typecheck every package -npm test # framework unit tests (Vitest) +npm test # framework and Astro integration unit tests (Vitest) npm run build # build all workspaces npm run build:examples # build the three demo sites only ``` diff --git a/examples/astro-docs/.gitignore b/examples/astro-docs/.gitignore new file mode 100644 index 0000000..aaa9103 --- /dev/null +++ b/examples/astro-docs/.gitignore @@ -0,0 +1,2 @@ +test-results/ +playwright-report/ diff --git a/examples/astro-docs/README.md b/examples/astro-docs/README.md new file mode 100644 index 0000000..704e9f4 --- /dev/null +++ b/examples/astro-docs/README.md @@ -0,0 +1,28 @@ +# Astro docs example + +An Astro 7 app that serves Inkform docs under `/docs` with +[`@inkform/astro`](../../packages/astro). It's shaped like a real host: its +home page (`src/pages/index.astro`) is its own, rendered on demand with a React +island; it runs with `output: 'server'` and the Node adapter; and Astro's +`security.csp` is on. + +```bash +npm run dev --workspace=@inkform/example-astro-docs # http://localhost:4321/docs +npm run build --workspace=@inkform/example-astro-docs +npm run start --workspace=@inkform/example-astro-docs # serves the build +npm run test:e2e --workspace=@inkform/example-astro-docs # Playwright: builds, serves, tests +``` + +- `content/docs/` holds `docs.json`, the pages and `openapi.json`. + [`essentials/components.mdx`](./content/docs/essentials/components.mdx) uses + every component in the kit. +- `content/blog/` and `content/changelog/` turn on `/docs/blog` and + `/docs/changelog`. +- [`e2e/docs.spec.ts`](./e2e/docs.spec.ts) checks that every page renders with + no CSP violation, that tabs, code groups, accordions, the TOC, the theme + toggle, the drawer, diagrams, the API sample pickers and Try It work, that + search finds pages, and that the docs pages load no React. + +`cookie` is a direct dependency only because of this monorepo's hoisting: +another workspace puts an older `cookie` at the root, where Astro's server +build would find it. A standalone app doesn't need it. diff --git a/examples/astro-docs/astro.config.ts b/examples/astro-docs/astro.config.ts new file mode 100644 index 0000000..d5e204c --- /dev/null +++ b/examples/astro-docs/astro.config.ts @@ -0,0 +1,29 @@ +import node from '@astrojs/node'; +import react from '@astrojs/react'; +import inkform from '@inkform/astro'; +import { defineConfig } from 'astro/config'; + +// A host app shaped like the forms app: on-demand pages by default, React +// islands on its own pages, Astro's CSP on. The docs live under /docs and +// are prerendered. +export default defineConfig({ + output: 'server', + adapter: node({ mode: 'standalone' }), + integrations: [react(), inkform({ base: '/docs', contentRoot: './content', mermaid: true })], + // This site has no Markdown pages of its own. Docs code blocks are + // highlighted by the integration, which keeps their colors CSP-safe. + markdown: { syntaxHighlight: false }, + security: { + csp: { + algorithm: 'SHA-256', + directives: [ + "default-src 'self'", + "img-src 'self' data:", + // The API Reference's Try It console calls the API from the browser. + "connect-src 'self' https://api.example.com", + 'frame-src https://www.youtube.com', + "object-src 'none'", + ], + }, + }, +}); diff --git a/examples/astro-docs/content/blog/hello-astro.mdx b/examples/astro-docs/content/blog/hello-astro.mdx new file mode 100644 index 0000000..2de067d --- /dev/null +++ b/examples/astro-docs/content/blog/hello-astro.mdx @@ -0,0 +1,17 @@ +--- +title: Inkform on Astro +date: 2026-10-23 +author: Inkform +description: The same content folder, now served by an Astro site. +tags: [release] +--- + +The Astro integration renders the framework's components at build time and +ships no React to the browser. + +## Why + +Some sites are Astro apps. Their docs can now live in the same app, under +`/docs`, with the same `docs.json`. + +See the [Quickstart](/quickstart) to set it up. diff --git a/examples/astro-docs/content/changelog/2026-10-01-v0-0-1.mdx b/examples/astro-docs/content/changelog/2026-10-01-v0-0-1.mdx new file mode 100644 index 0000000..581b33f --- /dev/null +++ b/examples/astro-docs/content/changelog/2026-10-01-v0-0-1.mdx @@ -0,0 +1,11 @@ +--- +title: First sketch +date: 2026-10-01 +version: 0.0.1 +--- + +A route per `docs.json` page. + +```ts +injectRoute({ pattern: '/docs/[...slug]', entrypoint: '…' }); +``` diff --git a/examples/astro-docs/content/changelog/2026-10-23-v0-1-0.mdx b/examples/astro-docs/content/changelog/2026-10-23-v0-1-0.mdx new file mode 100644 index 0000000..bb0f100 --- /dev/null +++ b/examples/astro-docs/content/changelog/2026-10-23-v0-1-0.mdx @@ -0,0 +1,9 @@ +--- +title: The Astro integration +date: 2026-10-23 +version: 0.1.0 +--- + +- Docs pages, the API Reference, blog and changelog under one base path. +- Pagefind search, built after `astro build`. +- `llms.txt` and `llms-full.txt`. diff --git a/examples/astro-docs/content/docs/docs.json b/examples/astro-docs/content/docs/docs.json new file mode 100644 index 0000000..10a5589 --- /dev/null +++ b/examples/astro-docs/content/docs/docs.json @@ -0,0 +1,46 @@ +{ + "name": "Inkform on Astro", + "version": "1.0.0", + "logo": { "light": "/logo-light.svg", "dark": "/logo-dark.svg" }, + "favicon": "/favicon.svg", + "colors": { "primary": "#c24e3d" }, + "navbarLinks": [{ "name": "GitHub", "href": "https://github.com/inkform-dev/framework" }], + "cta": { "label": "Home", "href": "/" }, + "tabs": [ + { + "tab": "Guides", + "navigation": [ + { + "group": "Get Started", + "pages": [ + { "title": "Introduction", "slug": "", "file": "index.mdx", "icon": "book-open" }, + { "title": "Quickstart", "slug": "quickstart", "file": "quickstart.mdx", "icon": "rocket" }, + { + "title": "Host an Astro site", + "slug": "guides/astro", + "file": "guides/astro.mdx", + "icon": "layers", + "children": [ + { "title": "Content Security Policy", "slug": "guides/csp", "file": "guides/csp.mdx", "icon": "shield" } + ] + } + ] + }, + { + "group": "Essentials", + "pages": [ + { "title": "Components", "slug": "essentials/components", "file": "essentials/components.mdx", "icon": "blocks" }, + { "title": "Markdown Syntax", "slug": "essentials/markdown", "file": "essentials/markdown.mdx", "icon": "type" }, + { "title": "Code Blocks", "slug": "essentials/code-blocks", "file": "essentials/code-blocks.mdx", "icon": "code" }, + { "title": "Navigation", "slug": "essentials/navigation", "file": "essentials/navigation.mdx", "icon": "map" } + ] + } + ] + }, + { + "tab": "API Reference", + "openapi": "openapi.json", + "apiReference": { "renderer": "native" } + } + ] +} diff --git a/examples/astro-docs/content/docs/essentials/code-blocks.mdx b/examples/astro-docs/content/docs/essentials/code-blocks.mdx new file mode 100644 index 0000000..402515d --- /dev/null +++ b/examples/astro-docs/content/docs/essentials/code-blocks.mdx @@ -0,0 +1,55 @@ +--- +title: Code Blocks +description: Display inline code and richly highlighted code blocks. +--- + +# Code Blocks + +Display inline code and fenced code blocks with syntax highlighting. + +## Inline code + +To denote a `word` or `phrase` as code, wrap it in backticks (`` ` ``). + +## Code blocks + +Fence code with triple backticks and a language for highlighting. Add +`title="…"` after the language to label the block: + +```js title="app.js" +export function greet(name) { + return `Hello, ${name}!`; +} +``` + +## Code groups + +Group related snippets — different languages or package managers — into a single +tabbed block: + + +```bash title="npm" +npm install @inkform/astro +``` + +```bash title="pnpm" +pnpm add @inkform/astro +``` + +```bash title="yarn" +yarn add @inkform/astro +``` + + +## Highlighting + +Code blocks are highlighted with [Shiki](https://shiki.style), the same engine +VS Code uses, so colors match your editor and stay readable in light and dark +mode. + +```ts title="server.ts" +import { parseOpenApi } from '@inkform/framework/openapi'; + +const model = parseOpenApi(rawSpec); +console.log(model.operations.length, 'endpoints'); +``` diff --git a/examples/astro-docs/content/docs/essentials/components.mdx b/examples/astro-docs/content/docs/essentials/components.mdx new file mode 100644 index 0000000..1d493f6 --- /dev/null +++ b/examples/astro-docs/content/docs/essentials/components.mdx @@ -0,0 +1,150 @@ +--- +title: Components +description: Every component in the kit, available in any .mdx file without imports. +--- + +# Components + +Each section below uses one component. Nothing on this page imports anything. + +## Callouts + +A `Callout` with `type="info"`. +A note. +A tip. +Some information. +Something to be careful about. +Something that breaks things. +Something that worked. + +:::warning +A callout written as a directive, `:::warning`. +::: + +## Cards + + + Prerendered pages, client-side search. + One token file restyles everything. + A card that links somewhere. + + + + Cards can sit on their own, too. + + +## Columns + + +
The first column holds any Markdown.
+
So does the second one.
+
+ +## Steps + + + Add an `.mdx` file under `content/docs`. + List it in `docs.json`. + Build and deploy. + + +## Tabs + + + Press ⌘ K to open search. + Press Ctrl K to open search. + Press Ctrl K there too. + + +## Accordions + + + Yes. The sidebar becomes a drawer on small screens. + Yes, with the toggle in the header. + + + + Accordions work without JavaScript: they're `
` elements. + + +## Code groups + + +```bash title="npm" +npm install @inkform/astro +``` + +```bash title="pnpm" +pnpm add @inkform/astro +``` + +```bash title="yarn" +yarn add @inkform/astro +``` + + +## Parameter and response fields + + + The maximum number of results to return. + + + + The plant's id. + + + + The id of the created record. + + + + Who owns it. + + +## Frames and embeds + + + ![Hero](/hero.svg) + + + + +## Tooltips + +Hover SSG to see its tooltip. + +## Diagrams + +```mermaid title="A request, end to end" +sequenceDiagram + Reader->>Docs: Open /docs/quickstart + Docs-->>Reader: Prerendered HTML + Reader->>Pagefind: Search "install" + Pagefind-->>Reader: Results +``` + + B[Build]\n B --> C[Ship]"} caption="Written as a component" /> + +## API links + + links to its operation page, and so does +this one. + + + +## Blog parts + + + + + + + +## Placeholders + + + +A component the kit doesn't have shows up as a visible marker instead of +breaking the build: + +Its children still render. diff --git a/examples/astro-docs/content/docs/essentials/markdown.mdx b/examples/astro-docs/content/docs/essentials/markdown.mdx new file mode 100644 index 0000000..c0e86da --- /dev/null +++ b/examples/astro-docs/content/docs/essentials/markdown.mdx @@ -0,0 +1,65 @@ +--- +title: Markdown Syntax +description: Text, titles, and styling in standard Markdown. +--- + +# Markdown Syntax + +Write content in standard Markdown — the framework renders it with GitHub-flavored +extensions, callouts, and syntax-highlighted code. + +## Titles + +Use `#` headings for sections. Second- and third-level headings (`##`, `###`) +appear in the table of contents on the right. + +```md +## Section title +### Subsection title +``` + +## Text formatting + +We support most Markdown formatting. Wrap text to style it: + +| Style | How to write it | Result | +| --- | --- | --- | +| Bold | `**bold**` | **bold** | +| Italic | `_italic_` | _italic_ | +| Strikethrough | `~~struck~~` | ~~struck~~ | +| Code | `` `code` `` | `code` | + +## Links + +Link to [another page](/quickstart) with relative paths, or to +[an external site](https://example.com) with full URLs. + +## Blockquotes + +> The best way to predict the future is to invent it. + +## Lists + +- Unordered items +- Nest them by indenting + - Like this + +1. Ordered items +2. Count automatically + +## Callouts + +Use callouts to draw attention. They come in several flavors: + +This is a note — neutral, informational. +This is a tip — a helpful suggestion. +This is a warning — proceed carefully. +This is a success message — all good. + +You can also write callouts as directives: + +```md +:::info +An info callout written as a directive. +::: +``` diff --git a/examples/astro-docs/content/docs/essentials/navigation.mdx b/examples/astro-docs/content/docs/essentials/navigation.mdx new file mode 100644 index 0000000..f85d3f2 --- /dev/null +++ b/examples/astro-docs/content/docs/essentials/navigation.mdx @@ -0,0 +1,68 @@ +--- +title: Navigation +description: Configure tabs, groups, pages, and the API Reference in docs.json. +--- + +# Navigation + +Your site's structure lives in `content/docs/docs.json`. It controls the top +tabs, the sidebar groups, and the API Reference. + +## Groups and pages + +The simplest config is a list of groups, each with pages: + +```json docs.json +{ + "name": "My Docs", + "navigation": [ + { + "group": "Get Started", + "pages": [ + { "title": "Introduction", "slug": "", "file": "index.mdx" }, + { "title": "Quickstart", "slug": "quickstart", "file": "quickstart.mdx" } + ] + } + ] +} +``` + + + `slug` is the URL path (an empty string is the index). `file` is the MDX file + relative to `content/docs`. Nest pages with a `children` array. + + +## Tabs + +Add top-bar tabs to split Guides from your API Reference: + +```json docs.json +{ + "tabs": [ + { "tab": "Guides", "navigation": [ /* groups */ ] }, + { "tab": "API Reference", "openapi": "openapi.json" } + ] +} +``` + +## API Reference from OpenAPI + +Point a tab's `openapi` field at a spec file (JSON or YAML) in `content/docs`. +The framework generates the entire API Reference — endpoint list, parameters, +request/response schemas, a cURL sample, and a live "Try it" playground — from +the spec. + + + This is the standard: API docs come from OpenAPI, everything else is MDX. Keep + your spec accurate and your reference stays accurate for free. + + +## Top bar + +```json docs.json +{ + "navbarLinks": [{ "name": "Blog", "href": "/blog" }], + "anchors": [{ "name": "GitHub", "href": "https://github.com/you/repo", "icon": "github" }], + "cta": { "label": "Dashboard", "href": "https://app.example.com" } +} +``` diff --git a/examples/astro-docs/content/docs/guides/astro.mdx b/examples/astro-docs/content/docs/guides/astro.mdx new file mode 100644 index 0000000..7b49a7e --- /dev/null +++ b/examples/astro-docs/content/docs/guides/astro.mdx @@ -0,0 +1,31 @@ +--- +title: Host an Astro site +description: How the docs fit into an Astro app that serves other things too. +--- + +# Host an Astro site + +The integration adds routes under its `base` and nothing else. Your pages, +middleware and API routes keep working. + +## Routes + +| Path | What | +| --- | --- | +| `/docs/…` | Docs pages from `docs.json` | +| `/docs/api-reference/…` | The API Reference | +| `/docs/blog/…`, `/docs/changelog` | When those folders have entries | +| `/docs/llms.txt`, `/docs/llms-full.txt` | For LLMs and agents | + +## Rendering + +Every docs route is prerendered, including in an `output: 'server'` app. React +renders the framework's components at build time; the pages ship a few small +scripts and no React. + +```mermaid title="Build" +graph LR + A[content/docs] --> B[MDX + kit] + B --> C[Static HTML] + C --> D[Pagefind index] +``` diff --git a/examples/astro-docs/content/docs/guides/csp.mdx b/examples/astro-docs/content/docs/guides/csp.mdx new file mode 100644 index 0000000..2b8d093 --- /dev/null +++ b/examples/astro-docs/content/docs/guides/csp.mdx @@ -0,0 +1,19 @@ +--- +title: Content Security Policy +description: What docs pages add to Astro's security.csp, and why. +--- + +# Content Security Policy + +With `security.csp` on, Astro hashes the scripts and styles it bundles. Docs +pages add these on their own pages only: + +- the hash of the inline script that sets light or dark mode before paint, +- the hash of one `