Making the Livewire Flux Editor component return JSON instead of HTML

October 30th, 2025
3 min read

Flux has saved me so much time in building completely custom UIs for Livewire - especially in the current project where there are some very specific UI requirements from the client.

One of the Pro components in Flux is the Editor - a WYSIWYG editor built using Tiptap.

Here’s the really interesting fact too: Statamic’s Bard fieldtype is a WYSIWYG editor built using Tiptap… do you see where I’m going with this?

In Statamic world, Bard will (by default) store the content as JSON, not HTML - meaning it has greater support for sets and separation of markup from actual content - this is great when you have to change the implementation of a set: your stored content is just data, and your template handles the layout.

Righto, so I’ve built a custom Alpine-based Tiptap editor for a project before which was for a Statamic site, and needed the output to be Statamic-friendly, so used Tiptap’s getJSON method to return JSON for easy interoperability with Statamic. The other option is getHTML which returns, you guessed it, HTML.

Back to Flux: the Editor component just uses the getHTML method, which for many use cases can be enough.

But given my experience with Statamic and the benefits of structured content (rather than raw HTML), I want my Flux Editor instances to return JSON instead. But unfortunately you can’t do this out of the box.

Do you want a prop added to the Editor in Flux that can toggle this behaviour? Give this discussion a vote!

Thankfully, Caleb and Josh from the Livewire team have made it possible to hook in to different aspects of each component - including the Editor component which means we can hook in to the getter that returns the value back to the Livewire world.

This callback gives us access to the editor instance, which is the Tiptap editor, meaning we have access to the function call that returns content. Meaning we can change what it returns.

This getter in Flux as it is now does two things:

  1. If there’s no content, return an empty string, otherwise

  2. return the HTML using getHTML

What we need to do is:

  1. If there’s no content, return null (remember, it is JSON, not a string), otherwise

  2. return the JSON using getJSON

With this simple change, it is now possible to get JSON instead of HTML.

While you could do this on your Editor instance, I have multiple Editors throughout my app and didn’t want to re-define it each time: so I have this code in my main app bundle that hooks in to every Editor instance.

1document.addEventListener('flux:editor', (e) => {
2 e.detail.init(({editor}) => {
3 setTimeout(() => {
4 editor.options.element.closest('ui-editor')._controllable.getter(() => {
5 if (editor.isEmpty) return null;
6 return editor.getJSON();
7 });
8 }, 0);
9 })
10});

Maybe you’re like me and just prefer it, but the real selling point here, if your content needs to interact with Statamic, returning JSON opens up so many possibilities for advanced content editing - including adding custom extensions to Tiptap for implementing Sets within Flux’s Editor that can be correctly loaded in Statamic too. Totally bananas but how awesome is that!

And hopefully one day we can see the Editor component in Flux have a prop that allows us to toggle this behaviour instance-by-instance. Show your support on this discussion!

Thanks to Josh Hanley for being an awesome friend and helper in tightening up the code required to get this happening.

likes
reposts
comments

Comments

Reply on Bluesky to join the conversation.