How to Create a Master Page Template

Summary:

With Marketpath CMS you can create a master page template that defines specific content areas within a page layout. Then, you can create specific page templates that extend the master template and only provide content for those designated content areas.

By Matt Zentz

This past week I was working to migrate a site from our old CMS to our new CMS. It's a daunting, partly manual process, especially for large sites. But it's one we're happy to do to get our customers into a superior content management system. In this case, I needed to secure nearly all of the pages for a site by utilizing their external custom app to handle the authentication. Marketpath CMS simply performs checks to validate that login.

The Problem

I won't discuss the auth validation here. That wasn't the issue. The issue was I needed to redirect the user to the custom app's login page if they weren't logged in. Seems simple enough - just add a meta refresh tag with the login url. Easy peasy, except it wasn't. I can't return any of the page content because anyone can fetch the url contents and display them without authenticating. 

Instead, I need to wrap all the content in a big if statement (yes, there are big if statements and little if statements - it's a thing) and if not authorized, return the minimal html so the meta refresh redirects the user to the login page.

Up to this point, all of our new CMS sites used a partial header template and a partial footer template. These were included and in the page template. A simple example is below.

header partial template

<!DOCTYPE html>
<html lang="en">
 <head> <title>My Page</title>
 </head>
 <body>
 <div class="header">....</div>
 <div class="main-content">

page template

{% include "header" %}
<div class="left">
......
</div>
<div class="right"> ......
</div>
{% include "footer" %}

footer partial template

</div>
<div class="footer">....</div>
</body>
</html>


The biggest issue with this method is that, with liquid, I can't start an if statement in the header and end it in the footer. if statements must be completed within their own template.

The Solution

Instead of including a header template and a footer template I can make a master page template and extend it. So the above code then becomes two templates instead of three.

master template (partial template)

<!DOCTYPE html>
<html lang="en">
<head> <title>My Page</title>
</head>
<body> <div class="header">....</div> {% block main_content %} <div class="main-content"> <div class="left">
......
</div>
<div class="right">
......
</div> </div> {% endblock %}
<div class="footer">....</div>
</body>
</html>


specific page template

{% extends "master template" %}

{% block main_content %}  <div class="full-column">
......
</div>
</div> {% endblock %}


In this example, the specific page template only provides those blocks that are defined by the master template. Any other top-level liquid tags will throw an error. You can only have extends and block tags in a template that extends another.

By building my templates this way I am reducing my template load by one and allowing myself to wrap all the content in the big if statement. See below for an example.

master template with authentication logic

{% assign is_authenticated = ([AUTH LOGIC GOES HERE]) %}
{% if is_authenticated %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body> <div class="header">....</div>
{% block main_content %}
<div class="main-content">
<div class="left">
......
</div>
<div class="right">
......
</div> </div>
{% endblock %}
<div class="footer">....</div>
</body>
</html> {% endif %} {% unless is_authenticated %}<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0; url=https://customerloginapp.com/" />
</head>
<body> Redirecting...</body> </html> {% endunless %}


There are two things happening here. First, I'm excluding my auth validation logic. That will be for a future post. 2nd I am using a single if statement and then an unless statement. While working with this code (and beating my head against a wall) I found a bug with having blocks inside an if/else block. Get rid of the else and use unless and it works. It's weird, I know. And when I say I found the bug, I really mean our senior product developer, Levi Carter, found it. He also discovered this master template capability. Kudos, Levi. Kudos.

Finding the master template feature was a great addition to our toolbox for developing complex websites. This is definitely one we'll continue to use in the future.