Files
twenty/packages/twenty-docs/scripts/generate-ui-reference.ts
Raphaël Bosi a44c8bdf92 Add Twenty UI documentation and generated API references (#25791)
Add a UI Library documentation section so developers can get started
with Twenty UI, customize its theme, and use its components.

The section has guides for setup, theming, design tokens, dark mode,
server rendering, and accessibility, plus a page per component (17 so
far) with usage examples and a generated props reference.

How the references are generated and kept in sync:
- `nx generate:ui twenty-docs` extracts prop types and JSDoc from the
twenty-ui components with react-docgen-typescript and the design tokens
from the token pipeline, writes them to `packages/twenty-ui/generated`,
and renders MDX snippets under
`packages/twenty-docs/snippets/ui/generated`.
- `nx check:ui twenty-docs` runs in CI Docs and fails when the data or
snippets are stale, when a page and the generated snippets disagree, or
when a guide example does not compile against the public entry points
and peer dependencies.
- Twenty UI's own props now carry JSDoc descriptions, and generation
fails on an undocumented prop.

Old `/twenty-ui/*` URLs redirect to the new pages. The pages use the
existing Crowdin translation workflow; the generated snippets are shared
across locales.
2026-09-14 08:03:21 +00:00

72 lines
2.3 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import {
type ComponentDocumentation,
type TokenDocumentation,
} from '../../twenty-ui/docs/types';
import { checkUiReferenceImports } from './ui/check-ui-reference-imports';
import {
renderComponentReference,
renderTokenReference,
} from './ui/render-ui-reference';
import { syncUiReferenceFiles } from './ui/sync-ui-reference-files';
const GENERATED_HEADER = `{/*
* _____ _
*|_ _|_ _____ _ __ | |_ _ _
* | | \\ \\ /\\ / / _ \\ '_ \\| __| | | | Auto-generated file
* | | \\ V V / __/ | | | |_| |_| | DO NOT EDIT - changes will be overwritten
* |_| \\_/\\_/ \\___|_| |_|\\__|\\__, | Generated by: npx nx generate:ui twenty-docs
* |___/
*
* This file is generated from the documentation data in packages/twenty-ui/generated.
* To update it, edit the component prop types or design tokens in twenty-ui and run:
* npx nx generate:ui twenty-docs
*/}`;
const dataRoot = resolve(__dirname, '../../twenty-ui/generated');
const snippetsRoot = resolve(__dirname, '../snippets/ui/generated');
const pagesRoot = resolve(__dirname, '../ui');
const components: ComponentDocumentation[] = JSON.parse(
readFileSync(resolve(dataRoot, 'components.docs.json'), 'utf8'),
);
const tokens: TokenDocumentation[] = JSON.parse(
readFileSync(resolve(dataRoot, 'tokens.docs.json'), 'utf8'),
);
const outputs = [
...components.map((component) => ({
name: `${component.slug}.mdx`,
content: renderComponentReference(component),
})),
{ name: 'tokens.mdx', content: renderTokenReference(tokens) },
];
const syncErrors = syncUiReferenceFiles({
directory: snippetsRoot,
outputs: outputs.map((output) => ({
...output,
content: `${GENERATED_HEADER}\n\n${output.content}`,
})),
isCheckMode: process.argv.includes('--check'),
});
if (syncErrors.length > 0) {
process.stderr.write(
`${syncErrors.join('\n')}\nRun npx nx generate:ui twenty-docs.\n`,
);
process.exitCode = 1;
}
const importErrors = checkUiReferenceImports({
pagesDirectory: pagesRoot,
outputs,
});
if (importErrors.length > 0) {
process.stderr.write(
`${importErrors.join('\n')}\nKeep the pages under ui/ and DOCUMENTED_COMPONENTS in twenty-ui/docs/components.ts in sync.\n`,
);
process.exitCode = 1;
}