Search engineering for a decoupled frontend
Decoupling changes who renders the page. That single change determines what a crawler receives, and it quietly removes several things a conventional CMS provided without anyone deciding to give them up.
The rendering decision is the search decision
In a conventional CMS the server produces the HTML and the crawler receives it. In a decoupled frontend the HTML may be produced at build time, per request, at the edge, or in the browser — and only some of those deliver complete markup to a crawler that does not execute JavaScript. That is not a performance question with a search side effect; it is the search question, and everything else follows from it.
- The frontend is decoupled and the site's visibility changed after the move
- Pages are indexed with the wrong title, description or content
- Redirects that used to work stopped working after the frontend took over
- Structured data that was present before the move is now absent
- The sitemap and the site disagree about which URLs exist
- Search results show content that is not on the page a visitor sees
- New content is discovered slowly
- Nobody has checked what the site serves before JavaScript runs
The people who usually bring us this problem
A team that has decoupled and lost visibility
The move happened and the search position changed with it.
A team about to decouple
You want the search consequences designed for rather than measured afterwards.
A team whose frontend renders in the browser
Content arrives through JavaScript and you need to know what a crawler actually gets.
What this costs while it goes unfixed
Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.
What a crawler receives is a rendering decision, not a framework property
A statically generated route delivers complete HTML. A server-rendered route delivers complete HTML per request. A client-rendered route delivers a shell that depends on execution. All three are possible in the same application, and the search outcome is decided route by route rather than by the choice of framework.
Decoupling removes things a CMS provided implicitly
A WordPress site redirects, generates canonicals, publishes a sitemap and resolves internal links because the CMS does that. Once the frontend serves the request, none of it happens unless it is rebuilt — and the removal is silent, which is why it is usually discovered from a traffic chart rather than from a decision.
Client rendering splits the page into two versions
What is delivered and what is displayed are different documents, and a crawler's view of the page depends on whether it executed the second one. Where content arrives after load, the delivered version may contain none of it — and the symptom is a page indexed for its navigation rather than its content.
Structured data and metadata move to the frontend
Anything the CMS emitted is now the frontend's responsibility, per route and per content type. It is a generation problem rather than a markup problem, and it belongs with the rendering rather than being added to templates afterwards.
Capabilities
Each of these is work we carry out, not an area we advise on.
What each route delivers before JavaScript runs
The rendered response for every route class, fetched without executing the application, compared against what a browser displays. This is the first measurement and it determines whether the problem is a rendering choice or something else.
Rendering strategy for search
Which routes need to deliver complete markup and which can depend on execution, decided against what the content is and how it is found. Server or static rendering for content that has to be indexed; client rendering for what genuinely benefits from it.
Redirect ownership
Where redirects, canonical URLs and 404 handling live now that the frontend serves the request, and the inventory of addresses that has to be mapped onto them. This is the single largest search risk in a decoupling and the one most often left unowned.
Canonical and URL correctness
Canonicals generated by the frontend, agreeing with the URL that was fetched, the redirect that resolved and the sitemap entry. On a decoupled site these four can disagree, and each disagreement divides a signal that should be consolidating.
Metadata and structured data generation
Titles, descriptions, canonicals, hreflang and structured data emitted per route and per content type from the content model, so the set of page types with correct metadata is the set that exists. Authored per template, it drifts the moment a type is added.
Sitemaps from the route source
Sitemaps generated from the same data that generates the routes, so a page cannot exist without appearing in one. On a decoupled frontend the sitemap is frequently built separately and drifts immediately.
Internal link resolution
Content referencing other content — related items, cross-references, taxonomy links — resolved into real anchors in the delivered HTML. Where those resolve on the client, the crawler sees a page with no internal links, which is how a decoupled site becomes a set of unconnected pages.
Verification as delivered
Every route class checked on the response: markup completeness, metadata, structured data, canonical, status code and links. The intended output and the delivered output are different things, and only one of them is what a search engine reads.
Engineering methodology
The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.
Measure what is delivered before changing anything
The raw response per route class, without executing the application. That single measurement distinguishes a rendering problem from a metadata problem from a redirect problem, and it is the step that is skipped when a decoupling is diagnosed from a traffic chart.
Decide rendering per route against what has to be found
Not globally. A route whose content has to be indexed needs to deliver it; a route that is behind a sign-in does not. The decision is per class and it is recorded, so a later change has something to be measured against.
Assign ownership of redirects, canonicals and sitemaps
Named, in the frontend or in whatever serves the request, before the frontend takes traffic. The gap between WordPress ceasing to handle these and something else starting to is where visibility is lost, and it is lost without an error.
Generate metadata from the content model
Not from templates. A decoupled frontend already generates its routes from data; metadata, structured data and canonicals are generated from the same data or they drift as page types are added.
Verify on the response, per route class
Markup completeness, metadata, structured data, canonical, status and links, checked as delivered. A rendering configuration describes intent; the response describes what happened.
Measure the search outcome against a baseline
Coverage, impressions and clicks by page type, before and after, with the changes attributable. A decoupling can improve search delivery and it can break it, and which one happened is established rather than assumed.
What an engagement produces
Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.
Measurement
- What every route class delivers before JavaScript runs
- Where that differs from what a browser displays
- Redirects, canonicals, sitemaps and structured data: what exists and what was removed
- Internal links present in the delivered HTML
- A baseline of coverage, impressions and clicks by page type
Engineering
- Rendering strategy per route class, with the reason recorded
- Redirects, canonicals and 404 handling owned by the serving layer
- Metadata and structured data generated from the content model
- Sitemaps generated from the route source
- Internal links resolved into the delivered HTML
Verification
- Every route class checked on the response, not sampled
- Canonical agreement across fetch, redirect, declaration and sitemap
- Structured data validated as delivered
- Coverage, impressions and clicks by page type, against the baseline
- What remains dependent on client execution, and the consequence stated
Architecture and technology
What decoupling removes by default
- Redirects, which the CMS used to intercept before rendering
- Canonical URLs, unless the frontend generates them
- Sitemaps, unless something regenerates them from the content
- Structured data, which the CMS emitted
- Internal links between content, where they resolve on the client
- Content in the delivered HTML, if the route renders in the browser
What each rendering mode delivers to a crawler
- Static — complete HTML at build time, current as of the build
- Server-rendered — complete HTML per request, current as of the request
- Incremental or edge — complete HTML, current as of the last regeneration
- Client-rendered — a shell; the content depends on execution
- Mixed — different answers per route, which is why per-route measurement is the first step
If this is not quite your problem
These overlap at the edges. Sending you to the right page is more useful than having you work it out.
The architecture is still being designed
The full path from CMS through API and frontend to the cache layer.
Headless website developmentWordPress is being kept for editors
The decoupled arrangement where the CMS stays and the frontend changes.
Headless WordPress developmentThe frontend application needs engineering
Routing, rendering modes and data fetching per route.
Next.js developmentRendering is the specific problem
What a crawler does and does not execute, and what depends on it.
JavaScript SEOFrequently asked
Is a headless frontend bad for SEO?
No, and it can be better — a statically rendered route usually delivers faster, cleaner HTML than a CMS rendering it per request. The risk is not the architecture, it is what decoupling removes silently: redirects that a CMS plugin used to handle, canonicals it generated, a sitemap it published, internal links it resolved. None of that stops happening with a warning. It stops happening because the component that did it is no longer serving the request, and the symptom is a traffic chart rather than an error.
Do you have a headless SEO project?
No. Our published work is platform and infrastructure engineering, and none of it is a decoupled frontend a reader could inspect. The page describes what is measurable rather than what we have done: what each rendering mode delivers to a crawler, what decoupling takes away by default, and how redirects, canonicals and sitemaps are owned once the frontend serves the request. That is checkable on its own terms, and the first measurement — the raw response per route class — is the same for any site.
Do search engines render JavaScript?
They execute it, with limits that are not published and that change. The practical position is that a page whose content arrives only through execution is a page whose indexing depends on a second pass that may be delayed, partial or absent — and that is a risk taken route by route rather than a property of the framework. Where the content matters for search, delivering it in the response removes the dependency entirely, and that is a rendering decision rather than an optimisation.
Where should redirects live now?
Wherever the request actually arrives, which after a decoupling is no longer WordPress. That means the frontend, the edge, or whatever serves the request — and the important part is that something owns it and that the full inventory of existing addresses is mapped onto it. The gap between the CMS ceasing to handle redirects and something else starting to is where a decoupling loses its search visibility, and it is lost without any error being raised, which is why ownership is assigned before the frontend takes traffic.
How do we know if our frontend is delivering the content?
By fetching the response and looking at it, without executing the application. That is the whole check: if the content is in the delivered HTML, a crawler has it; if only the shell is, then indexing depends on execution. It takes minutes per route class and it is the measurement that should precede any other work — because a rendering problem, a metadata problem and a redirect problem all present as a decline, and only this distinguishes them.
Related capabilities and work
Bring us the problem you have not been able to fix
Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.