@pro-laico/mux-video
Lets editors upload videos in the Payload admin and drop them onto pages. Mux handles the encoding and adaptive streaming, and a ready-made video block renders the player.
@pro-laico/mux-video lets editors upload videos straight from the Payload admin and place them on pages with a ready-made video block. Uploads go to Mux, which handles the encoding and adaptive streaming, and the bundled block renders the Mux player on your site, with controls for autoplay, looping, muting, preload, and a blurred poster frame.
@pro-laico/mux-video is a Tool package, a building block of the Atomic Payload stack meant to be used alongside @pro-laico/core and the other @pro-laico/* packages (most easily via the atomic-payload template), not on its own.
Installation
pnpm add @pro-laico/mux-videonpm install @pro-laico/mux-videoyarn add @pro-laico/mux-videonext, payload, and react are peers you already have in a Payload + Next.js app. This package builds on the upstream @oversightstudio/mux-video plugin, so install it too. The Mux player (@mux/mux-video-react) ships bundled, so you don't add it yourself.
Setup
@pro-laico/core comes bundled with this plugin — it's a dependency, not a separate install — and provides the shared fields, hooks, and utilities this plugin builds on. See @pro-laico/core → Setup.
Adding Mux video to your own Payload + Next.js project.
Add the plugin to your Payload config
import { buildConfig } from 'payload'
import { muxVideoPlugin } from '@pro-laico/mux-video'
export default buildConfig({
plugins: [muxVideoPlugin()],
})This registers the mux-video collection (in the admin's Assets group) where uploaded videos live, and applies the upstream Mux plugin's fields to it. With your Mux credentials in place (see environment variables), editors can upload a video and Mux takes over encoding and streaming.
Set your Mux credentials
The plugin reads your Mux API token and webhook secret from the environment before buildConfig runs. Without MUX_TOKEN_ID and MUX_TOKEN_SECRET, the plugin logs a warning and uploads will fail, so set them before you start the app.
Add the video block to your pages
The package ships a VideoChild block that lets editors pick an uploaded Mux video and set playback options (autoplay, loop, muted, preload, plus a blurred poster frame). Register it through @pro-laico/atomic's child-blocks plugin so it renders inside your Atomic pages:
import { buildConfig } from 'payload'
import { childBlocksPlugin } from '@pro-laico/atomic/children'
import { Video } from '@pro-laico/mux-video/blocks/videoChild'
export default buildConfig({
plugins: [
childBlocksPlugin({ childBlocks: [Video] }),
// ...other plugins
],
})The block is not re-exported from the package root. Import the prebuilt Video block (or the createVideoBlock factory) from the @pro-laico/mux-video/blocks/videoChild subpath.
Render it on the frontend
You don't mount the player by hand. The block's renderer is registered with @pro-laico/atomic's child renderer, so once a page's blocks pass through RenderChildren, any VideoChild block automatically renders the Mux player:
// app/(frontend)/[...slug]/page.tsx
import { RenderChildren } from '@pro-laico/atomic/children/render'
export default async function Page({ page }) {
return (
<main>
<RenderChildren blocks={page.children} />
</main>
)
}Need the player component directly for a custom layout? It's available at @pro-laico/mux-video/blocks/videoChild/component as VideoChild, which mounts @mux/mux-video-react with the block's settings.
The atomic-payload template already wires everything up: the plugin is in the config, the VideoChild block is registered with the child-blocks plugin (and given a styling field), and pages render through the Atomic child renderer. You just add your Mux credentials and use the block.
Add your Mux credentials
Copy the Mux keys into your .env (the template's .env.example lists them):
# .env (Mux credentials)
MUX_TOKEN_ID=
MUX_TOKEN_SECRET=
MUX_WEBHOOK_SIGNING_SECRET=See environment variables for what each one is for.
Upload a video
In the admin's Assets group, open the mux-video collection and upload a video file. Mux handles encoding and streaming once it's uploaded.
Drop the video block on a page
Editing a page, add a Video block, pick the uploaded video, and set the playback options (autoplay, loop, muted, preload, and the blurred poster frame). The template renders it through the Atomic child renderer, so the Mux player shows up on the frontend with no extra wiring.
Options
muxVideoPlugin(options?) accepts:
Prop
Type
The uploadSettings and initSettings options take their own nested keys:
All options at their defaults, as a working starting point:
muxVideoPlugin({
enabled: true,
includeCollection: true,
adminThumbnail: 'image',
// collectionOptions is unset by default
uploadSettings: {
cors_origin: process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000',
},
initSettings: {
tokenId: process.env.MUX_TOKEN_ID || '',
tokenSecret: process.env.MUX_TOKEN_SECRET || '',
webhookSecret: process.env.MUX_WEBHOOK_SIGNING_SECRET || '',
},
})Environment variables
The plugin picks these up automatically before buildConfig runs:
| Variable | Purpose |
|---|---|
MUX_TOKEN_ID | Your Mux API access token ID. Required for uploads and Mux API calls. |
MUX_TOKEN_SECRET | Your Mux API access token secret. Required alongside the token ID. |
MUX_WEBHOOK_SIGNING_SECRET | Verifies incoming Mux webhooks (e.g. when an upload finishes encoding). |
NEXT_PUBLIC_SERVER_URL | Used as the cors_origin for Mux uploads. Falls back to http://localhost:3000. |
Exports
The plugin
Export
Type
muxVideoPluginplugin
Parameters
options?:MuxVideoPluginOptionsSee the Options table above. All keys are optional; the Mux credentials default to the MUX_* environment variables.Returns
PluginA Payload config plugin you add to buildConfig({ plugins: [...] }).Example
import { buildConfig } from 'payload'import { muxVideoPlugin } from '@pro-laico/mux-video'export default buildConfig({plugins: [muxVideoPlugin()],})Location
@pro-laico/mux-videoMuxVideoPluginOptionstype
Location
@pro-laico/mux-videoMuxVideocollection
mux-video, in the admin Assets group). Import it to register or extend the collection yourself.Location
@pro-laico/mux-videoThe video block
Export
Type
createVideoBlockfunction
prependFields / appendFields weave your own fields (e.g. a styles ClassNameField) into the start or end of its Video tab, so the block carries no CSS dependency of its own.Parameters
options?:VideoBlockOptionsprependFields and appendFields: Payload fields spread at the start and end of the block's Video tab. Both default to [].Returns
BlockA Payload block (slug and interfaceName VideoChild) you register through @pro-laico/atomic's child-blocks plugin.Example
import { buildConfig } from 'payload'import { childBlocksPlugin } from '@pro-laico/atomic/children'import { createVideoBlock } from '@pro-laico/mux-video/blocks/videoChild'import { ClassNameField } from '@pro-laico/styles/fields/className'// add a styles className field to the video block's Video tab:const Video = createVideoBlock({ appendFields: [ClassNameField({ namePrefix: 'video' })] })export default buildConfig({plugins: [childBlocksPlugin({ childBlocks: [Video] })],})Location
@pro-laico/mux-video/blocks/videoChildVideoblock
VideoChild) with no extra fields. Register it through @pro-laico/atomic's child-blocks plugin.Location
@pro-laico/mux-video/blocks/videoChildVideoBlockOptionstype
createVideoBlock (the prependFields / appendFields to weave into the block). An alias of core's BlockFieldExtensions.Location
@pro-laico/mux-video/blocks/videoChildVideoChildfunction
Parameters
props:RenderChild<VideoChildType>The resolved child-block props @pro-laico/atomic passes its renderers. The player and data attributes come from pt.c.p / pt.c.da.Returns
ReactElementThe mounted Mux player (@mux/mux-video-react), loaded with next/dynamic.Example
// a custom layout that renders one resolved video child directlyimport { VideoChild } from '@pro-laico/mux-video/blocks/videoChild/component'export function Hero({ child }) {return ( <section> <VideoChild {...child} /> </section>)}Location
@pro-laico/mux-video/blocks/videoChild/componentRelated
@pro-laico/images
Adds the image and favicon upload collections to your Payload admin: web-ready WebP sizes, a favicon picker field, and an image block for your pages.
@pro-laico/richtext
A ready-to-use rich-text block for Atomic Payload: a Lexical editor for writing formatted content in the admin and a renderer that turns it into clean React on your site.