CLI Integrations
Author an npm package that contributes components, templates, and upgrade codemods to Astryx.Overview
An integration is an npm package that contributes components, templates, and/or upgrade codemods to a consumer's design-system workflow. Consumers install the package and add it to their astryx.config; from then on the integration's contributions show up alongside core's in the same CLI commands.
The system runs on two files. The consumer writes astryx.config.{ts,mjs,js} at their project root to list which packages to load. The author writes astryx.integration.{ts,mjs,js} at the package root to declare what the package contributes. This page is the author's guide. For the consumer side, run npx astryx docs getting-started.
On the consumer side, adding your package is one line:
typescript// astryx.config.tsexport default {integrations: ['@acme/astryx-widgets'],};
Your components and templates then appear next to core's:
bashastryx component --list --package @acme/astryx-widgetsastryx component AcmeCarousel --props
The Integration File
To register your package as an integration, add an astryx.integration.{ts,mjs,js} file as a sibling of your package.json. It tells the CLI where to find your components, templates, and codemods. Identity (name, version) comes from your package.json, not this file.
typescript// astryx.integration.tsexport default {components: './components',templates: './templates',codemods: './codemods',issuesUrl: 'https://github.com/acme/widgets/issues',};
Every field is optional. Declare only the contribution roots your package ships. There is no factory to call. Write a plain object, and for editor autocomplete and type-checking annotate it with the AstryxIntegration type exported from @astryxdesign/cli/authoring.
Components
Export your components from your library however you like, and consumers still import them from your package. For each component the CLI should document, ship a .doc.{ts,mjs,js} file with the same stem, for example AcmeCarousel.tsx alongside AcmeCarousel.doc.ts.
typescript// AcmeCarousel.doc.tsexport default {type: 'component',name: 'AcmeCarousel',description: 'A carousel that cycles through slides.',// props, usage, examples, ...};
Templates
Templates are usually not exported from the package directly. Instead, consumers browse them through the CLI and materialize them into their app. Define a template as a plain object stamped with type: 'page' (full pages) or type: 'block' (smaller chunks) in a .template.{ts,mjs,js} file next to the source, for example AcmeLandingPage.tsx and AcmeLandingPage.template.ts.
typescript// AcmeLandingPage.template.tsexport default {type: 'page',// name, description, preview, ...};
The CLI needs the template source at consume time, so make sure it is included in your published package. This is typically done via the exports key in package.json. It also lets the docsite render template previews in the future.
jsonc{"exports": {// ..."./templates/*.tsx": "./templates/*.tsx"}}
To verify it resolves, try importing the template component with its .tsx extension. An extensionless specifier will not resolve under moduleResolution: bundler, and the extensionful export above is what lets this type-check without consumers enabling allowImportingTsExtensions.
typescriptimport('@acme/astryx-widgets/templates/AcmeLandingPage.tsx');
Codemods
Ship codemods so astryx upgrade can migrate consumers across breaking changes in your package. Point the integration file's codemods field at your codemods root, and author each one as a plain object stamped with type: 'code' (transforms source files) or type: 'config' (rewrites the consumer's astryx.config).
typescript// codemods/v2-rename-prop.tsexport default {type: 'code',// title, description, transform, ...};
All authoring types are exported from @astryxdesign/cli/authoring: ComponentDoc, HookDoc, and ReferenceDoc for docs, TemplateDoc for templates, and AstryxConfig, AstryxIntegration, and AstryxCodemod for the project files. Consumers can also run their own post-codemod hooks, such as a reinstall or rebuild, via hooks.postCodemod in their astryx.config.
How It Works
Every CLI command loads the consumer's astryx.config, resolves each listed integration's manifest from node_modules, and discovers its contributions. Everything is validated against one strict schema at the load boundary: the CLI parses each file through @astryxdesign/cli/authoring when it loads it, not when you author it. There are no factories; you write a plain object and stamp its type.
Discovery is resilient. A broken or misconfigured integration is skipped with a single non-blocking warning on stderr instead of crashing the CLI, and it never corrupts a --json stdout envelope. Everyday commands keep working with the remaining valid contributions.
To inspect problems, run astryx validate-integration <package> for a detailed report on one package, or astryx doctor for an overall health check of the setup.