webbyfox/ services/ wagtail cms development

01 · Wagtail practice

Wagtail CMS development & headless migrations.

For UK higher education, publishers and public-sector teams who've outgrown WordPress block-builders and need an editor-safe, schema-first publishing platform — optionally fronted by Next.js, fully WCAG 2.2 compliant, and ready for AI-assisted editorial tooling.

Sound familiar?

  • Editors keep "breaking" the homepage because the block-builder lets them drop a hero anywhere
  • WordPress plugin sprawl means every minor upgrade is a release-week panic
  • You need a Next.js or React frontend but your CMS only thinks in PHP templates
  • Accessibility audits keep failing and the dev team can't enforce alt-text or heading order at the editor level
  • Marketing wants multi-site, multi-language, and AI-assisted drafting — your current CMS does none of it

The model-first, editor-safe workflow.

Wagtail's killer feature is that page schemas are defined in Python — not assembled at runtime by a marketing manager dragging blocks around a canvas. You set the rules in code; editors get freedom inside them, not freedom over them. The result is a publishing platform that's flexible for content teams and predictable for engineers.

// axis
PHP block-builders
Wagtail StreamField
layout safety
Editors can drop any block anywhere; layouts drift over time.
Schema-enforced. Each block type declares its allowed children, validators, and parent contexts in Python.
content portability
HTML blob in post_content — opaque to APIs and analytics.
Typed JSON. Every block has a clean schema; safe to expose via REST or GraphQL with zero re-modelling.
version history
Plugin-dependent; rollback often loses block state.
First-class revisions. Every save creates an atomic revision you can diff, preview, and restore.
type safety
Loose dictionaries; rename a field and 500s appear at the edge.
Typed models. Django migrations make schema change a deploy-time event, not a runtime surprise.
accessibility enforcement
Bolt-on plugins; rarely block publication.
Axe-core built into the admin. Editors see violations before they hit publish.

Monolithic Wagtail templates when it fits

  • Content-led marketing site or institutional site
  • Editorial team of 2–10, one frontend surface
  • SEO speed and time-to-publish matter most
  • Smallest possible total cost of ownership

Headless Wagtail + Next.js when it fits

  • Rich, interactive frontend (course finders, configurators, dashboards)
  • Multiple consumers — web, native mobile, kiosk, partner sites
  • Frontend and CMS need independent release cadences
  • Editorial team wants live preview parity with production

A step-by-step data migration blueprint.

A WordPress, Drupal or Sitecore export is almost never structured content — it's a tangle of inline HTML, shortcodes, relative links and orphaned media. We don't dump it into a single rich-text field and walk away. We parse, clean and re-typecast it into Wagtail StreamField blocks your editors can actually maintain.

M.01

Source export & inventory

WXR, database snapshot or live API crawl. We catalogue every URL, content type, custom field and media reference into a typed migration plan.

→ migration_plan.json
M.02

HTML parsing pipeline

Custom BeautifulSoup pipelines extract semantic structure from messy WYSIWYG output and emit typed StreamField blocks — paragraphs, headings, pull-quotes, code, galleries.

→ BeautifulSoup · lxml
M.03

Link & media rewriting

Relative <a href>s become database-backed Wagtail page references. Media is downloaded, deduplicated, alt-text inferred, and stored in Wagtail's image renditions.

→ no dead links
M.04

Dry-run & diff review

Every page is rendered side-by-side: old vs new. Editors approve a sample, we tune the parser, then re-run end-to-end against the full dataset.

→ visual regression
M.05

Redirects & SEO continuity

301 redirects from every legacy URL, canonical tags preserved, sitemap regenerated, structured data ported. No drop in Search Console impressions.

→ /seo-handover.csv
M.06

Cutover & freeze

Final delta migration during a short editorial freeze. DNS switch, observability dashboards on, on-call rota for 72 hours. You go live with confidence.

→ go-live

Built-in compliance & WCAG 2.2.

UK public-sector bodies sit under the Public Sector Bodies (Websites and Mobile Applications) Accessibility Regulations 2018. Private-sector enterprises now face the European Accessibility Act. We configure Wagtail's built-in Axe-core checker to audit editor content in real time — before publication, not after a complaint.

A.01

Editor-time accessibility checks

Axe-core runs inside the Wagtail admin against every preview. Editors see — and have to acknowledge — accessibility violations before they can publish.

pre-publish
A.02

Alt-text enforcement

Custom image block validators block save when alt-text is missing, generic, or duplicates the filename. AI-suggested alt-text is offered as a starting point — never auto-applied.

enforced
A.03

Heading-order linting

StreamField validators reject pages that skip heading levels or use H1 more than once. Reading order is checked against the rendered DOM, not the source markup.

DOM-aware
A.04

Audit logs for compliance

Every accessibility check produces an auditable log entry. Attach the export directly to your accessibility statement or GDS service assessment evidence pack.

GDS-ready
A.05

Keyboard & screen-reader testing

