Using Pintura Image Editor with Alpine

For a quick start use the Alpine example project as a guideline.

Alpine implementation example

In the example below we'll use the appendDefaultEditor method to quickly add an image editor to an HTML element.

This creates a "default" editor that has all available plugins loaded and comes preset with all plugin default options and English locale. Each of these settings can be adjusted freely.

<!DOCTYPE html>

<link rel="stylesheet" href="./pintura.css" />

<!-- Alpine Pintura custom directive, see code snippet below -->
<script src="./alpine-pintura/index.js" type="module" defer></script>

<!-- Load Alpine library -->
<script src="./alpine/alpine.min.js" defer></script>

<div x-data="{ src: null, dest: null }">
    <!-- Load images from file input -->
        @change="(e) => {
            // Get the first file
            const [file] = e.target.files;

            // Check if is defined and is image
            if (!file || !/image/.test(file.type)) return;

            // Set as editor source
            src = file;

    <!-- Load a local or remote image -->
    <button x-show="!src" @click="src = 'image.jpeg'">Load local image</button>

    <!-- Displays resulting image if defined -->
    <img x-show="dest && !src" :src="dest" alt="" />

    <!-- Pintura node -->
        style="width: 90vw; height: 600px"
            imageCropAspectRatio: 1,
        @pintura:init="(e) => {
            // Clear previous result (if any)
            dest = null;
        @pintura:load="(e) => {
            // Just to show what the load event contains
            console.log('load', e);
        @pintura:process="(e) => {
            // Called when an image is processed
            console.log('process', e); 

            // Clear source so editor hides
            src = null;
            // Show resulting image 
            dest = URL.createObjectURL(e.detail.dest);

Alpine custom directive for Pintura

This code creates a basic Alpine Pintura directive to create inline editors.

It routes the editor events to the directive DOM node using dispatchEditorEvents, it creates reactive properties using effect, and it cleans up the editor instance and event routes when the node is destroyed.

import {
} from '../node_modules/@pqina/pintura/pintura.js';

document.addEventListener('alpine:init', () => {
        (el, { expression }, { evaluateLater, effect, cleanup }) => {
            // create editor
            const editor = appendDefaultEditor(el);

            // route editor events to element
            const unsubs = dispatchEditorEvents(editor, el);

            // handle prop updates
            const getUpdatedProps = evaluateLater(expression);
            effect(() => {
                getUpdatedProps((props) => {
                    Object.assign(editor, props);

            // clean up editor
            cleanup(() => {
                // destroy editor instance

                // unsub all routed events
                unsubs.forEach((unsub) => unsub());

Next steps

With the editor set up, we can continue to configure the editor to our liking by adjusting the available options exposed by the editor API