strapi-component-ux-enhancer-plugin
v1.0.0
Published
This plugin adds additional enhancements to current component building like a default prefill for component fields and a component preview.
Readme
strapi-component-ux-enhancer-plugin
A Strapi 5 plugin that enhances the dynamic zone component authoring experience with template prefilling and live component previews.
Features
- Template Modal — When adding a component to a dynamic zone, shows existing instances of that component type and lets you prefill the new component with an existing instance's field values.
- Component Preview — Adds an Eye icon to the dynamic zone component toolbar that opens a live preview (e.g., Storybook iframe) of the component directly in the admin panel.
- Field Association — Preview URLs can be mapped to an enum field (like
type), so changing the component variant automatically resolves the correct preview. - Paginated Instance Browser — The template modal loads instances 10 at a time with infinite scroll and client-side search filtering.
How It Works
Template Modal
When you click a component in the dynamic zone picker (e.g., "Banner"), the plugin intercepts the click and shows a modal listing all existing instances of that component across all content types. You can:
- Select an instance to prefill the new component with that instance's field values
- Start blank to add an empty component as usual
- Search to filter instances by label text
The modal fetches instances from the server via the GET /strapi-component-ux-enhancer-plugin/instances/:componentUid endpoint with paginated results.
Component Preview
Components that have a component-preview custom field configured will show an Eye icon in the dynamic zone toolbar (next to the trash and drag icons). Clicking it opens a modal overlay with an iframe pointing to the configured preview URL (typically a Storybook story).
The preview config is stored as JSON in the custom field's default value, configured via the Content-Type Builder.
Preview Configuration
Add the Component Preview custom field to any component in the Content-Type Builder. The preview JSON is set in the field's "default" option.
Simple Mode (single preview URL)
{
"preview_url": "https://storybook.example.com/iframe.html?id=components-subscribe--default"
}Field Association Mode (variant-based previews)
Map preview URLs to values of an enum field on the component:
{
"fieldAssociation": true,
"fieldName": "type",
"previews": {
"full width - image": { "preview_url": "https://storybook.example.com/iframe.html?id=banner-full-width-image" },
"full width - video": { "preview_url": "https://storybook.example.com/iframe.html?id=banner-full-width-video" },
"two column - image": { "preview_url": "https://storybook.example.com/iframe.html?id=banner-two-column-image" },
"text only": { "preview_url": "https://storybook.example.com/iframe.html?id=banner-text-only" }
}
}The keys in previews must match the enum values exactly (case-sensitive, including spaces). When you change the enum value in the editor and click the Eye icon, it resolves the correct preview.
API Endpoints
Admin Routes (authenticated via admin JWT)
| Method | Path | Description |
|--------|------|-------------|
| GET | /strapi-component-ux-enhancer-plugin/instances/:componentUid | Paginated component instances (?page=1&pageSize=10) |
| GET | /strapi-component-ux-enhancer-plugin/component-types | All component UIDs in dynamic zones |
| GET | /strapi-component-ux-enhancer-plugin/preview-configs | Preview config map for toolbar injection |
All admin routes require admin::isAuthenticatedAdmin policy.
Architecture
server/src/
├── bootstrap.ts # Schema scanner initialization
├── controllers/
│ └── instance-controller.ts # Handles instances, component-types, preview-configs
├── services/
│ ├── instance-service.ts # Queries dynamic zones, builds labels, paginates
│ ├── schema-scanner.ts # Maps component UIDs to dynamic zone locations
│ └── population-builder.ts # Builds Strapi query configs for deep population
├── routes/
│ ├── admin/index.ts # Admin-authenticated routes
│ └── content-api/index.ts # Content API routes (if any)
└── types/ # Shared TypeScript interfaces
admin/src/
├── index.ts # Plugin register + bootstrap
├── bootstrap/
│ └── mount-modal.tsx # Template modal click interceptor + React fiber access
├── components/
│ └── TemplateModalRoot.tsx # Modal UI with infinite scroll
├── features/preview/
│ ├── register.ts # Custom field registration (component-preview)
│ ├── mount-drawer.tsx # Preview drawer portal
│ ├── mount-toolbar-buttons.tsx # MutationObserver-based toolbar Eye icon injection
│ ├── preview-state.ts # Global preview URL pub/sub state
│ └── components/
│ ├── PreviewInput.tsx # Custom field input (renders null, stores config)
│ └── PreviewDrawer.tsx # Iframe preview overlay modal
├── utils/
│ ├── search-filter.ts # Client-side instance search
│ └── deep-clone.ts # Deep clone for template field values
└── types/index.ts # Admin-side TypeScript interfacesSecurity
- Admin routes use
admin::isAuthenticatedAdminpolicy - All admin panel API calls use
getFetchClientfrom@strapi/strapi/admin(auto-includes admin JWT) - No
auth: falseon any route that returns content data
Development
# Install dependencies
npm install
# Build the plugin
npm run build
# Watch mode (rebuilds on changes)
npm run develop
# Type check
npx tsc --noEmitNode Version
This plugin requires Node.js v24+ (see .nvmrc).
