astro-docs/README.md
The Nx documentation site built with Astro and Starlight, featuring advanced content management through Markdoc and dynamic plugin documentation generation.
This documentation site leverages Astro's static site generation capabilities with Starlight for documentation-specific features. The architecture consists of:
When creating or reorganizing documentation, follow these 5 principles to determine where content belongs.
The sidebar has 4 top-level sections that follow the user journey:
astro-docs/
├── src/
│ ├── assets/ # Images and static assets to be optimized by Astro
│ │ ├── nx/ # Nx branding assets
│ │ ├── nx-cloud/ # Nx Cloud assets
│ │ └── nx-console/ # Nx Console assets
│ ├── components/ # React and Astro components
│ │ ├── layout/ # Layout components (e.g. Sidebar)
│ │ ├── markdoc/ # Markdoc tag components
│ │ └── utils/ # Utility functions
│ ├── content/ # Documentation content
│ │ ├── banner.json # Banner collection (generated by prebuild-banner)
│ │ ├── docs/ # Main documentation files (.mdoc, .mdx)
│ │ └── approved-community-plugins.json # Powers plugin registry
│ ├── pages/ # Dynamic pages and routes (e.g. devkit)
│ ├── plugins/ # Content loaders and plugins
│ │ ├── *.loader.ts # Dynamic content loaders (e.g. CLI commands and API docs generation)
│ │ └── utils/ # Plugin utilities
│ └── styles/ # Global styles
├── public/ # Static assets not to be optimized by Astro (fonts, robots.txt)
├── astro.config.mjs # Astro configuration
├── markdoc.config.mjs # Markdoc tags configuration
├── sidebar.mts # Sidebar structure definition
└── package.json
The site uses custom content loaders to dynamically generate documentation:
plugin.loader.ts) - Generates official plugin documentation (generators, executors, migrations)community-plugins.loader.ts) - Generates data for plugin registry (e.g. GitHub stars, npm downloads)nx-reference-packages.loader.ts) - Generated data for CNW, Devkit, nx cli (e.g. nx core related things)Regular Documentation (src/content/docs/)
.mdoc (Markdoc) or .mdx (MDX) formatDynamic Plugin Documentation
CLI Documentation
The site includes custom Markdoc tags for rich content.
Note: Starlight supports many Markdown and Markdoc features, such as code blocks, asides, etc.
{% aside %} - Highlighted information boxes{% cardgrid %}, {% card|linkcard %} - Card layouts{% tabs %}, {% tabitem label="some-label" %} - Tab layouts
syncKey so tabs are auto switched to the users preference if it makes sense.{% tabs syncKey="package-manager" %}{% graph %} - Interactive project/task graph visualization{% project_details %} - Project configuration viewer{% youtube %} - YouTube video embeds{% video_player %} - Custom video player{% iframe %} - Generic iframe embeds{% github_repository %} - GitHub repo cards{% stackblitz_button %} - StackBlitz demo launcher{% install_nx_console %} - IDE extension installer{% badge %} - Status/label pills{% metrics %} - Metrics display{% testimonial %} - Customer testimonials# Install dependencies and link workspace packages
# This will build Nx packages as well for API docs
nx serve astro-docs
# Or run astro dev directly
# This will not build Nx packages
cd astro-docs
npx astro dev
# Custom ports (useful for AI agents with git worktrees)
npx astro dev --port 3000
.mdoc file in src/content/docs/Example:
---
title: 'My New Guide'
description: 'Learn how to use this feature'
---
# Introduction
{% aside type="note" title="Important" %}
This is a note about the feature.
{% /aside %}
src/components/markdoc/markdoc.config.mjsPlugin documentation is auto-generated during build. To update:
The sidebar structure is defined in sidebar.mts. To add new sections:
export const sidebar = [
{
label: 'Section Name',
items: [
{
label: 'Page Title',
link: 'path/to/page',
},
// Nested sections
{
label: 'Subsection',
collapsed: true,
items: [...]
}
]
}
];
Note there is a special case for sidebar items appearing in the sidebar. Such as the
Referencesection which is handled via the[sidebar-reference-updater](./src/plugins/sidebar-reference-updater.middleware.ts)middleware.
src/styles/global.cssglobal.cssastro.config.mjsmarkdoc.config.mjssidebar.mtsThe floating banner promotes events/webinars. It's fetched at build time from a Framer CMS page and stored as an Astro content collection.
Set BANNER_URL to point to a Framer page that renders banner JSON:
BANNER_URL=https://your-framer-site.framer.app/api/banners/main
The Framer page should render JSON inside a <pre> tag:
{
"title": "Event Title",
"description": "Event description",
"primaryCtaUrl": "https://...",
"primaryCtaText": "Learn More",
"secondaryCtaUrl": "",
"secondaryCtaText": "",
"enabled": true,
"activeUntil": "2025-12-31T00:00:00.000Z"
}
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Banner headline |
description | string | Yes | Banner body text |
primaryCtaUrl | string | Yes | Primary button URL |
primaryCtaText | string | Yes | Primary button text |
secondaryCtaUrl | string | No | Secondary button URL |
secondaryCtaText | string | No | Secondary button text |
enabled | boolean | Yes | Show/hide the banner |
activeUntil | ISO 8601 | No | Auto-hide after this date |
prebuild-banner target and saved to src/content/banner.json as a collection (array)file() loader and schema validationenabled is false or activeUntil has passed, the banner won't showBANNER_URL is not set, an empty collection is generatedWhen a new major Nx version is released (or about to be released), create a versioned snapshot of the docs site so the previous version remains accessible at {major}.nx.dev (e.g. 22.nx.dev).
node ./scripts/create-versioned-docs.mts 22
This will:
22.6.4)22 containing only the pre-built static site plus minimal scaffolding (root package.json, nx.json, pnpm-lock.yaml, netlify.toml, and a no-op nx-dev project) so Netlify's configured build command succeeds instantlyIf no stable tags exist for that major version, it builds from the current branch.
For Nx 21+, the script builds astro-docs (Astro/Starlight). For legacy Nx 18–20, it builds nx-dev (Next.js with static export) — this path will be removed once those versions are no longer maintained.
--force — overwrite an existing local/remote {major} branch--redirect-to-prod — skip the build and produce a branch that 301s every path to https://nx.dev/docs. Used to retire an old versioned subdomain (e.g. 16.nx.dev) without maintaining its docs# Retire an old versioned site
node ./scripts/create-versioned-docs.mts 16 --redirect-to-prod
git push -f origin 22
Versioned sites are served via Netlify branch deploys of the main nx-dev Netlify site, with custom domains managed in Squarespace.
{major} branch is deployed as a branch deploy of the nx-dev site. The branch's root netlify.toml overrides the UI build settings so Netlify serves the pre-built static files (no rebuild, no @netlify/plugin-nextjs). Add the branch to the site's branch deploy allowlist, then add {major}.nx.dev as a domain alias pointing at the branch deploynx.dev is managed in Squarespace. Add a CNAME for {major} pointing at the Netlify branch deploy hostname