Routing

Routes are rules that map URL patterns to your templates, content, other URLs, or other parts of the application.

Learn by watching!
Check out the fundamentals screencast on Routing.

All of Statamic’s routes are defined in site/settings/routes.yaml (also accessible in the Control Panel Settings ยป Routes area). We support five different types of routes.

Template Routes

Template routes allow you to create individual URLs or patterns that map to specific templates. This is very different than using a Page to create a URL because there is no inherent content manageable in the Control Panel or content files. Instead, you can code anything you need to into the template itself, use Tags and Globals to display content, or pass data in through the route itself.

This is a useful technique for creating pages that aren’t editable in the Control Panel, or where an empty page might be more confusing than helpful. RSS feeds, site maps, search results, and other utility pages are a few such examples.

To create a template route set the desired URL or pattern as a key under routes, and then the template and any additional variables or settings you wish to pass through in a key-value array.

/search:
  template: search-results
  title: Look What I Found!
  layout: my-layout
  show_sidebar: false

When visiting example.com/search, the search-results.html template will be rendered and {{ title }} will display Look What I Found!, and whatever you decided {{ if show_sidebar }} should do, won’t be happening. You just shut that party down.

If all you need to set is a template, you can simplify the syntax and just pass the template string instead of the array.

/search: search-results

Wildcard Segments

Wildcards let you capture multiple routes at once. It’s like killing infinity birds with one stone. Wildcards are available anywhere in your route pattern and there aren’t any limits to how many you can use.

routes:
  /knock-knock-jokes/*/punch-line: joke

Any URL with knock-knock-jokes as the first segment, anything as the second segment, and punch-line as the third, will match this route and be rendered with the joke template.

You can pass the value of the wildcard segment into the template and create a variable on the fly. Instead of * you can set a parameter name like this:

routes:
  /knock-knock-jokes/{setup}/punch-line: joke

Given a URL of example.com/knock-knock-jokes/little-old-lady/punch-line, your template can use {{ setup }} to access the value little-old-lady. This is more consistent, reliable, and readable than relying on segment variables and allows you to change the routes and rearrange your site structure without ever breaking a link.

These wildcard variables can contain upper and lowercase letters, numbers, and underscores.

Ignoring Segments

You can also add a list of segments that should be completely and utterly ignored if found in your URL, like that poor nerdy kid at prom. This comes in handy if you have a form and want to redirect a user to /success but still use the same template, and other similar things we can’t think of.

ignore:
  - success
  - such

Keep in mind these ignore segments are global. example.com/such/bummer will be seen and routed as example.com/bummer, and example.com/weird-band-names/such as example.com/weird-band-names. These ignore values will still appear in your {{ segment_n }} variables.

Here’s an example on how you might use this in the context of a form submission page.

{{ if segment_3 == "success" }}
    <h1>You have done it!</h1>
{{ else }}
    {{ partial:contact-form }}
{{ /if }}

Loading Content

You may automatically load content into routes by providing a load variable pointing to either a URL or an ID of a content item.

routes:
  biography:
    template: about
    load: /about

This will make all the variables from the /about page available as top level variables on the /biography route, just as though you were on the page itself. This allows you to do away with any extra get_content tags.

Controller Routes

If you’re in need of more control of your output, you may use a controller. Specifically, one located in your site helpers area.

routes:
  /complicated/stuff: ComplicatedController@stuff

This will output whatever the stuff method in your Statamic\SiteHelpers\ComplicatedController class returns.

Make sure to return something that Laravel can convert into a response.
For example: a string, an array (which will be converted to JSON), or a Response object.

Collection and Taxonomy Routes

By their very nature, Collections and Taxonomies don’t determine their own URLs. To do so would limit their flexibility. This is where you get to decide just how their URLs are structured and where they go.

The syntax is very similar to the wildcards above, but instead of passing variables into templates, here you’re passing variables into the URL. It’s the same, except different.

Here are some things to note:

  • Entries and terms can use any variables from their data / front-matter.
  • Date-based entries also have access to year, month, and day.
  • Values will be slugified. Handy if the values are multi-word or contain international characters.
  • If an array is encountered, the first item will be used. (More info below)

For example:

collections:
  blog: /blog/{year}/{month}/{slug}
  locations: /stores/{state}/{city}
taxonomies:
  tags: /blog/tags/{slug}

Any time you’re looping through the collection to render its data, each entry’s {{ url }} will match to this format. For the locations collection, you could see URLs like the following:

  • http://example.com/stores/new-york/saratoga-springs
  • http://example.com/stores/florida/miami

And in the blog you might see this:

  • /blog/2015/12/christmas-already-what-the-heck
  • /blog/2016/01/where-did-the-year-go

Terms get their own URLs too. Some tag URLs might look like this:

  • /blog/tags/news
  • /blog/tags/events

Arrays in Routes

When a route contains an array value, Statamic will use the first item.

We’ll use a typical clothing store example. Say they have a product collection, where one product could be in multiple categories, like this:

title: Awesome Shirt
categories:
  - shirts
  - menswear

Given a route of /products/{categories}/{slug}, the URL would be /products/shirts/awesome-shirt.
Since categories is an array, Statamic used the first item, which was shirts.

Redirects

Statamic supports 2 methods of redirecting routes. “Vanity” (ie. not permanent) redirects, and regular (ie. permanent) redirects. They both have their pros and cons.

Vanity URLs

A Vanity URL is a dummy, easy to remember URL that redirects you to a permanent URL. A perfect use case would be to create a example.com/promo URL that redirects you to example.com/blog/2016/09-this-months-promo. You can change this redirect to any URL, any time, and never have to update your marketing material, ad buy, and so on.

vanity:
  /party: /my-long/page-name

This will forward http://yoursite.com/party to http://yoursite.com/my-long/page-name. Simple.

Best Practices
Vanity routes are temporary/utility 302s and should not be used as permanent redirects. It’s a Google thing.

Regular / Permanent / 301 Redirects

No matter what you call them, these are meant to be permanent redirects.

redirect:
  /party: /my-long/page-name

Best Practices
Browsers cache 301 redirects agressively, so use these accordingly. Ideally 301 redirects should be handled via rules in an .htaccess file or nginx conf rule. Server level redirects are faster because the requests don’t have to run Statamic to find where to send the request to.

Content Types

You can modify the Content-Type request headers (not to be confused with Statamic “Content Types”) from text/html to anything else you might need. Add content_type to your front-matter or route definition with the appropriate MIME type, like so:

  content_type: application/json

We’ve also added a few shorthands you can use without needing to look anything up.

  • json becomes: application/json
  • xml becomes: text/xml
  • atom becomes: application/atom+xml and also ensures the charset is utf8
Last modified on August 21, 2019