369 lines
13 KiB
Markdown
369 lines
13 KiB
Markdown
# Nx Documentation Site
|
||
|
||
[](https://starlight.astro.build)
|
||
|
||
The Nx documentation site built with Astro and Starlight, featuring advanced content management through Markdoc and dynamic plugin documentation generation.
|
||
|
||
## Architecture Overview
|
||
|
||
This documentation site leverages Astro's static site generation capabilities with Starlight for documentation-specific features. The architecture consists of:
|
||
|
||
### Core Technologies
|
||
|
||
- [**Astro**](https://docs.astro.build) - Static site generator with island architecture
|
||
- [**Starlight**](https://starlight.astro.build) - Documentation theme with built-in navigation, search, and i18n
|
||
- **React** - For implementing UI components
|
||
- **Netlify** - Deployment and hosting
|
||
|
||
### Key Features
|
||
|
||
- [Markdoc](https://markdoc.dev) with custom tags for rich content such as videos, graphs, etc.
|
||
- TailwindCSS for styling in Astro and React components
|
||
- Dynamic API documentation generation from Nx packages and CLI commands
|
||
- Community plugin registry
|
||
|
||
## Information Architecture Principles
|
||
|
||
When creating or reorganizing documentation, follow these 5 principles to determine where content belongs.
|
||
|
||
### 1. Progressive Disclosure (The "Journey" Rule)
|
||
|
||
- **Concept:** Don't overwhelm the user. Reveal complexity only as they advance in their journey.
|
||
- **The Test:** _Is this for the First 30 Minutes (Getting Started), the First 30 Days (Features), or Forever (Reference)?_
|
||
|
||
### 2. Category Homogeneity (The "Scan" Rule)
|
||
|
||
- **Concept:** Items in a list must be of the same "type" (noun, verb, or concept) to reduce cognitive load.
|
||
- **The Test:** _Does this list mix Concepts (Mental Model), Tasks (Update Nx), and Products (React)? If yes, split it._
|
||
|
||
### 3. Type-Based Navigation (The "Intent" Rule)
|
||
|
||
- **Concept:** Separate **Learning** (Narrative/Guides) from **Looking Up** (Reference/API).
|
||
- **The Test:** _Is the user here to learn a workflow (Guide) or look up a flag syntax (Reference)?_
|
||
|
||
### 4. The Pen & Paper Test (The "Theory" Rule)
|
||
|
||
- **Concept:** Distinguish Architecture from Features to keep "Core Concepts" pure.
|
||
- **The Test:** _Can I explain this using only a pen and paper?_
|
||
- **Yes:** It goes in **How Nx Works** (Architecture).
|
||
- **No (I need a terminal):** It goes in **Platform Features** (Feature).
|
||
|
||
### 5. Universal vs. Specific (The "Placement" Rule)
|
||
|
||
- **Concept:** Distinguish Platform features from Ecosystem tools to prevent "Features" from becoming a junk drawer.
|
||
- **The Test:** _Does this feature apply to EVERY user (e.g., Caching, Agents)?_
|
||
- **Yes:** **Platform Features**.
|
||
- **No (Only React users):** **Technologies**.
|
||
|
||
### Sidebar Structure
|
||
|
||
The sidebar has 4 top-level sections that follow the user journey:
|
||
|
||
1. **Getting Started** - Essential setup, tutorials, and core concepts (How Nx Works, Platform Features)
|
||
2. **Technologies** - Framework and tool-specific guides (React, Angular, Node, build tools, test tools)
|
||
3. **Knowledge Base** - Recipes, troubleshooting, and topic-specific guides
|
||
4. **Reference** - Exhaustive facts, no narrative (CLI commands, configuration, API docs)
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
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
|
||
```
|
||
|
||
## Plugins and Loaders
|
||
|
||
### Content Loaders
|
||
|
||
The site uses custom content loaders to dynamically generate documentation:
|
||
|
||
- **PluginLoader** (`plugin.loader.ts`) - Generates official plugin documentation (generators, executors, migrations)
|
||
- **CommunityPluginsLoader** (`community-plugins.loader.ts`) - Generates data for plugin registry (e.g. GitHub stars, npm downloads)
|
||
- **NxReferencePackagesLoader** (`nx-reference-packages.loader.ts`) - Generated data for CNW, Devkit, nx cli (e.g. nx core related things)
|
||
|
||
## Content Management
|
||
|
||
### Content Types
|
||
|
||
1. **Regular Documentation** (`src/content/docs/`)
|
||
- Written in `.mdoc` (Markdoc) or `.mdx` (MDX) format
|
||
- Organized by sections: getting-started, concepts, guides, api
|
||
- File-based routing (filename = URL path)
|
||
|
||
2. **Dynamic Plugin Documentation**
|
||
- Auto-generated from Nx packages
|
||
- Includes generators, executors, and migrations
|
||
- Updated during build process
|
||
- **Note**: Requires a rebuild and restart to reflect changes
|
||
|
||
3. **CLI Documentation**
|
||
- Auto-generated from Nx CLI commands
|
||
- Parsed from actual CLI implementation
|
||
- **Note**: Requires a rebuild and restart to reflect changes
|
||
|
||
### Markdoc Tags
|
||
|
||
The site includes custom Markdoc tags for rich content.
|
||
|
||
**Note**: Starlight supports many Markdown and Markdoc features, such as code blocks, asides, etc.
|
||
|
||
- https://starlight.astro.build/components/using-components/#using-a-component-in-markdoc
|
||
- https://starlight.astro.build/guides/authoring-content
|
||
|
||
#### Layout & Organization
|
||
|
||
- `{% aside %}` - Highlighted information boxes
|
||
- `{% cardgrid %}`, `{% card|linkcard %}` - Card layouts
|
||
- `{% tabs %}`, `{% tabitem label="some-label" %}` - Tab layouts
|
||
- Use the `syncKey` so tabs are auto switched to the users preference if it makes sense.
|
||
- e.g. `{% tabs syncKey="package-manager" %}`
|
||
|
||
#### Interactive Components
|
||
|
||
- `{% graph %}` - Interactive project/task graph visualization
|
||
- `{% project_details %}` - Project configuration viewer
|
||
|
||
#### Media & Embeds
|
||
|
||
- `{% youtube %}` - YouTube video embeds
|
||
- `{% video_player %}` - Custom video player
|
||
- `{% iframe %}` - Generic iframe embeds
|
||
|
||
#### Developer Tools
|
||
|
||
- `{% github_repository %}` - GitHub repo cards
|
||
- `{% stackblitz_button %}` - StackBlitz demo launcher
|
||
- `{% install_nx_console %}` - IDE extension installer
|
||
|
||
#### Content Enhancement
|
||
|
||
- `{% badge %}` - Status/label pills
|
||
- `{% metrics %}` - Metrics display
|
||
- `{% testimonial %}` - Customer testimonials
|
||
|
||
## Development Workflow
|
||
|
||
### Getting Started
|
||
|
||
```bash
|
||
# 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
|
||
```
|
||
|
||
### Adding New Content
|
||
|
||
#### Regular Documentation
|
||
|
||
1. Create `.mdoc` file in `src/content/docs/`
|
||
2. Add frontmatter with title and description
|
||
3. Use Markdoc tags for rich content
|
||
4. File location determines URL structure
|
||
|
||
Example:
|
||
|
||
```markdown
|
||
---
|
||
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 %}
|
||
```
|
||
|
||
#### Adding Custom Markdoc Tags
|
||
|
||
1. Create Astro component in `src/components/markdoc/`
|
||
2. (Optional) Create React component for more complex components, or ones that need to be shared with blog or non-docs pages
|
||
3. Register in `markdoc.config.mjs`
|
||
4. Define attributes and validation
|
||
|
||
### Updating Plugin Documentation
|
||
|
||
Plugin documentation is auto-generated during build. To update:
|
||
|
||
1. Make changes to the plugin's schema/implementation
|
||
2. Run the build process
|
||
3. The loader will automatically fetch and generate updated docs
|
||
|
||
### Sidebar Management
|
||
|
||
The sidebar structure is defined in `sidebar.mts`. To add new sections:
|
||
|
||
```javascript
|
||
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 `Reference` section which is handled via the `[sidebar-reference-updater](./src/plugins/sidebar-reference-updater.middleware.ts)` middleware.
|
||
|
||
## Styling and Theming
|
||
|
||
- Uses Tailwind CSS v4 with Vite plugin
|
||
- Global styles in `src/styles/global.css`
|
||
- Component-specific styles use Tailwind utilities
|
||
- Dark/light mode support built into Starlight and customized in `global.css`
|
||
|
||
## Configuration Files
|
||
|
||
### `astro.config.mjs`
|
||
|
||
- Site configuration
|
||
- Integration setup (React, Markdoc, Starlight)
|
||
- Vite plugins
|
||
- Build options
|
||
|
||
### `markdoc.config.mjs`
|
||
|
||
- Custom tag definitions
|
||
- Attribute validation
|
||
- Component mappings
|
||
|
||
### `sidebar.mts`
|
||
|
||
- Navigation structure
|
||
- Section organization
|
||
- Dynamic content injection points
|
||
|
||
## Banner Configuration
|
||
|
||
The floating banner promotes events/webinars. It's fetched at **build time** from a Framer CMS page and stored as an Astro content collection.
|
||
|
||
### Setup
|
||
|
||
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:
|
||
|
||
```json
|
||
{
|
||
"title": "Event Title",
|
||
"description": "Event description",
|
||
"primaryCtaUrl": "https://...",
|
||
"primaryCtaText": "Learn More",
|
||
"secondaryCtaUrl": "",
|
||
"secondaryCtaText": "",
|
||
"enabled": true,
|
||
"activeUntil": "2025-12-31T00:00:00.000Z"
|
||
}
|
||
```
|
||
|
||
### Schema
|
||
|
||
| 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 |
|
||
|
||
### Behavior
|
||
|
||
- Banner is fetched during `prebuild-banner` target and saved to `src/content/banner.json` as a collection (array)
|
||
- Uses Astro content collection with `file()` loader and schema validation
|
||
- Requires rebuild/redeploy to update the banner
|
||
- Users can dismiss the banner (stored in localStorage)
|
||
- If `enabled` is `false` or `activeUntil` has passed, the banner won't show
|
||
- If `BANNER_URL` is not set, an empty collection is generated
|
||
|
||
## Versioned Docs
|
||
|
||
When 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`).
|
||
|
||
### Creating a Version Snapshot
|
||
|
||
```bash
|
||
node ./scripts/create-versioned-docs.mts 22
|
||
```
|
||
|
||
This will:
|
||
|
||
1. Fetch tags from origin, find the latest stable release for that major (e.g. `22.6.4`)
|
||
2. Checkout that tag, install deps, and build the docs site
|
||
3. Create an orphan git branch `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 instantly
|
||
4. Return to your original branch
|
||
|
||
If 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.
|
||
|
||
#### Flags
|
||
|
||
- `--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
|
||
|
||
```bash
|
||
# Retire an old versioned site
|
||
node ./scripts/create-versioned-docs.mts 16 --redirect-to-prod
|
||
```
|
||
|
||
### Pushing the Branch
|
||
|
||
```bash
|
||
git push -f origin 22
|
||
```
|
||
|
||
### Deployment Setup
|
||
|
||
Versioned sites are served via Netlify branch deploys of the main `nx-dev` Netlify site, with custom domains managed in Squarespace.
|
||
|
||
- **Netlify** — each `{major}` branch is deployed as a [branch deploy](https://docs.netlify.com/site-deploys/overview/#branch-deploy-controls) 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 deploy
|
||
- **Squarespace** — DNS for `nx.dev` is managed in Squarespace. Add a CNAME for `{major}` pointing at the Netlify branch deploy hostname
|