Clean Templates with Stash

Clean Templates with Stash

I am not sure if it is still hip and trendy within the ExpressionEngine (EE) community to use Stash. There was so much buzz about it when people started using it and talking about it, and we have received a few EE projects utilizing it.

I like it, it has its quirks but I think it not only helps improve rendering but also cleans up your template code considerably. Traditionally at my old studio, and I want to note there are several ways to do this, we would typically have a section, say About, with a landing page that listed all the entries for that section and a detail page that had the actually content for the entry. To set this up you would create your section group:

/about.group

Within there, you would create the index page along with the .landing and .detail page. So now your structure looks like this:

/about.group
    index.html
    .landing.html
    .detail.html

These would then be embedded within the index page depending on a segment conditional. If segment_2 is empty, we embed the landing page, else we show the detail page and let EE figure out the entry.

{if segment_2 == ''}
    {embed="about/.landing"}
{if:else}
    {embed="about/.detail"}
{/if}

Ok, a little clunky, we now have three files to keep track of whenever we have changes to this section. What if the clients wants to change the container for the content, ie. the index page? We'll need to go through each index page of each section to change it. Say the client wants the title to be in gold for just the About section? Would you then go into the .detail page and add a class for the h1? Now you will have to be careful that no one comes along and copies over what is usually boilerplate code for the detail section.

Issues like these start adding up: driving up maintenance time and turnaround for client requests. What if instead we have one, well documented, file per section, one container, and a simple tag we can utilize for any custom styling? Not only will this clean things up considerably, but can make edits much more manageable.

Setting up clean templates

I will not go over Stash basics, there are some tutorials available on the general structure of using Stash partials. If you do not already have it created, you will want to create a section for all your wrappers. I usually call this /_layouts.group, in here you will want to add your wrapper for all your pages. I want to note that you can create as many wrappers as you'd like, but for this article I am trying to keep the amount of trackable files down. Having one layout for the homepage and one for the inner pages is pretty common.

Within here, I want to set up the container for all your page content so we will be getting all the stash variables we are going to set, starting with the <head>. Now, I am a big fan of SEO lite, so we will put a block in the head to grab a section title:

<!DOCTYPE HTML>
<html>
    <head>
        {if segment_2 == ''}
        {exp:stash:get name="seo-title"}
        {if:elseif segment_2 == 'category'}
        {exp:seo_lite category_url_title="{segment_3}"}
        {if:else}
        {exp:seo_lite url_title="{segment_2}"}
        {/if}

This sets it up so if we are on the landing page we will grab a title variable off our page, otherwise we will check to see if we are using category headings (assuming we are using /category/ as the segment name). I paste this block within all wrapper regardless of using categories, if we do we will not have to go back through any code. If nothing matches, let's grab the url_title off the last segment.

After that we will include meta tags, links to stylesheets and web-fonts, and scripts we will be using on all pages. I include a {exp:stash:get name="head"} for any additional scripts or anything else needed. Remember that calling a get on something that isn't set is fine, it doesn't add much overhead and let's you set up defined blocks within your template to stash.

Down to the <body> tag, I like to add in a section identifier that I can later use as a 'hook' for any custom css or script:

<body id="{exp:stash:get name='id'}">

Going down to where you will have your content, you will probably have something like <div id="main"> or <article> tag, let's grab our stashed content:

<div id="main">
    {exp:stash:get name="content"}
</div>

I also want to grab the secondary content, such as section menu along with any callouts:

<div id="secondary">
    {exp:stash:get name="secondary"}
</div>

Now, let's get to the actually template. First we can devote the first lines to some general comments, Copyright/TOS, documentation, etc. I like have a boiler plate section that lists the developer who last edited it too.

{!--
Page: AwesomeSite.com
Section: About
Last Edited By: Chris Hardee (chris.hardee@grok-interactive.com)
Last Edited On: 03/24/2014 14:10
Notes: < page notes >
--}

I also like to prepend a title before each stash block, along with any notes if needed.

Now let's add our one and only embed:

{!-- Layout --}
{embed="_layouts/page"}

Stash users know you can put the embed anywhere you like, I like to put it front and center.

Next, and I will talk about this in the next section, I like to assign an ID variable that we can use for any css or script for that specific section:

{!-- ID --}
{exp:stash:set name="id"}about{/exp:stash:set}

Our SEO Title we are grabbing from earlier:

{!-- SEO Title --}
{exp:stash:set name="seo-title" parse="inward"}
{exp:seo_lite default_title="About Us"}
{/exp:stash:set}

Now let's start on the content, we will want to first check to see if we are on a landing page or a detail page.

{!-- Content --}
{exp:stash:set name="content"}
    {if segment_2 == ''}
    {if:else}
    {/if}
{/exp:stash:set}

Looping through our entries depending on whether we are on a landing page or entry page.

{!-- Content --}
{exp:stash:set name="content"}
    {if segment_2 == ''}
        <h1>About Us</h1>
        {exp:channel:entries channel="about" disable="member_data|categories" limit="5" paginate="bottom"}
            <a href="{url_title_path='about/index'}">
                <h2>{title}</h2>
                {summary}
            </a>
        {/exp:channel:entries}
    {if:else}
        {exp:channel:entries channel="about" disable="member_data|pagination|categories"}
            <h1>{title}</h1>
            {content}
        {/exp:channel:entries}
    {/if}
{/exp:stash:set}

There we go! We now have our detail and landing sections all within one template, with only one embed.

ID Hooks

Remember when we set that section ID up? Well let's say if a client asks us to make all the titles for the event section to be in Comic-Sans. Normally you'd have to set up a class, call it about-font, and add it to all the titles or add it to the main section and let all child title appear in this new font.

Instead what I do is use that ID in a special section or separate file for any changes. In our custom.css file:

/* Section Styles */

body#about h1 {
    font-family: Comic Sans, Comic Sans MS, cursive;
}

Now we have some clear designation on which sections have differing styles, which is especially helpful when all the inner sections share the same wrapper.

That is it for this blog post, let me know if you have any comments for suggestions on ExpressionEngine or Stash usage. Also let us know if you have an Expression Engine work that needs to be done!

Links

Categories: Software Development | Tags: Expression Engine

Portrait photo for Chris Hardee Chris Hardee

Developer at Grok-Interactive and first full-time employee. Develops in Rails & PHP, along with projects for/involving Expression Engine, Responsive Web Design, and Mobile Applications. When he is not developing he helps run the San Antonio hackerspace 10BitWorks.com

Comments


LET US HELP YOU!

We provide a free consultation to discover competitive advantages for your business. Contact us today to schedule an appointment.