Edit on GitHub
Jump to docs navigation

Templating / Templates and routing

Note: You are currently reading the documentation for Bolt 2.2. Looking for the documentation for Bolt 5.2 instead?

Whenever your browser gets a page on a Bolt website, it uses an URL like /entries or /page/lorem-ipsum. Bolt knows how to handle URLs like these, and displays the information the browser requested. Bolt does this by mapping the URL to a so-called Route. This Route is the controller that (when called) fetches the content from the database, selects the template to use, renders the HTML page according to that template and the content and serves it to the browser.

At the same time, if you create a new record, Bolt will know what the URL for that content is. So when that URL is requested by a browser, it can map it back to the correct content.

For example, if you have a 'Pages' ContentType, with 'Page' as a singular_name, your site will automatically have pages like:

  • http://example.org/pages
  • http://example.org/page/lorem-ipsum-dolor

Automatic template selection

Bolt has some rules to help you quickly build custom templates for your site. If your template is named exactly like the singular_slug or slug for the ContentType or record it will be automatically used.

How does Bolt select what template to use for a given request? Unless specified, Bolt will determine the names of these templates automatically via a method we call 'cascading templates'. This allows for great flexibility, as well as ease of use. Unless you specify anything, pages will get rendered using the basic default templates, but you can refine this in the definition of the ContentTypes or even on a per-record basis. The rules for selecting a template are as follows.

Selection of a template for an single record page:

  • If an overview page like /page/foo-bar is requested, and the ContentType has a 'templateselect field' and a template is selected for this record, that template will be used.
  • Otherwise, if the ContentType definition has a value for record_template, that template will be used.
  • Otherwise, Bolt will check if a template with a suited name exists. For example, if the ContentType's singular_name is 'Entry', Bolt will check for an entry.twig template. If it exists, that template will be used.
  • Otherwise, if record_template is set in config.yml, that template will be used.
  • If no other rule matches, Bolt will use a template named record.twig.

Selection of a template for an overview page:

  • If an overview page like /entries is requested, and the ContentType definition has a value for listing_template, that template will be used.
  • Otherwise, Bolt will check if a template with a suited name exists. For example, if the ContentType's name is 'Entries', Bolt will check for an entries.twig template. If it exists, that template will be used.
  • Otherwise, if listing_template is set in config.yml, that template will be used.
  • If no other rule matches, Bolt will use a template named listing.twig.

In the default template for a single record, it is available as both {{ record }} and also by the name of the singular name. So, in the above example, you can also use {{ page }}, without having to set it specifically. Likewise, in the default template for multiple records, the content is available as {{ records }} and also by the name of the ContentType, for example {{ pages }}.

Note: As you might have noticed, sometimes the examples use {{ page }}, sometimes {{ entry }} and sometimes something different altogether. These are just the names of the objects containing the content, or the array with several records of content. By default you can use the singular name of your ContentType, so be sure to replace them with whatever the names of your content types or variables are.

Routing

The URLs mentioned in the previous paragraphs are actually just defaults. Each can be adjusted to your own liking. There are some caveats with regards to correct canonical URLs, but otherwise you can change it to anything you like.

Below you will find a complete description of the route definition in the YAML file.

The easiest way to add your own is to follow the examples defined in the distributed routing.yml.dist file. The order of the routes is important because it is a first-come first-serve architecture. So if you add your own ContentType routes it will probably need to be defined before the general contentlink route.

Some routing examples

Make old .html pages work

In this example we add routes to make old /contact.html links work with your new Bolt system.

oldpages:
  path:           /{slug}.html
  defaults:       { _controller: 'Bolt\Controllers\Frontend::record', 'contenttypeslug': 'page' }
  requirements:
    slug:       '[a-z0-9-_]+'

Host requirement

In this example we use the host requirement to show a specific page on the home of a particular host. The defaults are set to the regular record-action with a specific ContentType and slug set up.

example:
  path:     /
  defaults: { _controller: 'Bolt\Controllers\Frontend::record', 'contenttypeslug': 'page', 'slug': 'example' }
  host:     'example.mydomain.org'

ContentType overrides

This case overrides the default routing for ContentType page. Bolt will no longer create /page/{slug} links but will now create /{slug} routes. The old routes will still work, but the canonicals will be fixed to the new routes. The defaults are set to the regular record-action but we also added an additional contenttype: page line to tell Bolt to use this route for all records with ContentType page.

pagebinding:
  path:           /{slug}
  defaults:       { _controller: 'Bolt\Controllers\Frontend::record', 'contenttypeslug': 'page' }
  contenttype:    pages

An alternative is to also add the creation date:

pagebinding:
  path:           /{datecreated}/{slug}
  defaults:       { _controller: 'Bolt\Controllers\Frontend::record', 'contenttypeslug': 'page' }
  requirements:
    datecreated:    '\d{4}-\d{2}-\d{2}'
  contenttype:    pages

Single record override

This example overrides a single record to a specific URL. Useful if you only want to exempt a few pages and not a complete ContentType. Don't forget to add the recordslug: page/about line. This route should be high in the route list for it to work correctly.

aboutbinding:
  path:           /about
  defaults:       { _controller: 'Bolt\Controllers\Frontend::record', 'contenttypeslug': 'page', 'slug': 'about' }
  recordslug:     page/about

Filesystem based page generation

There is a way to configure the router to generate statically stored content. For the Bolt\Controllers\Frontend::template default controller can be assigned a parameter template that may points out a template that should be stored as a regular file under currently selected theme in the filesystem. Using file extension .twig is optional.

templatebinding:
    path: /mytemplate
    defaults: { _controller: 'Bolt\Controllers\Frontend::template', template: 'mytemplate' }

YAML description of a routing entry

The complete format of a single route in YAML is as follows:

bindname:
  path:       /{parameter..}/
  defaults:
    _controller:    'controller'
    _before:        'before'            # optional
    _after:         'after'             # optional
  requirements:
    parameter..:    required-regexp
  host:               hostname            # optional
  contenttype:        contenttype         # optional

Explanation of each argument:

Argument Description
bindname name to bind the route to, used for generating URLs.
path URL of this route, use {..} for parameters.
_controller controller method which will be called when this route matches.
_before called before the controller action will be called. if not set the method before() will be called in the controller.
_after called after the controller action is called. if not set the method after() will be called in the controller.
parameter.. name of the named parameter see path.
required-regexp regular expression which should be true for this route to be matched. it's also possible to add a callback here. it should return a regular expression which should match
hostname hostname to match for this route.
contenttypeslug if this route represent a new route for a ContentType, the ContentType should be specified.
Path

You are free to specify your own parameters, however when you are adding routes for ContentTypes or recordslugs you are limited to which parameters you can add. At least when you don't want to code your own Content-object. The following fields from a ContentType can be used as a parameter:

  • contenttypeslug
  • id
  • slug
  • datecreated - only the date part is returned (so yyyy-mm-dd)
  • datepublish - only the date part is returned (so yyyy-mm-dd)
Required regular expressions

When the routing is processed no content has been loaded yet, so validation cannot be based on actual database checks. Therefore the check is purely a syntax check using regular expressions. Bolt adds the ability to specify a callback which returns a regular expression. This allows us to dynamically enter ContentType slugs as valid URL parts.

You can either enter your own regular expression or use the callback notation which is class::method.



Edit this page on GitHub
Couldn't find what you were looking for? We are happy to help you in the forum, on Slack or on Github.