Skip to main content
Jack Sleight .DEV
Statamic

Hot reloading Statamic's live preview with Alpine or Livewire

Statamic 3.4.8 includes a fantastic PR by Tom Diggelmann that adds the option to send the live preview a post message on update, rather than fully refreshing the page. This allows you to update the page however you like, and can be used to hot-reload the content if your stack supports it.

It's up to you to implement the necessary code in your frontend, and how you do that will depend on the stack you're using. In this post I've covered how to do this with Alpine and Livewire.

The first thing you'll need to do is go into your collection config and under Preview Targets switch off the Refresh option. Then drop one of the following examples into layout.antlers.html:

Alpine

If you're using Alpine you can use the Morph plugin to update the DOM while preserving browser and Alpine state. This code only updates the body, as Alpine.morph() doesn't support morphing the whole document. If you need to update the head you could add that as well.

{{ if live_preview }}
<script>
window.addEventListener('message', async (event) => {
if (event.data.name === 'statamic.preview.updated') {
const text = await fetch(event.data.url).then((res) => res.text());
const updated = new DOMParser().parseFromString(text, 'text/html');
Alpine.morph(document.body, updated.body);
}
});
</script>
{{ /if }}
{{ if live_preview }}
<script>
window.addEventListener('message', async (event) => {
if (event.data.name === 'statamic.preview.updated') {
const text = await fetch(event.data.url).then((res) => res.text());
const updated = new DOMParser().parseFromString(text, 'text/html');
Alpine.morph(document.body, updated.body);
}
});
</script>
{{ /if }}

Livewire

If you're using Livewire you can simply call the $refresh method on the components in the page. This works best if you have a full-page component at the root, otherwise it may not refresh everything.

{{ if live_preview }}
<script>
window.addEventListener('message', (event) => {
if (event.data.name === 'statamic.preview.updated') {
Livewire.components.components().forEach(component => component.call('$refresh'));
}
});
</script>
{{ /if }}
{{ if live_preview }}
<script>
window.addEventListener('message', (event) => {
if (event.data.name === 'statamic.preview.updated') {
Livewire.components.components().forEach(component => component.call('$refresh'));
}
});
</script>
{{ /if }}
26th April 2023