What is a Route?

Concrete CMS builds websites, and websites are a collection of URLs. For example:


All of these URLs on contain “routes,” which are the segments of the URL past the actual domain name:

  • /about/company
  • /login
  • /dashboard
  • /api/customers

If you’ve used Concrete for any amount of time as a site editor or a developer, you’re undoubtedly familiar with the first three of these. These URL routes are created by pages at those particular locations. The “About > Company” page may have been created by an editor within the CMS, by adding a “Company” page of a certain page type beneath the About section. The /login and /dashboard URLs are actually single pages. In nearly all cases, a Concrete page results at a route, which, when visited, renders that page.

A page is a very convenient object: it has a site theme attached to it, can contain blocks, lives at a URL, can have permissions attached to it, shows up in the sitemap and is indexed by the search block, and much more. It can also easily be added by developers (in the case of single pages) or by site editors (in the case of adding a page of a reusable page type, like a Blog Entry or Content page.) Pages are ideal for most content management problems, but occasionally their benefits actually become drawbacks. For example, let’s say you’re creating a website with a custom API that you want to expose to some kind of custom JavaScript solution. Here, you’d like to get the username and user ID of the currently logged in user, whenever you send a simple browser request to /api/current_user. You’d like it to respond with a simple JSON string:

    username: ‘aembler’,
    user_id: 1

Or this, if the user is logged out, an empty JSON object.

You could do this with a single page and controller; you’d create a controller and single page, with a single page that has no output, and a controller method that returned JSON. Unfortunately if you did this, you’d get an entry for this item in the sitemap, and it might turn up in search results. This could confuse administrators and break things. And this is just for one item! What if your API has 100 endpoints? You don’t want to use pages.


In this case, the Concrete routing system is the answer. The routing system lets you add arbitrary endpoints to your Concrete installation, and return responses from them. These endpoints are accessible via a browser or a REST client, but they don’t add to your search index, show up in the sitemap, or slow a site tree down. Concrete itself uses the routing system extensively for user interface components like editing dialogs, system actions and more. Read on to learn how to define your own routes in a package, or at the application level.