Frameworks & CMS

Django or WordPress: which ships your roadmap on time?

A product manager scoping a CMS rebuild usually gets trapped between two pitches: ship quickly with an integrated CMS, or invest in a headless stack for flexibility. My position: default to the coupled CMS unless the product roadmap already contains multiple front ends or unusual publishing rules, because headless content creates engineering work that teams routinely under-budget.

Most single-site products should choose the coupled CMS first

Coupled CMS Stack means one platform owns content modeling, editing, routing, preview, templates, and publishing. WordPress 6.5 with the Block Editor, Drupal 10 with Layout Builder, Statamic 5 on Laravel 11, and Craft CMS 5 all fit this model, even though their developer experience differs. Headless Composition Stack means content lives in one system while rendering happens elsewhere, often with Next.js 14, Nuxt 3, Astro 4, Remix 2, SvelteKit 2, or a native app consuming REST, GraphQL, JSON:API, or GROQ.

Top Frameworks and CMS for Modern Web Development argues for surveying the landscape, but the scoping mistake is treating every option as equally cheap to operate. The integrated CMS wins when the product is one primary website, the content team needs visual authoring, and the roadmap is full of ordinary page types, because fewer separate systems means fewer preview states, deployment dependencies, and support handoffs.

The Rise of Headless CMS in Modern Web Architecture captures the architectural pull toward APIs, but API-first content only wins after a product manager budgets the missing glue. That glue includes preview tokens, draft APIs, webhooks, cache purging, rich-text rendering, image transformation, redirects, search indexing, content migrations, and permission mapping.

I would not choose a headless CMS for a single marketing site with normal landing pages, author bios, case pages, forms, and a blog, because it turns solved editorial problems into custom product requirements. A PM may disagree if the engineering team prefers React everywhere, but preference is not scope reduction when editors still need approvals, previews, redirects, media reuse, and scheduled publishing.

The practical decision is not “old CMS versus new architecture.” It is whether the team benefits more from a bundled publishing surface or from separating content from presentation. Coupling is not technically inferior when it shortens the path between “editor changed the page” and “the page is safely live,” because that path is where many launch delays hide.

Headless wins only when distribution or product behavior justifies the extra seams

Option 1: Coupled CMS Stack. It wins when the site is the product’s main content destination, page composition matters more than omnichannel reuse, and the editorial team expects to publish without asking engineering for each layout change. Its cost is slower freedom for highly custom interfaces, because templates, plugins, and CMS conventions can constrain unusual experiences.

Option 2: Headless Composition Stack. It wins when the same content must power a website, app surface, authenticated dashboard, partner feed, and localized microsites from one model, because API-driven content avoids duplicating copy and governance across products. Its cost is integration ownership, because no headless CMS automatically gives you production-grade routing, front-end preview, CDN invalidation, analytics continuity, or editorial troubleshooting.

That comparison is the core scoping conversation. Contentful, Sanity, Storyblok, Strapi 5, Directus 10, Hygraph, Prismic, and Payload 3 are serious tools, but buying one does not remove the need to design content contracts. With Contentful’s GraphQL Content API, for example, a product team still has to decide which fields are nullable, which entries can be referenced recursively, and how fallback locales behave. With Sanity GROQ, the team still has to govern projections so front-end developers do not ship brittle queries across every route.

Use headless when content is a shared product asset. A subscription product with a web app and a logged-in help surface may justify headless because the same structured guidance can appear inside onboarding, account pages, and public documentation. A campaign website usually does not justify it because the content loses value when detached from layout, visual review, and publishing speed.

For scoping, ask whether the first release needs more than 2 consumer applications; treat that threshold as a planning trigger to examine headless, not as a universal law. If the answer is one public website and a possible future app, postpone headless because speculative channels create current sprint work without current user value.

The missing work in headless is preview, caching, and governance

Headless projects are underestimated because the demo path is short: create a content type, fetch JSON, render a page. The production path is longer because editors need to see drafts, users need fast pages, and support teams need to debug mismatches between CMS state and rendered output.

A realistic headless backlog should include draft preview with signed URLs or session cookies, webhook handling from Contentful, Sanity, Strapi, or Storyblok, and cache rules in Vercel, Netlify, Fastly, or Cloudflare. It should also include media transformation through Imgix, Cloudinary, Next.js Image Optimization, or a CMS-native asset pipeline, because ungoverned images are a common source of slow pages.

