How to add a carousel to your Bolt CMS homepage
Tags: slickjs, carousel, boltcms, tutorial
Published: 2017-01-20 22:17:52

---
title: How to add a carousel to your Bolt CMS homepage
published: true
description: Tutorial showing step-by-step how to create and include a carousel in Bolt CMS
cover_image: http://www.splitshire.photos/bucket/SplitShire-67842.jpg
tags: slickjs, carousel, boltcms, tutorial
---

In this tutorial, we will add a carousel to the homepage of our [Bolt CMS](https://bolt.cm/) using the jQuery based [Slick](http://kenwheeler.github.io/slick/) library. We will first define what our goal is, set up the base system, create a basic HTML version of the carousel and finally incorporate it into our Bolt CMS page.

## User Stories

A carousel is a collection of images that are presented on a website. There are two roles in this scenario: a website visitor and a website editor.

1. As a visitor, I want to see some images about the service of the website I am visiting.
2. As a visitor, I only want to see one image at a time.
3. As a visitor, I want to be able to manually browse the images with back (`<<`) and forth (`>>`) buttons.
4. As a visitor, I want the loading time of the website to be as little as possible.
5. As an editor, I want to create a carousel in the backend.
6. As an editor, I want to add/remove images to/from a carousel.
7. As an editor, I want to change the order of the images in the carousel.

(Note: The user stories may seem a bit fine-grained, but they will help you to stay on track and can check many todos and stay motivated)

## Setup

(Note: If you are familiar with setting up a development environment and Bolt CMS itself, you can skip this and the next section. Just take care of the naming conventions I introduce here.)

You need a local development environment using a command-line and running *PHP 5.6/7*, *Composer*.

I am using a Mac for my development, and I use the very handy development tool [Laravel Valet](https://laravel.com/docs/5.3/valet). Please use whatever you and your machine works best with, be it *MAMP*, *DesktopServer* or even *Docker*. If you are not on a Mac and have no preferences, I highly recommend [Laravel Homestead](https://laravel.com/docs/5.3/homestead) to you.

You are ready to go if `php -v` in terminal spits out `PHP 7.1.0` or any other version number above 5.6, `composer` shows you a list of commands.


## Installing Bolt

(Note: I always add line numbers for my edits. Those derive from vanilla settings, so if you added extra lines in your files, the numbers would not be correct. But even in these situations, they will guide you to the approximate location.)

We will use *Composer* to install the CMS itself. `composer create-project bolt/composer-install:^3.2 carousel --prefer-dist` 

`carousel` is the name of the app – you can name it however you want, just note this name, you might need it later. Be patient, the installer downloads quite a few libraries (~ 100 MB). The installer will ask you a few questions about locations that I will just confirm with `Enter`. Of course, you can change the details to your liking here.

Bolt is ready for setup now. You just need to tell your local web server to serve the `public` folder.  The easiest way is to fire up PHP's internal dev server with `php -S localhost:8888` while within the `public` folder. I prefer using *Valet* which uses *Nginx* under the hood. The command is `valet link conference` while within the `public` folder. You can now open `carousel.dev` in your browser and add an admin user.

There is a note below the form which informs you that you're using *SQLite*. SQLite is a „database in a file“, which makes it a lot more mobile than a MySQL database. It is production-ready for sites where you have few editors (= people editing the database) and as many visitors (= requesting data from the database and cache) as you like. Our conference app may become a case where many users access and alter the database via their entries, so probably for a production site, I would go for a full-blown MySQL database. For development SQLite is fine, and you can [migrate from SQLite to MySQL or MariaDB rather simply](https://www.symfony.fi/entry/migrating-bolt-cms-from-sqlite-to-mysql-mariadb) later if you want.


## Setting up Bolt

Did you create your admin user already? I gave mine the username `carousel-24st3` (the name is not so easy to get, which is good to prevent brute-force login attempts). Click save, and you'll be redirected to `carousel.dev/bolt` and see the backend. 

## Creating the content type

Let's start by managing the data structure first:

There may be more than one carousel on your website. It hence makes sense to create a new *ContentType* for it. A carousel consists of two fields: a title (mainly for reference) and an *Imagelist*. An *Imagelist* is a collection of images.

So, open your config file from `carousel/app/config/contenttypes.yml` and add a new *ContentType*:


```
# pages-contenttype just for orientation
pages:
    …
    recordsperpage: 100

# carousel contenttype
carousels:
    name: Carousels
    singular_name: Carousel
    fields:
        title:
            type: text
          slug:
            type: slug
            uses: title
        gallery:
            type: imagelist
    record_template: carousel.twig
```

What do the settings under `fields` mean?

1. Every `field` has a name, such as `title` and `gallery`. 
2. We will access the content via these names in our template later. 
3. The type of a field is one from [this list](https://docs.bolt.cm/3.2/fields), with `type: text`, `type: textarea` and `type: html` being the most used ones.  The last one is the equivalent of the content area that you know from Wordpress, where you can add and format freeform text.

We need a *slug* to get an URL for a single carousel. And *gallery* is just the name for the list of images. Lastly, `record_template: carousel.twig` will enable us to create a template part for all carousels that we can then include in any part of the website.

We head over to [our backend](http://carousel.dev/bolt) and update the database. In the left panel, we now have a new section called "Carousels".

Note: When you visit your site at [carousel.dev](http://carousel.dev), you will be greeted by an error message. We did not create a page, so Bolt does not have anything to show here.

## Creating our first carousel
Create a new carousel from the menu in the backend's left panel. Let's give it the title  `My Carousel` and add a couple of images via `Select from server`. We can see a few example images there and luckily they all have the same size. Adding four images via `Adding selected` is enough to showcase the carousel. Set *Status* to `Published`.

Once we added images, we can change their order simply by click, hold and move them around. We can delete them from the carousel by clicking the `x` on the right.

## Preparing the template
We defined `carousel.twig` as the template file for carousels. It does not exist yet, so we will just copy `index.twig` from the folder `public/theme/base-2016/` . We need to change a few things here:

1. Remove `{{ record.teaser }}`, `{{ record.body }}` as we do not have these fields
2. Loop over the images we have with 
```
{% for images in record.gallery %}
    {{ image|showimage() }}
{% endfor %}
```

Save and we can now view the preview. The preview URL that we can directly visit is [carousel.dev/preview/carousel](http://carousel.dev/carousel/my-carousel). We see four images, each on a single line.

Ok, what do we need to get a moving carousel?

1. The carousel Javascript and CSS assets
2. A Javascript script that initiates the carousel

### Loading the JS and CSS assets

We could hardwire the assets in the base template ( `public/theme/base-2016/partials/_master.twig`, but let's think twice.

We only need the carousel assets in pages that contain carousels. Adding the sources to `_master.twig` would load them on every page. We do not want this. What can we do instead?

Let's open `_master.twig`. In line 19 and 20 there is a tag `{% block headincludes %}{% endblock headincludes`. This is a [Twig block](#). It enables us to extend the master template with every template that uses it with `% extends ‚partials/_master.twig‘ %}` – just as our `carousel.twig`. This way we can include custom headers just for this page.

Here is how it should like for `carousel.twig`:

```
{% block headincludes %}
    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" />
    <!-- Add the slick-theme.css if you want default styling -->
    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick-theme.css" />
    <style>
.slick-prev:before, .slick-next:before { 
    color:red !important;
}
</style>
{% endblock headincludes %}
```

Note: We have to define blocks one after another, so make sure you add the `headinclude` outside of the `main` block. The order of blocks is not crucial, following a logical order makes it easier to read the code, though.

This will load Slicks CSS files from a remote CDN server, so we do not have to install extra software.

What about the Javascript assets? It is considered best practice to include them at the end of your page, just before the closing `</html>`.  And Bolt's `base-2016` template has a block for this as well `bottomincludes`. This is how it is supposed to look like for loading the assets for us (again in `carousel.twig`:

```
<script type=" text/javascript " src="//code.jquery.com/jquery-1.11.0.min.js "></script>
    <script type="text/javascript " src="//code.jquery.com/jquery-migrate-1.2.1.min.js "></script>
    <script type="text/javascript " src="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js "></script>
```

Save `carousel.twig` and reload the preview in Chrome. And? Nothing. Click right in the window and view the source. Here you can see that indeed the CSS and JS were loaded. But what is missing?

### The Javascript script that initiates the carousel

Of course, we need to initiate *slick* and tell it which elements to include in the carousel. We have to wrap the loop in a div and give it a unique ID so we can access it:

```
    <div id="my-carousel">
        {% for image in record.gallery %}
            {{ image|showimage() }}
        {% endfor %}
    </div>
```

As documented on [slick's website](#), we can now initiate (or define) the carousel such as this within the `bottomincludes` block:

```
    <script type="text/javascript ">
        $(document).ready(function(){
          $('#my-carousel').slick({
            slidesToShow: 1,            
            lazyLoad: 'ondemand',
            autoplay: true,
            accessibility: true
          });
        });
    </script>
```

We address the div with `#my-carousel` and defined a few settings. We get lazy loading out of the box which basically means that not all images will be loaded at page load but rather when they are being viewed. This speeds up the initial load, especially on mobile connections.

Save and load the [carousel again](http://carousel.dev/carousel/my-carousel). Yeah, that looks like a carousel now. But wait: Where are the buttons to switch between the images? 

Fiddling through the page source will reveal that there are buttons for back and forth – but they are white. There is an easy fix: Just add this to your `headincludes` block:

```
    <style>
        .slick-prev:before, .slick-next:before { 
            color:red !important;
        }
    </style>
```

Save, refresh and see the buttons.

We now have a fully functional carousel. We can [visit and enjoy it](http://carousel.dev/carousel/my-carousel)

## Including the carousel in the header area
Right now we have to visit a special URL to view the carousel. Sometimes, however, we want to include the carousel on every page. For example: In Bolt's `base-2016` theme we might want to put the carousel where we see a city panorama now.

What should we do?

1. Move the assets to the global `_master.twig` file (we need them on any page now) (put the CSS in the header and the JS before the `</html>` as described above
2. In `base-2016/partials/_header.twig`  define the content of the carousel and load a new partial, because the generic `record` variable gets always filled with the current page's values. We need the values from one page, however, so we use `setcontent` to get our carousel's content. 

```
{% setcontent mix = '/carousel/my-carousel' %}
{{ include('partials/_carousel.twig') }}
```

3. Create new partial `_carousel.twig` in `base-2016/partials` and just paste the loop in it:

```
<div class="large-12 columns headerphoto" id="my-carousel">
    {% for image in mix.gallery %}
        {{ image|showimage() }}
    {% endfor %}
 </div>
```

Save everything and create some pages in the backend (I created an `about` and `contact` page and filled them with some dummy content.

When we load [about](#) and [contact](#) now, we see the carousel. We did not fine tune the dimensions and the headings and body text may be covered by the carousel, but you can check the page source to see that they are actually there.

Great job!