Skip to content
Postkit

Customizing

Since version 0.3.0

Defaults and slots. Change what authors get without asking, and swap a single part of a component for your own.

Defaults and slots are rungs 4 and 5 of the customization ladder. Both keep the component's definition, so its directive, validation and manifest entry don't change and every existing post keeps working.

RungWhat you changeHow
1. PropsOne instancevariant, size, tone, layout…
2. TokensFonts, colours, spacing everywhereYour Chakra system, or --postkit-* custom properties
3. Part stylesA component's lookRecipes, CSS on the anatomy, or classNames per part
4. DefaultsWhat authors get without askingdefaults in createPostkit
5. SlotsOne part of the markupoverrides.Callout.slots
6. ViewsThe whole renderoverrides.Figure.view
7. EjectThe source itselfnpx postkit eject
8. NewSomething Postkit doesn't havenpx postkit new

Defaults

Set site-wide prop defaults with defaults, keyed by component name:

ts
// lib/postkit.ts
import { createPostkit } from '@postkit/react';
import { article } from '@postkit/react/kits';

export const postkit = createPostkit({
  kits: [article],
  defaults: {
    Callout: { variant: 'plain' },
  },
});

Every callout now renders with the plain variant unless its author asks for another one. A prop written in the post always wins over a default.

Without defaults, every component uses its definition's defaults. The variant default is subtle for every component.

createPostkit checks defaults when it runs: a component that isn't enabled, a prop the component doesn't have, or a value the prop doesn't allow throws an error naming it.

The manifest's per-prop default is the definition's default, not your site's: the manifest describes the components, and your defaults are a rendering choice.

How each renderer applies them

The same defaults object works with both renderers:

  • Headless: the defaults become the view's prop defaults.
  • Chakra: props that are theme variants (variant, size, tone) are written into the recipe's defaultVariants. Other props become the view's defaults.

If you set the same variant default in both places, createPostkit's defaults wins.

Because Chakra variant defaults live in the recipe, you can also set them with part styles, next to the rest of a component's look:

ts
import { createPostkitTheme } from '@postkit/chakra';

export const postkitTheme = createPostkitTheme({
  callout: {
    defaultVariants: { variant: 'plain' },
  },
});

Use defaults when the choice is about content, and the recipe when it's part of a theme you share between sites.

Slots

A slot override replaces one named part of a component and keeps the rest. The part names are the component's anatomy, listed on each component page.

tsx
// lib/postkit.tsx
import { createPostkit, type PostkitSlotProps } from '@postkit/react';
import { article } from '@postkit/react/kits';

function InkMark(props: PostkitSlotProps) {
  return (
    <span {...props}>
      <svg aria-hidden="true" viewBox="0 0 16 16" width="16" height="16">
        <circle cx="8" cy="8" r="6" fill="currentColor" />
      </svg>
    </span>
  );
}

export const postkit = createPostkit({
  kits: [article],
  overrides: {
    Callout: {
      slots: { icon: InkMark },
    },
  },
});

Your part receives the slot's props and styles, typed as PostkitSlotProps: the anatomy attributes (data-postkit-part and any state), the part's className and style, and its children. With Chakra, the recipe's styles for that part arrive in className too. Spread them onto your root element so the part still carries its name and still picks up your CSS.

Class names per part, without replacing the element, go in overrides.Callout.classNames (see Part styles).

Slots replace the parts a view renders itself: an element the view returns with a matching data-postkit-part. A view not built with postkitView or postkitChakraView (in 0.3.0, Chakra's CodeBlock, CodeGroup, LinkPreview and SocialPost) can't take slot overrides yet, and createPostkit says so; override its view instead.

When to go further

If you need to change how the parts fit together, not just one of them, replace the whole render with a view. If you need to change the source itself, eject it.

Edit this page on GitHub

Postkit

Richer posts, written once, right everywhere.

© 2026 Postkit. MIT licensed.
LicensingPrivacy