Google’s documented Core Web Vitals thresholds are LCP at 2.5 seconds, INP at 200 milliseconds, and CLS at 0.1 for a good experience, and those numbers matter because a distributed CMS architecture often shifts performance risk from the CMS vendor to the front-end team. Treat 300 seconds as a tunable revalidation interval for non-critical pages, because shorter intervals increase freshness while longer intervals reduce origin calls and deployment noise.

Contentful publishes a default Content Delivery API limit of 55 requests per second for many spaces, and the exact plan limit matters because a naive front end can accidentally turn one page view into several API calls. Run a measured content-entry trial with 3 editors rebuilding 10 existing pages, because the result exposes whether the schema supports real publishing or only developer demos.

A small smoke test can reveal whether the CMS API, cache headers, and response shape are acceptable before the team commits to a stack. Save this as cms-smoke-test.mjs and run it with Node.js 20:

const url = "https://wordpress.org/news/wp-json/wp/v2/posts?per_page=5";
const started = performance.now();
const res = await fetch(url, { headers: { accept: "application/json" } });
const posts = await res.json();

console.log("status", res.status);
console.log("cache-control", res.headers.get("cache-control"));
console.log("ms", Math.round(performance.now() - started));
console.log(posts.map((p) => p.slug).join("\n"));

This is not a benchmark, because one request cannot model production load, but it makes the PM ask useful questions: where does caching happen, what headers exist, how large is the payload, and what breaks when the CMS is slow? The same exercise can be repeated against Drupal JSON:API, Strapi REST, Sanity’s HTTP API, or a GraphQL endpoint using persisted queries.

Governance also needs scope. OpenAPI 3.1 helps document REST contracts, GraphQL schemas help introspection, and TypeScript 5.4 helps detect broken assumptions at build time, but none of them decides who can delete a field, rename a content type, or publish an entry that removes required copy. Those decisions belong in the project plan because content model changes are product changes.

Coupled CMS work is less glamorous, but easier to estimate

The coupled stack has its own costs, and pretending otherwise creates disappointment. WordPress plugin conflicts can slow delivery because dependencies may assume different versions of PHP, Gutenberg blocks, or REST endpoints. Drupal configuration management can be disciplined but heavy because content types, views, roles, and modules move through deployment pipelines. Craft CMS and Statamic can be clean for developers, but their licensing and ecosystem choices need review because fewer ready-made plugins can mean custom work.

Still, a coupled CMS is easier for a PM to estimate when the scope is content-heavy and interaction-light. Page templates, editor permissions, redirects, forms, menus, media, SEO fields, sitemap generation, and preview are usually first-class concerns. The cost is less architectural optionality, because the CMS shape influences the front end, but that trade is often acceptable when launch certainty matters more than channel abstraction.

Use a coupled CMS when the editorial team needs visual composition inside the same system that publishes the page. WordPress Full Site Editing, Drupal Layout Builder, Craft Matrix fields, and Statamic Bard fields all reduce custom interface work because editors assemble content through native patterns. A custom React preview can match that experience, but it costs more because the team must rebuild editing affordances the CMS already has.

For scope, budget 5 to 8 working days as an adjustable allowance for content migration mapping on a medium site, because redirects, media references, author fields, and HTML cleanup usually consume more time than the import script. Reserve another 1 to 2 days as a planning number for editorial acceptance testing, because a build is not ready if editors can only publish by following developer-written workarounds.

The performance argument against coupled CMSs is weaker than many teams assume, because full-page caching, CDN rules, object caching with Redis 7, and modern PHP 8.3 can serve mostly static content well. A badly configured WordPress site can be slow, but a badly configured Next.js headless site can also be slow when it over-fetches GraphQL, disables static generation, or purges caches too broadly.

The security argument is also not decisive by itself, because every architecture has exposed surfaces. A coupled CMS exposes the CMS application, while a headless stack exposes APIs, webhook receivers, preview endpoints, build tokens, and front-end dependencies. The PM should scope patch ownership either way, because “managed” rarely means “no operational responsibility.”

Start by pricing the handoffs before pricing the software

The first concrete step is to run a two-hour scoping workshop with product, engineering, design, and one real editor. List every handoff from draft to live page, mark which system owns it, and assign a build-or-configure label. If most boxes sit inside one CMS, choose coupled; if content must travel across products, price headless honestly before committing.