Routing and menus in decoupled Drupal

Decoupled Router and JSON:API Menu Items let editors keep control of URLs, aliases, redirects and navigation while a separate front end renders the site. This page covers how they work, how to configure them and what to confirm before building.

On this page

How decoupled routing keeps editors in charge of URLs and navigation

Teams moving to a Next.js or other framework front end still need editors to own URLs, redirects and navigation, and that control has to live in Drupal. Decoupled Router resolves incoming paths against Drupal's path aliases and redirects so the front end can ask Drupal what a URL points to, and JSON:API Menu Items exposes the menus editors build in Drupal as JSON the front end can render. Teams need both as soon as the public site is no longer generated by Drupal's own theme layer, because otherwise every new page, renamed section or redirect becomes a developer ticket. The split is simple to state and easy to get wrong. Drupal is the source of truth for routes, aliases, redirects and menu structure, while the front end is the renderer that turns those answers into pages. Drupal core already handles aliases and redirects for its own pages, but a decoupled build depends on contributed modules and on how the front end calls them, so this page covers the work DeployOpen plans around that split: which entities editors may alias, how redirects are matched and ordered, how menus are scoped by language and role, and how the front end handles paths that Drupal does not recognize. Confirm the exact module versions against the Drupal version you run, since compatibility is per release.

The decisions that matter most are made before the first menu item is built. Decide which content types get path aliases and which get fixed routes owned by the front end, since mixing the two produces collisions that are hard to debug later. Decide who may create redirects, how they are reviewed, and whether imports from the old site will be loaded as redirects so inbound links and search rankings survive. For menus, decide whether editors manage one shared menu tree or per-language trees, and whether the front end should receive menu items already filtered for access. Each of these choices changes the endpoints the front end calls and the editorial workflow, so they belong in the written scope. Verification should run against the front end, not only against Drupal. Test a sample of old URLs through the new build, confirm that an alias change in Drupal shows up on the public site after the cache clears, and check that unknown paths return the right status code. Plan for the ongoing cost as well: redirect tables grow, menu changes need a publishing check, and each Drupal or front end upgrade can change how paths resolve. Ask any partner to price the setup and the maintenance of these routing rules separately, so you can see what your own team would need to keep running after launch.

Which routing and menu options fit which build

This table compares four ways to handle routing and navigation in a decoupled Drupal build, from Decoupled Router alone to keeping all routing logic in the front end. Read each row against your editorial needs and how much custom code your team is prepared to maintain. The main takeaway is that the more logic you move out of Drupal, the more your front-end team owns, and the more editors depend on fixed conventions.

OptionWhen it fitsWhat editors gainWhat the team maintains
Decoupled Router aloneOne front end with conventional page paths that editors manage through URL aliasesEditors set and change path aliases in Drupal, and the front end resolves them to contentFront-end catch-all route, handling for unknown paths, and checks that aliases stay unique
Decoupled Router with JSON:API Menu ItemsEditors need to control site navigation order, labels and parent-child structure without a front-end releaseMenus are edited in Drupal and appear in the front end through the menu endpointMapping of menu link data to front-end components, caching of menu responses, and menu depth limits
Custom JSON:API menu resourceNavigation needs fields or rules that the standard menu output does not carry, such as icons, audience flags or localized labelsEditors gain the extra fields they need, as long as the custom resource is designed with themA custom module, its schema, access rules, tests and upgrades alongside Drupal core releases
Front end owns routing, Drupal stores aliases onlyThe front-end framework controls URL structure and content is reached through stable IDsEditors enter content and aliases but cannot change navigation or route structure directlyRouting and navigation definitions in code, redirect logic, and content editing workflows that link to front-end routes
Redirects managed in DrupalMigrated sites or changed URLs where search rankings and bookmarks must be preservedEditors create and review redirects without developer helpRedirect rule ownership, loop checks, and verification that the front end honors redirect responses

Setting up Decoupled Router and menus step by step

