Skip to content
Postkit

Reference

Since version 0.3.0

CLI. Add, own and create components from your terminal.

One small tool for the moments config isn't enough: turning on kits, taking a component into your repo, keeping it current, and making your own.

The CLI is @postkit/cli, and its command is postkit. It depends only on @postkit/core and file tooling, so it works with either renderer.

sh
npm install --save-dev @postkit/cli

Once it's installed, npx postkit runs your project's copy. To try it without installing, use the package name: npx @postkit/cli eject figure. A bare npx postkit outside a project would look for a different, unscoped package.

Commands

sh
npx postkit --help
npx postkit eject --help
CommandWhat it doesExample
postkit addTurn on a kit or component and update your confignpx postkit add media
postkit ejectCopy a component's view into your repo to own itnpx postkit eject figure
postkit diffSee what changed upstream since you ejectednpx postkit diff figure
postkit newScaffold a component of your ownnpx postkit new showcase
postkit manifestWrite the catalog for editors like Prismarknpx postkit manifest

Names work in any case: figure, Figure, code-block and CodeBlock all work. npx postkit --version prints the installed version.

Every command takes --config <file>. An error you can fix, such as a component that doesn't exist or a file that's already there, prints as one line and exits with 1.

Your config

Every command that needs your createPostkit config finds it the same way:

  1. --config <file>, if you pass it.

  2. postkit.config.ts (or .mts, .js, .mjs) in the current directory, then in the project root (the nearest package.json). It exports your createPostkit result as default or postkit:

    ts
    // postkit.config.ts
    export { postkit as default } from './lib/postkit';
  3. Otherwise, the one file in your project that calls createPostkit(. If there's more than one, the CLI stops and asks for --config.

add and eject edit the file that calls createPostkit({ … }), following postkit.config.ts to it. They only change what they can read with certainty: a single call with an object literal, array literals for kits, components and exclude, and an object literal for overrides. Anything else, such as kits built in a function or options spread from another object, is left alone, and the CLI prints the exact lines to add instead.

postkit add

sh
npx postkit add media
npx postkit add poll
text
✓ lib/postkit.ts   kits += media
✓ lib/postkit.ts   components += Poll

A kit name (article, technical, media, discovery, engagement, publishing) is imported from @postkit/react/kits and added to kits. A built-in component whose kit is already on is taken out of exclude; otherwise its definition (from @postkit/core/components) and your renderer's view (from @postkit/react or @postkit/chakra) are imported and added to components. A name that's neither a kit nor a built-in component stops with a hint to run postkit new instead.

FlagDefaultMeaning
--configdiscoveredThe config file
--dry-runfalsePrint the change as a diff, unwritten

postkit eject

Ejecting copies the view (and its recipe, for Chakra) into your repo. The definition stays upstream, so your posts, validation and editor support don't fork.

sh
npx postkit eject figure --renderer chakra --to libs/postkit
text
✓ libs/postkit/figure/figure.recipe.ts
✓ libs/postkit/figure/figure.tsx
✓ .postkit-eject.json   Figure @ @postkit/chakra 0.3.0
✓ lib/postkit.ts   overrides.Figure.view → ../libs/postkit/figure/figure

Still bound to Figure's definition from @postkit/core/components.
It imports @postkit/chakra, @postkit/core, @postkit/react; keep them in your dependencies.
Chakra applies the recipe registered as postkitFigure first: register the ejected recipe in your theme to use your edits (see /docs/eject).
Run `postkit diff figure` after upgrading @postkit/chakra.

The folder is <--to>/<component>/. With --renderer headless, you get the view and its CSS instead of a recipe. Without --force, eject stops if a file it would write already exists.

FlagDefaultMeaning
--rendererfrom configheadless or chakra
--tosrc/postkitWhere the component's folder goes
--dry-runfalseShow the files and config change only
--forcefalseOverwrite files that already exist
--no-registerregistersLeave your config alone

"From config" means chakra when your config passes renderer: chakra from @postkit/chakra, and headless when it has no renderer. See Eject for when to use it.

postkit diff

After an upgrade, see exactly what upstream changed in the views you own, and decide what to bring across.

sh
npx postkit diff figure
text
Figure (chakra) in libs/postkit/figure: @postkit/chakra 0.3.0 → 0.3.2
--- a/figure.tsx	@postkit/chakra@0.3.0
+++ b/figure.tsx	@postkit/chakra@0.3.2
@@ -59,7 +59,7 @@
           alt={alt}
           htmlWidth={postkitImageDimension(props.width)}
           htmlHeight={postkitImageDimension(props.height)}
-          loading={props.loading}
+          loading={props.priority ? 'eager' : props.loading}
           decoding="async"
           sizes={props.sizes}
           srcSet={props.srcSet}

1 file changed upstream. Your copy wasn't changed.
Your edits: figure.recipe.ts.

Without a name, it checks every component in .postkit-eject.json. When nothing changed upstream, it prints No upstream changes.

FlagMeaning
--acceptRecord the installed version as your new base, once you're done
--exit-codeExit with 1 when upstream changed, for CI

postkit new

Scaffold a component with its definition, headless view and styles. It gets a Markdown directive, validation and a manifest entry for free.

sh
npx postkit new showcase
text
✓ src/postkit/showcase/showcase.definition.ts
✓ src/postkit/showcase/showcase.tsx
✓ src/postkit/showcase/showcase.css

Register it with createPostkit({ components }) in lib/postkit.ts:

import { Showcase } from '../src/postkit/showcase/showcase';
import { showcaseDefinition } from '../src/postkit/showcase/showcase.definition';

export const postkit = createPostkit({
  // …your renderer and kits
  components: [{ definition: showcaseDefinition, view: Showcase }],
});

Use it as <Showcase /> in MDX or :::postkit-showcase in Markdown.
Import showcase.css from your global stylesheet for the headless view.

With --chakra it also writes showcase.recipe.ts and showcase.chakra.tsx, and the registration uses the Chakra view. With --spec it writes a spec per view (showcase.spec.tsx, and showcase.chakra.spec.tsx with --chakra).

FlagDefaultMeaning
--tosrc/postkitWhere the component's folder goes
--chakrafalseAlso a Chakra view and slot recipe
--specfalseA spec per view (Vitest)
--categoryarticle-structureThe catalog category
--directivepostkit-<name>The Markdown directive
--descriptionThe one line editors and the catalog show
--import-extensionnonejs for Node's nodenext module resolution
--dry-runfalseList the files without writing them
--forcefalseOverwrite files that already exist

In an Nx workspace, nx g @postkit/nx:component showcase writes the same files from the same templates. See New components.

postkit manifest

sh
npx postkit manifest --out public/postkit-manifest.json

Loads your config (TypeScript and TSX work) and writes the v2 manifest of exactly the components it enables, yours included, to stdout or --out. It's the same JSON as postkit.manifest(), for editors like Prismark. With --out, it confirms on stderr:

text
✓ public/postkit-manifest.json   from lib/postkit.ts

manifest finds the config like the other commands (see Your config). The module must export the createPostkit result as default or postkit, or as its only export with a manifest() method.

Edit this page on GitHub

Postkit

Richer posts, written once, right everywhere.

© 2026 Postkit. MIT licensed.
LicensingPrivacy