Frontend components are smoke-tested with axe-playwright in CI. We test against NVDA + Firefox and VoiceOver + Safari before sign-off.

CI-gated

Secure draft previews on a headless frontend.

When the frontend is Next.js and the CMS is Wagtail, the trickiest moment in the day is "let me preview my draft." We override PagesAPIViewSet to serve the latest unpublished revision behind a short-lived signed token — so editors get true preview parity without exposing draft content to the world.

api/views.py · wagtail draft preview endpoint PYTHON
# Override Wagtail's default endpoint to serve secure draft previews
# to a Next.js preview canvas, gated by a short-lived signed token.
from django.http import Http404
from rest_framework.response import Response
from wagtail.api.v2.views import PagesAPIViewSet

from .auth import verify_preview_token


class DraftPagesAPIEndpoint(PagesAPIViewSet):
    """Serve live pages by default; draft revisions for valid preview tokens."""

    def detail_view(self, request, pk):
        instance = self.get_object()

        if request.GET.get('draft') == 'true':
            # Reject anyone without a valid, signed, short-lived token
            if not verify_preview_token(request, page=instance):
                raise Http404("Preview token invalid or expired.")
            # Fetch the latest unpublished revision for the preview canvas
            instance = instance.get_latest_revision_as_page()

        elif not instance.live:
            raise Http404("This page is draft-only.")

        serializer = self.get_serializer(instance)
        return Response(serializer.data)

A few details that matter: we never trust a raw ?draft=true flag, the token is HMAC-signed against the page ID and expires in 60 seconds, and the response sets Cache-Control: private, no-store so no edge cache leaks draft content.

What you walk away with.

Production-ready Wagtail, owned by your team. No vendor lock-in, no proprietary block format, no surprises six months later.

01
Typed StreamField content model

Page types, blocks, validators and snippet models in Python, documented and tested. Your editors get safe flexibility; your engineers get migrations they can reason about.

02
Headless API or Django templates

REST & GraphQL endpoints, preview tokens, image renditions and ISR-friendly cache headers — or fast server-rendered Django templates if that's the right call.

03
Editor training & handbook

Two live sessions plus a written handbook tailored to your actual content model. Editors are productive on day one, not day thirty.

04
WCAG 2.2 audit + statement

Independent accessibility audit, prioritised remediation, and a draft accessibility statement matching the Cabinet Office template.

05
CI/CD & observability

GitHub Actions pipeline, preview environments per PR, Sentry & structured logs wired up, on-call runbook for the first 90 days.

06
SEO continuity package

301-redirect map, canonical preservation, sitemap, structured data and a Search Console handover so post-launch impressions hold steady.

Common questions.

Can you migrate our WordPress site without breaking links or losing SEO?

Yes. The migration pipeline parses your WXR export through BeautifulSoup, rewrites relative links into database-backed Wagtail page references, and reissues 301 redirects from every legacy URL. Canonical tags are preserved and structured data is ported. Most clients see no drop in Search Console impressions post-launch — and several see an uplift inside three months thanks to faster Core Web Vitals.

Should we go headless with Next.js or stay on Django-rendered templates?

Headless makes sense when you need a richly interactive frontend, multiple consumers (web + mobile + kiosk), or want frontend and CMS release cycles to be independent. Monolithic Wagtail templates remain the lower-cost choice for content-led sites where the editorial team is small and SEO time-to-render matters more than client-side interactivity. We help you make the build-vs-buy call before any code is written — usually inside a 2-week Discovery Sprint.

Do you work with public-sector procurement frameworks like G-Cloud?

Yes. We structure delivery to align with the GDS Service Standard — separate Discovery, Alpha, Beta and Live phases, accessibility statements, open-source preference, and exit transition planning. We're comfortable working under G-Cloud terms and producing the architectural evidence procurement teams need.

How does Wagtail handle multi-language and multi-site at scale?

Wagtail supports multi-site (one install, many root pages) and multi-language (via wagtail-localize) natively. We've shipped configurations with 12+ sites in 8 languages on a single install. Editorial workflow, translation review, and per-locale publishing schedules are all supported.

What if our team has never used Wagtail before?

Wagtail's admin is genuinely the easiest CMS to onboard editors into — most teams are productive after a single one-hour session. We include two live training sessions plus a written handbook tailored to your specific page types and editorial workflow. After go-live we offer a 90-day support window where your team can raise questions and we triage them within one business day.

Can we add AI features (RAG search, AI alt-text, content generation) later?

Yes — that's a deliberate design goal. Because Wagtail content is typed Python models, we can layer AI features directly onto the same domain model: pgvector embeddings of page content for semantic search, AI-suggested alt-text and SEO meta, draft translation, tone-matching. See our Applied AI & RAG practice for the full picture.

Ready to leave the block-builder behind?
Let's scope it.

Discovery sprint
2 weeks · fixed-price · £8k
Migration build
8–14 weeks · from £45k
Greenfield Wagtail
6–10 weeks · from £35k