3.3.4 • Public • Published

    Blender Media

    Software License Build Status

    The media uploader and manager for Blender, our CMS.


    The blender-media can be installed from npm.

    yarn add @spatie/blender-media

    blender-media also requires you to install vue@'^2.0.0', lodash@'^4.0.0', and spatie-dom@'^1.0.0':

    yarn add vue@'^2.0.0' lodash@'^4.0.0' spatie-dom@'^1.0.0'


    This repository contains a dummy version of the media component which can be used for development. It can be built and served on http://localhost:4000 with the following command:

    npm run example

    script will also watch for JS and CSS file changes.


    In order to use the media component, you need to register it first. You can register it globally, or inside a Vue component:

    import Media from '@spatie/blender-media';
    import Vue from 'vue';
    // Global registration...
    Vue.component('media', Media);
    // ...or scoped to your view model
    new Vue({
        el: 'body',
        components: {

    After registering the component, it can be used in your html:

        :model="{ name: 'MyModel', id: 1 }"
            "id": 1,
            "name": "image_1",
            "fileName": "image_1.jpeg",
            "customProperties": {},
            "orderColumn": 1,
            "thumbUrl": "/media/image_1.jpeg",
            "originalUrl": "/media/image_1.jpeg",
            "collection": "images"
        :data="{ locales: ['nl', 'en'] }"

    If you want to use a media component outside of a Vue instance, this package provides a mount function. The mount function will replace every element that matches a given selector with a media component. The element should contain props just like you'd pass them with Vue.

    import { mount } from '@spatie/blender-media';
    export default function init() {
        :model="{ name: 'MyModel', id: 1 }"
        :data="{ locales: ['nl', 'en'] }"

    Media Objects

    Media objects look like the original model from the Laravel package.

    interface Media {
        id: number;
        name: string;
        fileName: string;
        customProperties: any;
        orderColumn: number;
        thumbUrl: string;
        originalUrl: string;
        colection: string;

    Component Properties

    The component requires a few properties in order to handle the collection and uploads.

    type: string

    The type of component that should be rendered (see Types for more details).

    upload-url: string

    The URL that newly uploaded media will be posted to. This endpoint should handle the upload, and return a Media object.

    model: { name: string, id: number }

    The fully qualified class name of the model that the media is related too and it's ID.

    initial: Array<Media>

    The media items that are already in the collection.

    data: any

    Custom data that can be used in the media editor, e.g. a list of available locales so the media item can be toggled per language.


    Each media instance requires a type. A type determines the setup of the media component. Types are registered via the registerType method, which takes a name and options as arguments.

    import { registerType } from 'blender-media';
    registerType('images', {
        accepts: '.jpg,.gif',
        multiple: true,
        editor: 'basic',

    The package ships with image, images, download and downloads types. Types have to be registered before any media component gets rendered. If you register a type with the same name twice, only the last registered type will be used.

    Type Options

    accepts: ?string = null

    The file types that the uploader will accept. If accepts is null, all file types will be accepted. Available formats of the string are described in Dropzone's documentation.

    multiple: bool = true

    Determines whether multiple files can be uploaded to a collection.

    editor: string = 'basic'

    The name of the registered editor to be rendered inside the component. See Editors for a more detailed explanation.

    extend: ?string = null

    Extend an existing type. Creates a new type, based on an existing type. Other options will overwrite the existing type's options.


    Every media row has an editor in the section between the thumbnail and the remove button. The default editor—named basic—has in input to rename the media object.

    Available Editors

    This package ships with 4 editors:

    • basic: A simple name field
    • sizePicker: A name field and a size dropdown with 4 options (full width, 2/3, 1/2, 1/3)
    • toggleLocales: A name field and a toggle for every language, to enable or disable the image. Use this when you need a different image per language
    • translatedDescription: A description field for every language. Use this when the image is the same per language, but needs a translated caption

    Editors come as-is, there's no extra configuration. If you need a variation, for example different widths in the sizePicker, copy the source code and register your own project-specific editor.

    Project-Specific Editors

    Editors are Vue components with an editor mixin. The mixin takes care of the boilerplate that a custom editor requires.

    • It adds media and data props
    • It provides convenience methods for dealing with custom properties
    • It provides convenience methods for UI actions

    The editor mixin allows you to set two new options: customProperties and translatableCustomProperties. They both take a name as key, and a default value as property value.

    import editor from './editor';
    export default {
        mixins: [editor],
        customProperties: {
            sku: '',
        translatableCustomProperties: {
            description: '',
        computed: {
            descriptions() {
                return this.customProperty('description');
        methods: {
            updateDescription(locale, value) {
                this.setTranslation('description', locale, value);

    Editors can then be registered with the registerEditor method. Like types, editors have to be registered before any media component gets rendered. If you register an editor with the same name twice, only the last registered editor will be used.

    import { registerEditor } from 'blender-media';
    import MyEditor from './editors/MyEditor';
    registerEditor('myEditor', MyEditor);

    Note that editors should be contained in a .vue file since they also require a template! Browse the existing editors for some examples.

    Editor Methods

    customProperty(key: string, fallback: any = null)

    Return the value of a custom property. If the property isn't defined, return the fallback.

    // { customProperties: { foo: 'bar' } }
    // > 'bar'
    this.customProperty('baz', 'qux');
    // > 'qux'
    setCustomProperty(key: string, value: any)

    Set a custom property.

    // { customProperties: {} }
    this.updateCustomProperty('locales', { nl: true, en: false });
    // { customProperties: { locales: { nl: true, en: false } } }
    getTranslation(key: string, locale: string)

    Get a translated custom property.

    // { customProperties: { foo: { en: 'bar' } } }
    this.getTranslation('foo', 'en');
    // > 'bar'
    setTranslation(key: string, locale: string, value: any)

    Set a translated custom property's translation.

    // { customProperties: { foo: { en: 'bar' } } }
    this.setTranslation('foo', 'en', 'baz');
    // { customProperties: { foo: { en: 'baz' } } }


    Since this is an internal project, we don't accept pull requests at this time.


    The MIT License (MIT). Please see License File for more information.

    Example images provided by Unsplash.


    npm i @spatie/blender-media

    DownloadsWeekly Downloads






    Last publish


    • spatie