Atomic Payload
Plugins

@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-video
npm install @pro-laico/mux-video
yarn add @pro-laico/mux-video

next, 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:

VariablePurpose
MUX_TOKEN_IDYour Mux API access token ID. Required for uploads and Mux API calls.
MUX_TOKEN_SECRETYour Mux API access token secret. Required alongside the token ID.
MUX_WEBHOOK_SIGNING_SECRETVerifies incoming Mux webhooks (e.g. when an upload finishes encoding).
NEXT_PUBLIC_SERVER_URLUsed as the cors_origin for Mux uploads. Falls back to http://localhost:3000.

Exports

The plugin

Export

Type

muxVideoPluginplugin
The plugin itself. Registers the mux-video collection and applies the upstream @oversightstudio/mux-video plugin to it. Default and named export.

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-video
MuxVideoPluginOptionstype
The TypeScript type for the plugin's options.

Location

@pro-laico/mux-video
MuxVideocollection
The collection uploaded videos live in (slug mux-video, in the admin Assets group). Import it to register or extend the collection yourself.

Location

@pro-laico/mux-video

The video block

Export

Type

createVideoBlockfunction
Factory that builds the VideoChild block. Optional 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/videoChild
Videoblock
The prebuilt VideoChild block (slug and interfaceName VideoChild) with no extra fields. Register it through @pro-laico/atomic's child-blocks plugin.

Location

@pro-laico/mux-video/blocks/videoChild
VideoBlockOptionstype
The options type for createVideoBlock (the prependFields / appendFields to weave into the block). An alias of core's BlockFieldExtensions.

Location

@pro-laico/mux-video/blocks/videoChild
VideoChildfunction
The child-block renderer that mounts the @mux/mux-video-react player with the block's playback settings. Registered automatically through @pro-laico/atomic's renderer, so you rarely import it directly; reach for it only when you render a video outside the child renderer.

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/component

On this page