This sequence takes a Drupal backend from a compatibility check to a headless front end that resolves editor-managed paths and navigation correctly. Each step closes with a check, so the team knows the routing and menu layer works before the front end depends on it.

  1. Confirm core and module compatibility

    Before installing anything, the team confirms that the Drupal core version in use supports the planned Decoupled Router and JSON:API Menu Items releases, and that the PHP version meets the requirement for that core line. Drupal 11 requires PHP 8.3 or later, and Drupal 10 requires PHP 8.1 or later. Check the compatibility statement on each contributed project page and record the exact versions in the project's composer.lock file. The step is done when a clean local build installs with those versions and the status report shows no errors.

  2. Install and configure Decoupled Router

    The developer installs the Decoupled Router module with Composer, enables it, and sets the JSON:API endpoint prefix and the front end's base URL in the module configuration. The backend should then answer path resolution requests for known aliases. Confirm the module is enabled on the environment that the front end will call, not only on the developer's laptop. The step is done when a request for a published node's alias returns the entity type and UUID that the front end needs.

  3. Set up path aliases and redirects

    An editor or site builder creates a test set of path aliases and at least one redirect for a retired URL, using the core Path and Redirect modules. Aliases should be generated by pathauto or set manually, and each alias should map to exactly one canonical node. Check that alias uniqueness is enforced and that the redirect target is the intended current page. The step is done when a sample set of old and new URLs resolves to the expected content through the backend, with no loops or 404s.

  4. Expose menus through JSON:API Menu Items

    The developer installs JSON:API Menu Items and enables the resource for each menu the front end needs, such as the main and footer menus. Confirm which menu fields are returned, including the link URL, title, weight and parent, and remove any fields the front end does not need. Request each menu endpoint with a valid token or public access, depending on the site's model. The step is done when a menu response lists the parent and child items in the order set in the Drupal admin interface.

  5. Connect the front end catch-all route

    The front end engineer adds a catch-all route, typically a dynamic segment at the root of the app, that takes the requested path, asks Decoupled Router for the matching resource, and renders the correct template. The route should return a not-found response when the backend reports no match, and it should pass redirects through to the browser with the correct status code. The step is done when a request for an alias renders the matching page and an unknown path returns a 404 response.

  6. Test editor changes end to end

    An editor changes an alias, adds a menu link and unpublishes a page on a staging environment. The team then checks that the front end reflects each change after the cache is cleared or the revalidation hook runs. Test the old URL, which should redirect or return a not-found response as designed, and the new URL, which should render the page. Record the cache-clearing method in the runbook, since it determines how long editors wait for changes to appear. The step is done when every editor change produces the expected result on the front end and the test cases are saved for regression checks after upgrades.

Security and operations risks in headless routing

Path resolution, redirects and navigation sit between Drupal and a public front end, so a mistake in one place shows up in the other. The cards below cover the exposure, caching and patching risks that connect them, and the recurring checks that keep editors' URL decisions working after launch.

Unpublished content through path resolution

A resolver that maps a path to an entity can return content the public should never see if access checks are skipped or the front end requests a node by ID. Decoupled Router resolves paths through Drupal's entity access system, so test drafts, unpublished revisions and content restricted to certain roles from an anonymous client. Confirm that the front end never fetches by internal ID for public routes. Also check which fields the resolver exposes for each entity type.

Redirect loops and open redirects

Redirects created by editors can point at each other, and a front end that follows them without a hop limit can loop or fail on a routing response. Redirect targets that accept arbitrary external URLs can also be used to send visitors to other sites from your domain. Review who can create redirects, restrict external targets where your policy requires it, and test the front end's handling of 301 and 302 responses with a loop-detection case in the test set.

Stale menus and aliases in caches

Menus and path aliases are often cached at the front end, the CDN and the Drupal page cache, so a rename or unpublish can stay visible after the editor saves. Confirm which layer owns invalidation for each route type and whether menu changes purge the cached navigation payload. Test a menu edit, an alias change and a node unpublish on a staging build, then check that each layer returns the new result within the window your content team expects.

Patching contributed routing modules

Decoupled Router, JSON:API Menu Items and related modules are contributed code, so their vulnerabilities are published through the Drupal Security Team's advisory process rather than through core releases. Security releases come out on the third Wednesday of the month, so schedule a standing review of advisories for every contributed module on the routing path. Keep a record of the module versions in each environment so you can confirm exposure within the same day an advisory appears.

Monitoring the resolution endpoint

The endpoint that turns a path into a route is called on every page view, so failures in it show up as blank pages or 404s across the whole site. Monitor response codes, latency and the ratio of resolved to unresolved paths, and alert when unresolved paths rise after a deployment. Log the requested path and the response type so support can trace a reported broken link without guessing which route was involved.

Keeping redirect tables clean

Redirect tables grow as editors rename pages, and old chains of A to B to C redirects slow resolution and make behavior hard to audit. Schedule a recurring review that collapses chains, removes redirects to deleted content and flags redirects whose targets now return 404. Ask your content team who owns this review and how often it runs, because the work recurs for the life of the site and is rarely included in launch scope.

Questions teams ask before routing a headless Drupal build

What drives the cost of routing and menus in a decoupled Drupal build?

