Get started

How To

27 Feb 2024

How to use Wagtail within a MACH architecture

An in-depth analysis of how Wagtail aligns with MACH architectures and the changes required to run it headlessly.

Kyle Bayliss

Kyle Bayliss

Principal Engineer

wagtail-mach

Note: This is not another article explaining what MACH architecture is or comparing the pros/cons of operating a headless CMS - it focuses on using Wagtail within a MACH architecture.

Wagtail can operate headlessly as part of a MACH architecture or headful as part of a more traditional monolithic architecture.

As a reminder, MACH stands for:

  • Microservices
  • API-first
  • Cloud-native
  • Headless

How can Wagtail align with both MACH and monolithic architectures?

We'll use the four principles of MACH architecture to explain how Wagtail works great in either architecture:

Microservices

An application must provide a single, independent function to be classed as a microservice.

Wagtail provides a single business function: a Content Management System (CMS). While it can easily be extended to do more, thanks to how Django is built, Wagtail is a CMS at its core.

And as a microservice, Wagtail can be independently scaled as part of a distributed system.

Digging deeper into Wagtail's architecture and its ability to "do more", Wagtail's code is separated into modules (or "apps"), allowing developers to choose which Wagtail features to enable by adding them to INSTALLED_APPS.

Want the most basic installation of Wagtail?

INSTALLED_APPS = [
    # …
    "wagtail.sites", 
    "wagtail.users",
    "wagtail.search",
    "wagtail.admin",
    "wagtail",
]

Also want editors to manage documents or images?

INSTALLED_APPS = [
    # …
    "wagtail.documents",
    "wagtail.images",
]

You get the drift.

For those who want to learn more about extending Wagtail, see Django's documentation on Applications, Wagtail's documentation on contrib modules, and an extensive but incomplete list of third-party packages for Wagtail.

API-first

All functionality and content accessible to Django/Wagtail can be exposed via API(s), with developers or Wagtail editors controlling permissions.

Whether generating image renditions from the frontend website or exposing Wagtail content to external services/platforms, you can perform all interactions with Wagtail programmatically.

Wagtail includes a REST API powered by the Django REST Framework, whereas GraphQL API support is provided by wagtail-grapple (a separate package maintained by Wagtail core members), though both follow the OpenAPI Specification. Technically, any API format that works with Django will work with Wagtail.

Cloud-native

Wagtail runs anywhere - in the cloud or on-premises. It works well in containers and is fully scalable.

Headless

Unlike a decoupled CMS (e.g. WordPress, Drupal), Wagtail doesn't provide a presentation layer (i.e. your website's consumer-facing frontend); it focuses solely on allowing editors to create and manage content.

While you may choose Django for your frontend presentation layer and may choose to run a monolithic stack with Wagtail and Django tightly coupled, there is no technical requirement for either.

How to configure Wagtail to run headlessly

A few additional steps are required to configure Wagtail to run headlessly above and beyond the default installation.

Step 1: Enable the API

First, decide which API format(s) to use - REST, GraphQL, or something else. Choosing which API format is a big decision with plenty of pros/cons, though if responses don't need to be cached, I prefer GraphQL due to the developer experience.

To use GraphQL, install/configure the wagtail-grapple package.

To use REST, enable/configure Wagtail's API.

Once configured, your chosen content should be surfaceable via API, which is the first step in decoupling the CMS from the frontend.

Step 2: Change how documents are served

By default, Wagtail surfaces documents by linking to an interstitial Django view that checks whether the user has permission to access the document. This approach won't work within a headless architecture as users won't have access to the Django backend, so attempting to view a document from the frontend would result in an HTTP 403 response.

Instead, we'll configure Wagtail to serve documents directly from storage by adding this to Django's settings:

# Serve document files directly from storage.
WAGTAILDOCS_SERVE_METHOD = "direct"

For more information, see the WAGTAILDOCS_SERVE_METHOD documentation.

Step 3: Make previews work again

Wagtail's neat live preview feature needs additional support to work headlessly, as the frontend is no longer within Wagtail's direct control.

Install and configure the wagtail-headless-preview package to expose preview data to the frontend and make previews work again.

Step 4: Build your frontend(s)

With Wagtail now configured for use within a MACH architecture (🥳), it's time to build your frontend(s) in whatever technology you like and connect them to the API(s).