Beautifying Templated Websites with Leaf and Bootstrap

Use the Bootstrap framework to add styling to your templated Leaf pages, and see how to serve files with Vapor in this server-side Swift tutorial! By Tim Condon.

Leave a rating/review
Download materials
Save for later
Share
Update Note: Tim Condon updated this tutorial for Vapor 4. Tim Condon also wrote the original tutorial.

In the companion tutorial, Templating With Leaf, you started building a powerful, dynamic website with Leaf. The web pages, however, only use simple HTML and aren’t styled — they don’t look great!

In this tutorial, you’ll learn how to use the Bootstrap framework to add styling to your pages. You’ll also learn how to embed templates so you only have to make changes in one place. Finally, you’ll also see how to serve files with Vapor.

Note: This tutorial assumes you have some experience with using Vapor to build web apps. See Getting Started with Server-side Swift with Vapor 4 if you’re new to Vapor. You’ll need to at least use the steps in that tutorial to install the Vapor Toolbox in order to follow along with this tutorial. It will also benefit you greatly if you first work through the companion tutorial Templating With Leaf.

Getting Started

First, download the starter project for this tutorial using the Download Materials button at the top or bottom of the page. You can open the starter project in Xcode by running the following command from the root directory of the project:

open Package.swift

Base Templates

Currently, if you change the index page template to add styling, you’ll affect only that page. You’d have to duplicate the styling in the acronym detail page, and any other future pages.

Leaf allows you to embed templates into other templates. This enables you to create a “base” template that contains the code common to all pages and use that across your site.

In Resources/Views create a new file, base.leaf. Copy the contents of index.leaf into base.leaf. Remove everything between the <body> and </body> tags. This remaining code looks similar to the following:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>#(title) | Acronyms</title>
</head>
<body>

</body>
</html>

This forms your base template and will be the same for all pages. Between the <body> and </body> tags add:

#import("content")

This uses Leaf’s #import() tag to retrieve the content variable. To create this variable, open index.leaf replace its contents with the following:

#extend("base"):

#endextend

This tells Leaf to extend the base template when rendering index.leaf. base.leaf requires one variable, content. Add the following, in between #extend and #endextend to define content:

#export("content"):
  <h1>Acronyms</h1>

  #if(acronyms):
    <table>
      <thead>
        <tr>
          <th>Short</th>
          <th>Long</th>
        </tr>
      </thead>
      <tbody>
        #for(acronym in acronyms):
          <tr>
            <td>
              <a href="/acronyms/#(acronym.id)">
                #(acronym.short)
              </a>
            </td>
            <td>#(acronym.long)</td>
          </tr>
        #endfor
      </tbody>
    </table>
  #else:
    <h2>There aren’t any acronyms yet!</h2>
  #endif
#endexport

This takes the HTML specific to index.leaf and wraps it in an #export tag. When Leaf renders base.leaf as required by index.leaf, it takes content and inserts it into the base template. Save the files.

Running for the First Time

Before you run the app, you need to have PostgreSQL running on your system. You’ll run the Postgres server in a Docker container. Open Terminal and enter the following command:

docker run --name postgres \
  -e POSTGRES_DB=vapor_database \
  -e POSTGRES_USER=vapor_username \
  -e POSTGRES_PASSWORD=vapor_password \
  -p 5432:5432 -d postgres    

To check that your database is running, enter the following in Terminal to list all active containers:

docker ps

Next, you must a custom working directory in Xcode so Vapor knows where to find the Leaf files.

Option-Click the Run button in Xcode to open the scheme editor.

On the Options tab, click to enable Use custom working directory and select the directory where the Package.swift file lives:

Set the custom working directory in Xcode

To add acronyms into your database, use the instruction steps for the RESTed macOS app in the companion tutorial.

Build and run the app. Open your browser and enter the URL http://localhost:8080/. The page renders as before:

Homepage with Embedded template

Updating Acronym Page

Next, open acronym.leaf and change it to use the base template by replacing its contents with the following:

#extend("base"):
  #export("content"):
    <h1>#(acronym.short)</h1>
    <h2>#(acronym.long)</h2>

    <p>Created by #(user.name)</p>
  #endexport
#endextend

Again, the changes made were:

  • Remove all the HTML that now lives in the base template.
  • Extend the base template to bring in the common code and render content.
  • Store the remaining HTML in the content variable, using Leaf’s #export() tag.

Save the file and, in your browser, navigate to an acronym page. The page renders as before with the new base template:

Acronyms page with the new base template

Note: In debug mode, you can refresh pages to pick up Leaf changes. In release mode, Leaf caches the pages for performance so you must restart your application to see changes.

Set up Bootstrap

Bootstrap is an open-source, front-end framework for websites, originally built by Twitter. It provides easy-to-use components that you add to webpages. It’s a mobile-first library and makes it simple to build a site that works on screens of all sizes.

To use Bootstrap go to getbootstrap.com and click Get Started. Bootstrap provides a CSS file to provide the styling and Javascript files that provide functionality for Bootstrap components. You need to include these files in all pages. Since you’ve created a base.leaf template, this is easy to do!

On the Get Started page, find the Starter template section.

In the starter template’s <head> section, copy the two <meta> tags — labeled “Required meta tags” — and the <link> tag for the CSS — labeled “Bootstrap CSS.” Replace the current <meta> tag in base.leaf with the new tags.

At the bottom of the starter template, copy the <script> tag from Option 1. Put it in the base.leaf template, below #import("content") and before the </body> tag.

Save the file then, in your browser, visit http://localhost:8080. You’ll notice the page looks a bit different. The page is now using Bootstrap’s styling, but you need to add Bootstrap-specific components to make your page really shine.

Open base.leaf and replace #import("content") with the following:

<div class="container mt-3">
  #import("content")
</div>

This wraps the page’s content in a container, which is a basic layout element in Bootstrap. The <div> also applies a margin at the top of the container. If you save the file and refresh your webpage, you’ll see the page now has some space around the sides and top, and no longer looks cramped:

Updated layout with basic Bootstrap container