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
import {createConfig} from '@astryxdesign/core/config';
export default createConfig({
integrations: ['@acme/astryx-widgets'],
});

Your components and templates then appear next to core’s:

bash
astryx component --list --package @acme/astryx-widgets
astryx 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.ts
import {createIntegration} from '@astryxdesign/core/authoring';
export default createIntegration({
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. createIntegration is a type-preserving helper for editor autocomplete and type-checking. It lives in @astryxdesign/core/authoring and is also re-exported from @astryxdesign/cli/integration for back-compat.

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.ts
import {createComponentDoc} from '@astryxdesign/core/authoring';
export default createComponentDoc({
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 with createPageTemplate (full pages) or createBlockTemplate (smaller chunks) in a .template.{ts,mjs,js} file next to the source, for example AcmeLandingPage.tsx and AcmeLandingPage.template.ts.

typescript
// AcmeLandingPage.template.ts
import {createPageTemplate} from '@astryxdesign/core/authoring';
export default createPageTemplate({
// 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.

typescript
import('@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 with createCodemod (transforms source files) or createConfigCodemod (rewrites the consumer’s astryx.config).

typescript
// codemods/v2-rename-prop.ts
import {createCodemod} from '@astryxdesign/cli/codemod';
export default createCodemod({
// version, description, transform, ...
});

The codemod helpers live in @astryxdesign/cli/codemod, not @astryxdesign/core/authoring like the doc, integration, and template helpers. 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 create* helpers do not validate. They are identity functions whose value is their TypeScript surface, so validation happens when the CLI loads the file, not when you author it.

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.