The cost follows the number of URL patterns, content types and menus that need to resolve correctly in the front end, not the number of pages alone. The main drivers are how many content types carry editor-managed aliases, how many menu levels and menu sources (main, footer, language-specific) the front end must render, whether redirects must be imported from an old site, and how many front-end routes must be mapped to Drupal entities. Each of these adds design, build and test work. A quote should break the effort into URL policy, Drupal configuration, front-end route resolution, redirect handling and verification, and it should say which items are one-time and which need ongoing maintenance when editors add new content types or menus.

How long does a routing build take in general terms?

Duration depends on how many content types and menus are involved, how much legacy URL data must be preserved, and how many front-end frameworks or sites share the same Drupal. A small site with a few content types and one menu is usually a short, focused task, while an estate with several languages, imported redirects and multiple front ends takes longer because each route type needs its own test cases. Ask any partner for a timeline built from a written scope, and ask which parts run in parallel, such as URL policy sign-off while the front end is being scaffolded. No fixed duration applies to every project.

What does the client team need to provide before routing work starts?

The most important input is an editorial URL policy: the rules for how paths are built from titles, categories and dates, who may override an alias, how long old paths must keep working, and what happens when a page is unpublished. Teams should also provide a current URL inventory or crawl export, the list of menus and their editors, sample content covering each content type and language, the redirect rules that must survive the move, and the front-end routes the new site will expose. Without sample content that includes long titles, special characters and translated pages, the test plan will miss the cases that break in production.

Can an in-house team build decoupled routing without a partner?

Yes, if the team already has Drupal and front-end engineers who understand entity routing, path aliases and caching, and if someone owns the URL policy. The work is mostly configuration, a small amount of custom code for front-end route resolution, and careful testing. The gaps usually appear in redirect migration, cache invalidation when aliases change and multilingual edge cases, because these only show up under realistic content volumes. A useful test is whether the team can name who approves alias changes, how a broken menu link is detected and how a redirect is added without a developer. If those answers are unclear, an external review or short implementation engagement can fill the gap.

How are migrated Drupal 7 URLs handled in a headless build?

Drupal 6 and 7 sites cannot be updated in place to Drupal 10 or later. They are migrated into a new site with the core Migrate, Migrate Drupal and Migrate Drupal UI modules or with Drush, and themes must be rebuilt. URL handling is a separate planning task: the path aliases stored in the old site should be mapped to the new content, and any old paths the public expects to keep must become redirects or aliases in the new site. The front end then needs to resolve those paths to the right content. Teams should confirm how their old URLs were structured, which patterns search engines and bookmarks rely on, and how the migrated aliases will be checked against the URL inventory before cutover. Drupal 7 security support ended on January 5, 2025, so any delay in migration has a security dimension as well as a routing one.

What changes to routing and menus when Drupal is upgraded?

Drupal's core release schedule says bugfix releases come out on the first Wednesday of each month, security releases on the third Wednesday, and new major versions typically every three years. Drupal 11 is the current major version, Drupal 12 is scheduled for the week of December 7, 2026, and Drupal 10 reaches end of life on December 9, 2026. For a decoupled build, minor and patch upgrades mostly affect the JSON:API and path resolution behavior the front end depends on, so the front end should have automated tests for routes, menus and redirects. Major upgrades need a check of contributed modules that handle routing and menus, a review of PHP requirements (Drupal 10 requires PHP 8.1 or later, Drupal 11 requires PHP 8.3 or later and Drupal 12 requires PHP 8.5 or later), and a pass over the URL policy. Ask a partner to show how the routing test suite is run before and after each upgrade.

Limits to confirm in your environment

Decoupled routing and menus depend on several moving parts: a Drupal core version, contributed modules, a front end framework and a CDN in front of both. Each link in that chain has limits that vary by release, so confirm them with the module maintainers or in a test environment before the build plan is fixed.

Module versions against core

Confirm which release of each routing and menu module supports your exact Drupal core version. Core and contributed projects move on separate schedules, and a module that works on one minor release may lag behind the next. Check the project page's compatibility statement and run your candidate versions against a copy of production content before you pin them in Composer. Record the result so the next upgrade starts from a known pairing. Ask the maintainers which releases they test against.

Framework support for path resolution

Ask whether your front end framework has a supported integration for resolving Drupal path aliases and redirects. Some frameworks document a route handler pattern, while others expect your team to write the lookup and fallback logic. Test a nested alias, a renamed alias and a removed node in your own framework version. Confirm how the framework handles dynamic routes, catch-all segments and cache revalidation when an editor changes a URL.

Redirects across language versions

Confirm how redirects behave when the same node has translations with different aliases. An alias change in one language may not update the others, and a redirect created for an English path may not match a German or French request. Test each language prefix, the fallback language and the home page separately. Check whether your redirect module creates entries per translation, and whether your front end honors the language prefix when it resolves a path.

