
Preview media files directly in the Content Manager with modal support and list view columns
released April 20, 2026
npm install strapi-plugin-media-previewA production-ready Strapi 5 plugin that enhances the Content Manager with powerful media preview capabilities. Preview any media file directly in a modal, access all media from the edit view header, and view media files in list view columns.
noopener,noreferrer security attributes| Dependency | Version |
|---|---|
| Strapi | ^5.0.0 |
| Node.js | >=18.0.0 |
| React | ^18.0.0 |
npm install strapi-plugin-media-preview
# or
yarn add strapi-plugin-media-preview
# or
pnpm add strapi-plugin-media-previewEdit config/plugins.ts (or config/plugins.js):
// config/plugins.ts
export default () => ({
'media-preview': {
enabled: true,
},
});npm run build
npm run developThat's it! Navigate to any content type with a media field ā you'll see the šļø preview button beside each uploaded file.
In the Content Manager edit view:
In the Content Manager list view:
The plugin handles URLs safely:
| URL Type | Behavior |
|---|---|
Absolute (https://...) | Used directly |
Relative (/uploads/...) | Prepended with backend origin |
| Null/undefined | Skipped |
The plugin uses a multi-layer injection strategy for maximum compatibility:
Layer 1: Edit View Header Injection
āāā Injects MediaPreviewButton into CM edit view header
āāā Button opens MediaPreviewModal on click
āāā Modal fetches media via Content Manager API
āāā Falls back to DOM scanning if API fails
Layer 2: List View Column Injection
āāā Registers hook for Admin/CM/pages/ListView/inject-column-in-table
āāā Adds custom "Media" column to all content types
āāā MediaColumnCell component renders dropdown
āāā Dropdown opens MediaFilePreviewModal for selected filesstrapi-plugin-media-preview/
āāā admin/
ā āāā src/
ā āāā index.ts # Plugin registration & bootstrap
ā āāā pluginId.ts # Plugin ID constant
ā āāā types.ts # TypeScript interfaces
ā āāā components/
ā ā āāā MediaPreviewButton.tsx # Edit view header button
ā ā āāā MediaPreviewModal.tsx # Main modal with API fetch
ā ā āāā MediaColumnCell.tsx # List view column cell
ā ā āāā MediaFilePreviewModal.tsx # Single file preview modal
ā ā āāā MediaFieldController.tsx # Legacy DOM observer
ā ā āāā PreviewButton.tsx # Core preview button
ā ā āāā MediaAssetPreviewActions.tsx # Asset preview wrapper
ā āāā hooks/
ā ā āāā useBackendUrl.ts # Backend URL resolution
ā āāā utils/
ā āāā url.ts # URL utilities
āāā package.json
āāā tsconfig.json
āāā plugin.config.ts
āāā README.mdNo configuration is required. The plugin works out of the box.
The plugin auto-detects the backend URL using:
window.__STRAPI_ADMIN_BACKEND_URL__ (injected by Strapi admin at runtime)window.location.origin (fallback)For custom deployments where the backend and admin are on different origins, ensure STRAPI_ADMIN_BACKEND_URL is set in your Strapi environment:
# .env
STRAPI_ADMIN_BACKEND_URL=https://api.yourdomain.comrel="noopener noreferrer" equivalent (window.open with 'noopener,noreferrer')file.url from the already-loaded field value| Strapi Version | Status |
|---|---|
| 5.x | ā Supported |
| 4.x | ā Not supported (use a Strapi 4 compatible version) |
config/plugins.tsnpm run buildnpm run developnpm run build in both directoriesThis can happen if:
Check the browser console for error messages.
Check your STRAPI_ADMIN_BACKEND_URL environment variable:
# .env
STRAPI_ADMIN_BACKEND_URL=https://api.yourdomain.comFor local development, the default is http://localhost:1337.
If you see an error like violates the following Content Security Policy directive: "default-src 'self'" when previewing PDFs, you need to update your Strapi security middleware.
Edit config/middlewares.ts (or config/middlewares.js):
export default ({ env }) => [
// ...
{
name: 'strapi::security',
config: {
contentSecurityPolicy: {
useDefaults: true,
directives: {
'connect-src': ["'self'", 'https:'],
'img-src': ["'self'", 'data:', 'blob:', 'https:'],
'media-src': ["'self'", 'data:', 'blob:', 'https:'],
'frame-src': ["'self'", 'https://your-media-domain.com'], // Add your media domain here
upgradeInsecureRequests: null,
},
},
},
},
// ...
];Ensure your tsconfig.json includes:
{
"compilerOptions": {
"skipLibCheck": true
}
}And you're using TypeScript 5+.
Built with ā¤ļø for the Strapi community.
Special thanks to:
MIT Ā© 2026
See LICENSE for more information.
Made with ā¤ļø for Strapi 5
Share your work with the community and get it listed in the Strapi ecosystem for everyone to discover and use.
Submit
