You're viewing the dependabot/github_actions/pnpm/action-setup-6 deployment.

pmndrs/docs

Documentation generator for pmndrs/* projects.

npm@pmndrs/docs storybook chromaticstorybook

Summary

A static MDX documentation generator, with a GitHub reusable workflow. It is primarily used for some pmndrs/* projects, but will work for anyone.

Gutenberg lithography

Those projects are known to be using this generator.

INSTALL

Clone the repository

$ git clone https://github.com/pmndrs/docs.git
$ cd docs

Use the right Node version

With nvm, which reads the repository's .nvmrc:

$ nvm install
$ nvm use
$ node -v # make sure your version satisfies package.json#engines.node

nb: if you want this node version to be your default nvm's one: nvm alias default node

Install the dependencies

$ pnpm install

Configuration

Environment variables configure the website. For MDX extensions, add docs.config.ts in the current working directory: components registers React components and scope exposes named data. Both fields are optional. See Custom components and data for the typed configuration and a live example.

Important

Variables default to "" (empty) unless a fallback is documented below.

vardescriptionexample
MDX*Path to *.mdx folder
NB: can be relative or absolute
docs or ~/code/myproject/documentation
DOCS_CONFIGPath to the component and data configuration, relative to the current working directory or absolute. Unset: look for docs.config.ts there; no file keeps the built-in renderer. CLI: --config overrides this variable.config/docs.config.ts
NEXT_PUBLIC_LIBNAME*Library nameReact Three Fiber
NEXT_PUBLIC_LIBNAME_SHORTLibrary short namer3f
BASE_PATHBase path for the final URL/react-three-fiber
HOME_REDIRECTWhere the home should redirect/getting-started/introduction
MDX_BASEURLBase URL for inlining relative images, or a path (e.g. /react-three-fiber) for root-relative oneshttp://localhost:60141or https://github.com/pmndrs/react-three-fiber/raw/master/docs
SOURCECODE_BASEURLBase URL for sourcecode: code path, and for relative links to repository files out of MDX: the tree of the repository root (as the reusable workflow sets it)https://github.com/pmndrs/react-three-fiber/tree/main
EDIT_BASEURLBase URL for displaying "Edit this page" URLshttps://github.com/pmndrs/react-three-fiber/edit/master/docs
NEXT_PUBLIC_URLFinal URL of the published websitehttps://pmndrs.github.io/react-three-fiber
ICONEmoji or image to use as (fav)icon (path local to MDX)
NB: also published at /icon.svg, which the libraries menu of the other pmndrs docs sites shows
🇨🇭 or /icon.png or /favicon.ico
LOGOLogo src/path (either FQURL or local to MDX path)/logo.png or https://worldvectorlogo.com/r3f.png
GITHUBGithub URL (its star count shows next to the header link)https://github.com/pmndrs/react-three-fiber
DISCORDDiscord URLhttps://discord.com/channels/740090768164651008/740093168770613279
SPONSOR_CARD"Sponsor Poimandres" card under the table of contents, on unless false -- for a site that is not a pmndrs libraryfalse
LIBS_MENUMenu of the pmndrs libraries behind the site name in the header, on unless false: the name is then a plain link homefalse
THEME_PRIMARYPrimary accent color (unset: the pmndrs lime #CAF543)#323e48
THEME_SCHEMETheme scheme, moot while color match is on (see THEME_COLOR_MATCH)content or expressive or fidelity or monochrome or neutral or tonalSpot or vibrant
THEME_CONTRASTTheme contrast -- value between -1 and 10 or -1 or 1 or -.6
THEME_NOTE"note" color#1f6feb
THEME_TIP"tip" color#238636
THEME_IMPORTANT"important" color#8957e5
THEME_WARNING"warning" color#d29922
THEME_CAUTION"caution" color#da3633
THEME_CUSTOM_COLORSCustom colors of the theme, name:hex[:blend] comma-separated -- each a role, <Color role="brand" />, :blend harmonizing it with the primarybrand:#ff2d95:blend,status:#17b26a
THEME_COLOR_MATCHEach core and custom color rendered true to its own input (Material Theme Builder's "Color match"), on unless false: it takes precedence over THEME_SCHEME, readers can toggle it from the sidebar, and the scheme toggle is hidden while color match is ontrue or false
THEME_SECONDARYSecondary color, instead of the one derived from the primary#B03A3A
THEME_TERTIARYTertiary color, instead of the one derived from the primary#7D5260
THEME_NEUTRALNeutral color (the surfaces), instead of the pmndrs warm grey #c1b793#c1b793
THEME_NEUTRAL_VARIANTNeutral variant color (the tinted surfaces, outlines), instead of the pmndrs #495720#495720
THEME_ERRORError color, instead of the pmndrs red #FF4980#FF4980
THEME_STORYBOOK"storybook" color#ff4785
THEME_NPM"npm" color#cb3837
THEME_CHROMATIC"chromatic" color#fc521f
CONTRIBUTORS_PATGitHub token for contributors API and the header star count (see: https://docs.github.com/en/rest/collaborators/collaborators?apiVersion=2022-11-28#list-repository-collaborators)ghp_1234567890
LIB_VERSIONVersion label in the sidebar footer (default: git describe --tags)v1.2.3
TAG_MATCHTags the version label is read from (git describe --match)v*.*.*
VERSION_URL_TEMPLATEURL of a branch deployment; enables the version switcherhttps://mylib-git-{branch:vercel}-myteam.vercel.app
VERSION_PRODUCTION_BRANCHProduction branch (default: main)master
VERSION_PRODUCTION_URLProduction branch URL (default: NEXT_PUBLIC_URL)https://docs.pmnd.rs
VERSION_BRANCHESRegex of the branches the switcher offers^(main|next|v\d+)$
VERSION_BRANCHES_LISTBranches the switcher offers, instead of the remote'smain,next,v9

* Required

Readers can re-seed THEME_PRIMARY, THEME_SCHEME, THEME_CONTRAST and THEME_COLOR_MATCH from the theme controls in the sidebar. An overridden control is outlined, and a double-click (or Delete) brings the site's value back.

MDX_BASEURL

Given a advanced/introduction.mdx file in the MDX folder:

advanced/introduction.mdx
![](dog.png)

becomes (for a MDX_BASEURL=http://localhost:60141 value):

![](http://localhost:60141/advanced/dog.png)

http://localhost:60141 being the MDX folder served.

Tip

When deployed on GitHub Pages, MDX_BASEURL will typically value something like https://github.com/pmndrs/uikit/raw/main/docs, thanks to build.yml rule.

MDX_BASEURL can also be a path only, root-relative, such as /react-three-fiber (or / for a site served at the root of its domain): the MDX folder then has to be served at that path, on the same host as the website. URLs then come out root-relative too:

![](/react-three-fiber/advanced/dog.png)

so they follow the website onto any host it answers on (e.g. both the deployment and the branch URL of a Vercel preview), where an absolute URL would point to one host only.

Note

With a path, the image frontmatter (og:image) is made absolute against the origin of NEXT_PUBLIC_URL, when set, since social images need an absolute URL.

THEME_*

We implement m3 design system, using material-theme-builder.

This is an embed iframe of material-theme-builder's <Mtb> story.

Note
  • Material Color for more information
  • The defaults are pmndrs/design-system's palette: the lime #CAF543 under color match, a warm grey neutral, and seven colors every site gets as custom colors, lime, teal, cyan, purple, red, orange and yellow (<Color role="teal" />).
  • THEME_PRIMARY is the seed: the secondary and tertiary colors are derived from it, unless the site gives its own (THEME_SECONDARY, THEME_TERTIARY). The neutral, neutral variant and error colors are the pmndrs ones, unless the site gives its own (THEME_NEUTRAL, THEME_NEUTRAL_VARIANT, THEME_ERROR).
  • THEME_COLOR_MATCH (on unless "false") is Material Theme Builder's "Color match - Stay true to my color inputs": each core and custom color keeps its input's chroma instead of being toned down to the scheme's, so THEME_SCHEME is ignored and the scheme toggle is hidden while color match is on. Readers can toggle color match from the sidebar. A custom color with :blend is still harmonized first.
VERSION_*, LIB_VERSION, TAG_MATCH
  • Label: git describe --tags (eg. v10.7.9, v10.7.9-3-ga1b2c3d), or <branch>@<shortsha> without tags. LIB_VERSION overrides it.
  • TAG_MATCH narrows the tags:
repo tagsTAG_MATCH
v10.7.9, v10v*.*.*
leva@0.10.1, other@1.0leva@*
  • VERSION_URL_TEMPLATE enables the switcher: the label lists the branches, each leading to the same page on its deployment. Full public URL (base path included), with a placeholder:
placeholderfeat/Dark_mode becomesforexample
{branch}feat-dark-modeURLs you createhttps://docs-git-{branch}-pmndrs.vercel.app
{branch:vercel}feat-darkmodeVercel Git integrationhttps://mylib-git-{branch:vercel}-myteam.vercel.app
{branch:raw}feat%2FDark_modea path or query stringhttps://example.com/preview?branch={branch:raw}
  • A hostname label holds 63 characters at most. When a long branch would overflow it, {branch:vercel} follows Vercel's own truncation, and {branch} keeps its slug's first 63 - (rest of the label) - 7 characters, drops a trailing -, and appends - and the first 6 hex characters of the branch name's SHA-256 (printf %s "$branch" | sha256sum | cut -c1-6): eg. claude/pages-shadcn-tailwind-prep-98d23c in https://design-system-git-{branch}-pmndrs.vercel.app becomes design-system-git-claude-pages-shadcn-tailwind-pr-2675d4-pmndrs. Outside the hostname, {branch} is never cut. To alias a deployment there, pmndrs-docs version-url prints the URL (--hostname: the hostname alone), or see the reusable workflow's version_hostname output.

  • VERSION_PRODUCTION_BRANCH leads to VERSION_PRODUCTION_URL; every other branch shows a banner linking to production.

  • Branches: the remote's, minus dependabot/, renovate/, changeset-release/. VERSION_BRANCHES replaces that filter, VERSION_BRANCHES_LIST the whole list. Read at build time.

Important
  • The per-branch URLs are yours to create: Vercel's Git integration does, vercel deploy does not (vercel alias set, see ci.yml).
  • Git needs full history and tags (fetch-depth: 0).

Usage

dev

Run dev.sh. The site listens on PORT (default 3000), the MDX folder on any free port, so several checkouts can run side by side:

$ ./dev.sh

which is:

dev.sh
#!/bin/sh

trap 'kill -9 0' SIGINT

export PORT=${PORT:-3000}
export _PORT=$(node -e 'const s = require("net").createServer().listen(0, () => { console.log(String(s.address().port)); s.close() })')

export MDX=docs
export NEXT_PUBLIC_LIBNAME="docs"
export NEXT_PUBLIC_LIBNAME_SHORT="docs"
export BASE_PATH=
export HOME_REDIRECT=
export MDX_BASEURL=http://localhost:$_PORT
export SOURCECODE_BASEURL="vscode://file$(pwd)"
export EDIT_BASEURL="vscode://file$(pwd)/docs"
export NEXT_PUBLIC_URL=
export ICON=
export LOGO=gutenberg.jpg
export GITHUB=https://github.com/pmndrs/docs
export DISCORD=https://discord.com/channels/740090768164651008/1264328004172255393
export CONTRIBUTORS_PAT=

npx serve $MDX -p $_PORT --no-port-switching --no-clipboard &

pnpm run dev &

wait

Then go to: http://localhost:3000

When running the engine against another repository, set both MDX and DOCS_CONFIG; the configuration is discovered from the working directory, not the MDX folder:

MDX=/path/to/library/docs DOCS_CONFIG=/path/to/library/docs.config.ts pnpm dev
Tip

If HOME_REDIRECT= empty, / will not redirect, and instead displays an index of libraries.

build

Run start.sh, same ports:

$ ./start.sh

which is:

start.sh
#!/bin/sh

trap 'kill -9 0' SIGINT

rm -rf out

export PORT=${PORT:-3000}
export _PORT=$(node -e 'const s = require("net").createServer().listen(0, () => { console.log(String(s.address().port)); s.close() })')

export MDX=docs
export NEXT_PUBLIC_LIBNAME="docs"
export NEXT_PUBLIC_LIBNAME_SHORT="docs"
export BASE_PATH=
export HOME_REDIRECT=
export MDX_BASEURL=http://localhost:$_PORT
export SOURCECODE_BASEURL=
export EDIT_BASEURL=
export NEXT_PUBLIC_URL=
export ICON=
export LOGO=gutenberg.jpg
export GITHUB=https://github.com/pmndrs/docs
export DISCORD=https://discord.com/channels/740090768164651008/1264328004172255393
export CONTRIBUTORS_PAT=

# The static export is the CLI's, built from this checkout: the same one the package publishes
pnpm run build:cli || exit 1
node bin/pmndrs-docs.mjs build $MDX out --format website || exit 1

npx serve $MDX -p $_PORT --no-port-switching --no-clipboard &

npx serve out -p $PORT &

wait

http://localhost:3000

CLI

The published CLI builds without cloning the engine. If your custom components import packages, install those dependencies in your repository first:

$ cd ~/code/pmndrs/react-three-fiber
$ curl -sL https://raw.githubusercontent.com/pmndrs/docs/refs/heads/main/preview.sh | \
  MDX="docs" \
  NEXT_PUBLIC_LIBNAME="React Three Fiber" \
  HOME_REDIRECT="/getting-started/introduction" \
  ICON="🇨🇭" \
  sh

which is:

preview.sh
#!/bin/sh

main() {
  trap 'kill -9 0' SIGINT

  export PORT="${PORT:-3000}"
  export _PORT="${_PORT:-$(node -e 'const s = require("net").createServer().listen(0, () => { console.log(String(s.address().port)); s.close() })')}"
  export VERSION="${VERSION:-latest}"

  export MDX="${MDX:-docs}"
  export NEXT_PUBLIC_LIBNAME="${NEXT_PUBLIC_LIBNAME:-docs}"
  # Relative assets resolve against the MDX folder, served below on the same port
  export MDX_BASEURL="${MDX_BASEURL:-http://localhost:$_PORT}"

  rm -rf "$MDX/out"

  # Every other option is read straight from the environment — same process, nothing to forward
  npx -y "@pmndrs/docs@$VERSION" build "$MDX" "$MDX/out" --format website || exit 1

  npx serve $MDX -p $_PORT --no-port-switching --no-clipboard &

  npx -y serve "$MDX/out" -p $PORT &

  wait
}

main

Any configuration variable goes in the same way; VERSION picks a published version of the CLI.

Then go to: http://localhost:3000

npx @pmndrs/docs@latest build --help lists the CLI flags, including --config for a configuration outside the repository root.

Both --format website and --format fragment use the same Next.js build and static export. Fragments contain only the compiled document: no layout, stylesheet or script. The CLI copies assets alongside folder fragments and preserves static Mermaid and Sandpack content.

$ npx @pmndrs/docs@latest build page.mdx
$ cat page.mdx | npx @pmndrs/docs@latest build

A single file or stdin writes HTML to stdout and build logs to stderr. These inputs also run a full Next.js build. Consumer components and data use the same docs.config.ts as the website.

read

The same CLI reads every pmndrs library in the terminal:

$ npx @pmndrs/docs                                 # every library, every page
$ npx @pmndrs/docs drei                            # one library
$ npx @pmndrs/docs drei/performances/instances     # one page
$ npx @pmndrs/docs search instanced mesh           # one result per line, on stdout

↑↓ moves in the focused pane, ⇥ switches pane, ←→ changes library, / searches, o opens the page in a browser, q quits. npx @pmndrs/docs browse --help lists every key.

search prints {lib} {path} - {title} and exits 1 when nothing matches; --in drei narrows it to one library, --in drei/performances/instances to the matching lines of one page.

Pages come from each library's llms-full.txt, cached for an hour (--refresh refetches). Piped, a page goes to stdout: npx @pmndrs/docs drei/performances/instances | glow.

Agents

llms.txt dumps and the pmndrs MCP server moved to their own page: Agents.