Menu items and language selection

Verify that menu links returned to the front end carry the correct language, weight and parent relationships for each translation. Menus may fall back to the default language when a translated link is missing, which can expose broken navigation to visitors. Confirm the exact fields your menu endpoint returns, and test a menu with an unpublished child item and a link to an external URL.

CDN caching of routing responses

Confirm the cache headers your CDN and reverse proxy apply to path resolution and menu responses. A cached redirect can keep sending visitors to an old URL after an editor changes an alias, and a cached menu can show removed links. Check whether purging is triggered by Drupal cache tags, whether the front end revalidates on a timer, and how long stale responses can persist. Test the full path with a real alias change before launch.

Authenticated and preview routes

Confirm how unpublished content and draft menu items are resolved for editors previewing pages on the front end. Preview requests often bypass the public cache and must carry a session or token that the public route does not. Verify that a preview link cannot expose unpublished aliases to anonymous visitors, and that the preview token expires on the schedule your security policy requires.

When to keep routing in Drupal and when to move it to the front end

Keep URL and redirect ownership in Drupal when editors create and change content paths, when the site already ranks for its existing URLs, or when the organization needs editors to fix a broken link without opening a ticket. In that model, Decoupled Router resolves the path alias on the Drupal side and tells the front end which entity to render, so the editor's alias and the redirect rules stay in one place. The default should be Drupal-owned routing unless the team has a clear reason to give that control away. Ask the front end team to confirm which path resolution their framework will perform on each request, and where a redirect will be evaluated when both the framework and Drupal hold a rule for the same path.

Move routing to the front end only when the team accepts that editors cannot change a URL without a developer. That trade-off is real for SEO continuity. Every URL change becomes a code change and a deployment, and the team must maintain a separate redirect map outside the content workflow. Migrations raise the stakes: if the existing site uses path aliases that the new front end does not reproduce exactly, search engines and inbound links will hit errors until the mapping is corrected. Before committing, export the current alias and redirect inventory, count the number of redirects that carry traffic, and confirm with the SEO owner which of them must survive unchanged.

Whichever side owns routing, test it as part of the migration rather than after launch. Compare a sample of legacy URLs against the new site for status codes, final destinations and canonical tags, and confirm that the menu data delivered through JSON:API Menu Items matches the navigation editors expect. The cost of this work depends on how many aliases, redirects and menu levels the site carries, so ask any partner to quote it from a written inventory of those items rather than from a general estimate.

How DeployOpen scopes and delivers decoupled routing work

Routing and menus touch editorial habits, module choices, front end code and long-term upkeep, so DeployOpen agrees on each of them in writing before build starts. The cards below follow that order, from the URL policy editors will live with to the documentation and support that keep it working after launch.

Editorial URL policy

Before any module is configured, DeployOpen works with editors to write down who owns path aliases, how slugs are generated, when a changed title may or may not change a URL, and which redirect is created automatically. This policy is the basis for every later decision. Check that it names the content types covered, the languages in scope and the approval step for manual overrides, because gaps here become inconsistent URLs across the whole front end.

Module selection and fit

The scope names the Drupal modules that resolve paths and expose menus, and confirms how each one is installed, versioned and reviewed against the Drupal version in use. Module choice drives what the front end can request, so the team should confirm which contributed projects are actively maintained for the target Drupal release before committing to them.

Front end integration contract

DeployOpen documents the exact request pattern the front end will use to resolve a path, fetch a menu tree and handle a missing or redirected URL. The contract covers response shape, status codes, caching behavior and the fallback when Drupal returns no match. Ask for this contract in writing so the Next.js or other front end team builds against a fixed interface rather than assumptions.

Alias and redirect test plan

The test plan lists the URLs that must resolve, the old URLs that must redirect, and the expected status codes for each. It includes editor-created aliases, changed titles, deleted nodes, language variants and redirect loops. Confirm that the plan runs automatically against the staging environment and that failures block release, since a single broken route can break search rankings and inbound links.

Menu structure and governance

Navigation is delivered as data, so the scope defines who can change menu items, how menus are split by site section or language, and how link targets are validated. This prevents a menu edit from pointing at an unpublished page. Confirm who approves structural changes and whether editors can reorder items without a developer.

Handover and optional retainer

At handover, DeployOpen delivers configuration notes, the URL policy, the test suite, runbooks for redirect cleanup and a record of custom code. Module upgrades, Drupal version changes and new routing rules can be covered by an optional retainer. Ask for the retainer scope in writing, including who reviews upgrade notes and how regression tests are rerun.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.