Plate UI
SkillFiles & storageLets your agent build and refactor shadcn-style React UI components for the Plate editor and its registry.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Plate UI skill
About this capability
Build new shadcn-style components for Plate's registry and editor surfaces. Use when authoring or refactoring registry UI/components, deciding what belongs in packages vs app-local component files, creating base/live kits and registry wiring, or applying React Compiler, Effects, accessibility, polym
What this skill tells your AI
The instructions your AI receives, as published by udecode/plate in .agents/skills/plate-ui/SKILL.md and read by ahel’s review.
Repo-specific companion to the shadcn skill.
Use the shadcn skill for CLI, upstream docs, and generic shadcn/ui rules.
Use this skill for Plate-specific component authorship: open-code preservation,
package extraction boundaries, base/live kit split, cross-platform layering,
and registry wiring.
Repo Surfaces
apps/www/src/registry/ui— live component and node renderersapps/www/src/registry/components/editor/plugins— base/live kit wiringapps/www/src/registry/registry-*.ts— registry metadata and dependenciespackages/*— durable transforms, queries, controllers, and public hooks
Principles
- Preserve open code. A shadcn-derived component should still look like source code a user can own, read, diff, and tweak.
- Extract only durable boundaries. Package code should own semantics, not JSX avoidance.
- Design below JSX. Cross-platform reuse belongs in command/state contracts, controllers, queries, and transforms — not in package-owned shadcn composition.
- Keep UI composition local until proven otherwise. Popovers, labels, and layout belong in the component unless multiple surfaces need the same contract.
- Registry wiring is part of authorship. A component is not done until kits, examples, and style deps are coherent.
- React floor is 19.2+. Do not add backward-compat code for React 18-era limitations or patterns.
Critical Rules
Cross-Platform Layering → cross-platform.md
packages/*/src/libowns semantic core: transforms, queries, schemas, serialization, controllers, command/state contracts.packages/*/src/reactis a thin adapter layer only.- Future native layers should consume the same conceptual contracts, not React-specific convenience hooks.
- If a package React hook mainly returns renderer-specific UI props/state, treat it as migration debt, not precedent.
Ownership & Extraction → ownership.md
- Extract package code for transforms, queries, serialization, stable controllers, and public hooks reused across surfaces.
- Keep one-off shadcn composition, labels, popover state, and local visual treatment in the app component.
- Never create a package hook just to hide JSX, avoid typing work, or move logic used by one component only.
- If extraction makes the component harder to compare with upstream shadcn/open code, keep it local.
- For sibling live/static registry renderers, duplicate presentation lookup data and tiny label helpers in each renderer instead of creating a third shared registry file. Extract only when the shared code owns real behavior beyond labels, menu data, or copy.
Component Shape & Editor Access → component-shape.md
- Node renderers use node-context hooks like
useElement()orusePath()when they are in element context. - Prefer direct
editor.getApi(plugin)/editor.getTransforms(plugin)oruseEditorPlugin(plugin)over local wrapper helpers. - If a node renderer forwards to
PlateElementorSlateElement, keep the full incomingpropsobject intact. Read fromprops, but do not destructure awayeditor,element, or other required fields and then spread only a partial object into the renderer. - Keep helpers inline when used once.
- Split static/base and live kits cleanly.
React Performance & Effects → react-performance.md
- Target React
>=19.2. Do not preserve React 18 compatibility patterns unless the user explicitly asks. - Effects are escape hatches, not state calculators.
- Derive during render unless synchronizing with a real external system.
- Put interaction logic in event handlers, not in effects watching state.
- Do not subscribe to fast-changing editor state unless the rendered output truly depends on it.
- Do not define nested components inside components.
Registry Wiring → registry.md
- Update
registry-kits.ts,registry-ui.ts, andregistry-examples.tstogether. - Add explicit
registryDependenciesfor every shared UI/style dependency. - If a component depends on shared CSS vars like highlight tokens, add the style registry dep.
- Examples should depend on kits plus any extra styles/components they introduce.
Registry Changelog
- User-visible registry UI, kit, example, metadata, style dependency, copied-code install shape, or generated registry changelog changes need a registry changelog entry or a concrete N/A reason.
- Use the
registry-changelogskill for schema, scaffold, generation, and verification. Do not duplicate the entry contract here.
Shadcn Proofing → shadcn-proofing.md
- Keep
asChild,data-slot,data-state, variants, and file shape recognizable. - Prefer one readable file with local subparts over scattering tiny hooks.
- Review custom code like an upstream diff: would this still feel like open source, or like framework sludge?
Major-Release Law
For the future redesign, use this as the default:
Package React hooks that mainly return renderer-specific UI props/state should be deprecated and moved app-local. Package layers keep cross-platform semantic/view-model contracts only.
If an existing hook breaks this law, do not copy it into new work just because it already exists.
Extraction Test
Extract to a package only if at least one is true:
- The code owns document semantics, serialization, transforms, or navigation contracts.
- Multiple UI surfaces or platforms need the same behavior contract.
- The code is a stable controller/hook whose output is not tied to one shadcn component's markup.
- The same logic would otherwise be duplicated across packages or adapters.
- A future native consumer could plausibly use the same conceptual contract.
Keep it local if any of these are true:
- The code only serves one component.
- The return shape is mostly labels, JSX wiring, class decisions, or popover/menu state.
- The main reason to extract is "this file feels long" or "types are annoying".
- The extraction would hide open-code structure from users.
- The abstraction only makes sense in React/web and has no plausible native sibling.
Key Patterns
// Good: package owns stable semantics, UI composes locally.
const { align, focused, readOnly, selected } = useMediaState();
return (
<MediaToolbar plugin={ImagePlugin}>
<PlateElement {...props}>...</PlateElement>
</MediaToolbar>
);
// Good: direct plugin access, no local wrapper layer.
const api = editor.getApi(CommentPlugin).comment;
const tf = editor.getTransforms(CommentPlugin).comment;
// Good: package core owns commands/state, platform UI composes locally.
const canToggleBold = bridgeState.canToggleBold;
const onPress = () => editor.toggleBold();
return <Button disabled={!canToggleBold}>Bold</Button>;
// Good: base/live split stays explicit.
export const BaseFootnoteKit = [
BaseFootnoteReferencePlugin.withComponent(FootnoteReferenceElementStatic),
BaseFootnoteDefinitionPlugin.withComponent(FootnoteDefinitionElementStatic),
];
export const FootnoteKit = [
FootnoteInputPlugin.withComponent(FootnoteInputElement),
FootnoteReferencePlugin.withComponent(FootnoteReferenceElement),
FootnoteDefinitionPlugin.withComponent(FootnoteDefinitionElement),
];
// Bad: package hook exists only to feed one shadcn component's local UI.
const state = useSingleComponentOnlyState();
return <Popover open={state.open}>...</Popover>;
// Bad: React-only package hook that mainly returns renderer glue.
const {
dialogTitle,
menuItems,
onOpenChange,
popoverOpen,
} = useToolbarMenuState();
Workflow
- Start with the
shadcnskill. Run the normalshadcndocs/search workflow first. - Search Plate for the closest analog in
apps/www/src/registry/ui,apps/www/src/registry/components/editor/plugins, and the relevantpackages/*. - Decide ownership with the extraction test before writing code.
- Decide the three layers before coding:
- semantic core
- platform adapter
- local open-code UI
- Apply the React checks before writing state/effects:
- can this be derived during render?
- should this stay in an event handler?
- am I subscribing to more editor state than the UI actually renders?
- Build the component as open code first.
- Extract only the boundaries that survive the test.
- Wire base/live kits and registry deps.
- Apply the registry changelog decision:
- user-visible registry change: add or update a registry changelog entry, run the generator, and run the registry changelog check
- not user-visible: record
N/A: <reason>
- If package exports changed, run
pnpm brl. - Verify the smallest honest surface:
- component spec for UI-only changes
- package build/typecheck when package code changed
- browser verification when the surface is interactive
Audit References
- component-audit.md — concrete good patterns and anti-patterns from this repo
Comprehensive References
Load these only when the task needs the detail:
.agents/rules/plate-ui/references/components.md— comprehensive component architecture reference: accessibility,asChild, composition, data attributes, artifact taxonomy, polymorphism, controlled/uncontrolled state, and component typing..agents/rules/plate-ui/references/react.md— comprehensive React reference: React Compiler, manual memoization escape hatches, Effects,useEffectEvent, ref access, derived state, Tailwind v4 syntax, data attributes, and UI constraints.
Detailed References
Signals
- GitHub stars
- 17k
- Forks
- 996
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
plate-ui- Source
- github.com/udecode/plate