Proudly routed elsewhere: The decline of upstream URL management in CMS
May 18, 2021Since the earliest days of the content management system (CMS), one of its most entrenched biases has been its tight coupling to, and resulting dependence on, the URL—a relic of the page-bound web. From the first CMSs—glorified message boards and blogging tools—to the powerful monoliths of today, the notions of URL management and path manipulation have been central to the idea of content management. Today, however, as the CMS points to more distributed architectures and more orchestration, technical teams are chafing at the micromanagement of digital experiences, to the dismay of content teams.
So, as CMSs begin to venture beyond the web, where pages are no longer the central atom of our content items writ large, and as pages themselves become increasingly componentized into self-rendering front-end components, this keystone of the CMS’s long-standing principles is increasingly coming under fire. In a world where URLs are no longer the bastion of the CMS but rather the fodder of front-end frameworks, and as routing becomes predominantly a focus of presentation layers thanks to the shifting separation of concerns, where are URLs headed in content architectures?
At first, CMSs managed pages and URLs one-to-one, where each content item had a canonical or authoritative URL at which its full version was always available. But as needs shifted and websites became ever more complex, rich and multifaceted landing pages with vanity URLs needed to be arbitrarily constructed out of disparate content items. Moreover, CMSs like Drupal and WordPress found that their primary methods of assigning URLs weren’t well-suited for search engine optimization (SEO), leading to the advent of friendly URLs and path aliases. Today, many CMSs have both canonical (made into friendly) URLs for individual items and vanity URLs for complex landing pages, all of which leads to quite a bit of head-scratching for developers, content editors, and SEO-minded marketers alike.
In this article, however, I make an argument for why the notion of “proudly routed elsewhere,” like the idea of proudly rendered elsewhere, is something organizations can no longer ignore. If you’ve completed the first stages of your digital transformation with web and mobile manifestations and are moving into decoupled and distributed architectures that prepare for life beyond the web, it’s time to bid a final farewell to upstream URL management as a fixture of the CMS. It’s time to let front-end frameworks take the baton, because they finally have routing under their belt in a self-assured way, especially as routing begins to leap beyond the page—for good.
The evolution of routing in JavaScript frameworks
Routing has changed in an almost unrecognizable way over the years. The fundamental link, the root of much of the power of the web, was mediated through references to URLs governed largely by server-side monolithic systems, which provided fully built HTML pages in response to a request for a particular route (e.g.
/articles/lorem-ipsum
). With the advent of client-side rendering, all of this began to change as hash-based routes (e.g. /#/articles/lorem-ipsum
) first appeared in JavaScript applications to allow for dynamic page changes like success messages or client-side authentication.Some CMSs forged a middle ground between client-side routing in JavaScript and server-side routing in server technologies like PHP. This was at the core of the concept of progressive decoupling, a term I co-originated, which encouraged developers to interpolate JavaScript components within CMS pages such that those pages could still be easily managed by content teams. But progressive decoupling always had an expiration date: that moment when server-side routing in JavaScript through Node.js and Express became not only a possibility but a prevalent pattern. Suddenly, it made far less sense to have two competing approaches to perform routing for a single web application, though, as I share later, there are clear and valid exceptions.
In contemporary JavaScript applications leveraging universal architectures, it’s rare to see even hash-based routing, as the History API in browsers and the wide availability of server-side routing in JavaScript architectures has led to a considerable shift in developer experience. Today, it’s largely anathema to JavaScript developers to concede the responsibility of routing to servers out of their control, and for good reason: many frameworks and libraries expect to be able to handle routes without delegating it to another system. Libraries like Reach Router (an accessibility-focused router now part of React Router) are now considered the authoritative way to govern both server-side and client-side routing in React and other ecosystems.
Perhaps the final nail in the coffin when it comes to JavaScript’s now-enduring primacy over server-side and client-side routing in web applications is the newfound prevalence of page transitions and animations. What was initially a mostly developer-only endeavor has now found favor in concerns regarding the user experience as well. In short, it was only a matter of time before proudly rendered elsewhere in decoupled CMS architectures became proudly routed elsewhere too.
Developers prefer slugs to friendly or vanity URLs
As we can see, the shift of the separation of concerns in content architectures has led to a world where consumer applications like those written in JavaScript now perform their own rendering, both on the server side and the client side—an architectural paradigm that for outsiders is somewhat nebulously termed universal JavaScript. This means that the responsibility for presenting data is no longer on the side of the CMS, and the CMS’s primary purpose is to deliver data to JavaScript and Jamstack consumers.
URLs are challenging because they lie at the nexus of both data and presentation. They’re used not only to access data on the CMS through APIs but also to serve pages and routes on presentation layers written in universal JavaScript. Today, now that JavaScript frameworks provide global routers that govern the entire application’s URL scheme and how URLs are defined, CMSs are finding themselves increasingly sidelined in the debate of who exactly gets to serve URLs.
To complicate matters further, some CMSs provide friendly URLs (e.g.
/articles/lorem-ipsum
in lieu of Drupal’s /node/22334
) that allow content editors and content managers to override the default “canonical” URL provided by a monolithic CMS. But these friendly URLs, like vanity URLs, might contain multiple slashes in ways that infringe on a JavaScript’s own hierarchical URL scheme using its own slashes in ways that govern not only server-side routing but also routing on the client side. Friendly and vanity URLs are therefore increasingly remnants of a quickly receding past paradigm—a page-to-page era where every route change required a round trip to the server.Thanks to server-side rendering in universal JavaScript implementations and the advent of techniques like link prefetching, a key tenet of Gatsby, developers today strongly prefer slugs (e.g.
lorem-ipsum
) that allow them to place these slugs wherever they need to within a pre-existing JavaScript-driven hierarchical URL scheme. Instead of relying on an aloof server-side CMS to provide a URL that is manually managed and prescriptive to a fault, developers can leverage routing schemes governed entirely by the application and employ those slugs wherever they see fit. This is why Contentful content types come prepackaged with a “slug” field—it just makes sense. An article entitled “Lorem ipsum” is expected to carry a slug lorem-ipsum
, which can then become /articles/lorem-ipsum
or /2021/05/18/lorem-ipsum
in an arbitrary consumer, most crucially according to that consumer’s preference.But where does this leave the content editors and SEO specialists who still desire fine-grained control over how their URLs look and feel, how friendly they are, and how easily they can manage them? The swing of the pendulum back toward developers in the latest wave of the CMS suggests that decisions about URLs need to be made much earlier in the process instead of willy-nilly after an implementation is already complete, something that can be frustrating for content teams used to much greater flexibility.
The risks of proudly routing elsewhere
Though it’s convenient to issue a sweeping conclusion about all web applications and their putative need to perform routing in JavaScript, organizations have a lot of decisions to weigh when it comes to where URLs fit in their content architectures. Letting the framework take care of routing is all well and good due to shared routers across server and client and built-in benefits like link prefetching in many technologies, but many are not yet ready to make this leap—whether because of limitations of the architecture itself or the requirements of the content teams on the other side of the back office.
Whether it’s because content editors are still accustomed to the traditional approach to URL management, which requires full control over routing within a monolithic CMS, or due to a hybrid content architecture that’s in flux between monolithic and headless implementations, it’s important to give routing—just like the earlier question of rendering—its own due diligence. For instance, for Drupal users that need to split their routing such that some requests point to the CMS while others point to an Express server, the Decoupled Router provides a compelling option.
Several years ago, I met with a client in Japan that had various swaths of its content architecture split across a monolithic CMS architecture as well as several JavaScript frameworks running in parallel, all operating on the same domain. Though “proudly routed elsewhere” is certainly an aspirational goal for many developers, for many cross-functional teams, the reality remains far more complex. In many situations, as it should be, depending on content teams’ needs and developers’ needs, the desired route (pun intended) can go either way and take multiple paths to the correct destination.