Shaping the Page

How to Build a Simple Tumblr Blog with ExpressionEngine

Written by Andy Johnson  |  November 20, 2010  |  Permalink

This is a short tutorial explaining how to use ExpressionEngine to build a simple Tumblr blog, similar to the Journal we use on Shaping the Page. If you have even a foundational knowledge of ExpressionEngine, and know the difference between a channel, a template, and a field group, you should be able to follow along just fine.

Channels

Part of the appeal of a Tumblr-style blog are the variety of dedicated post types for entries, making it quick and easy to post a snippet of information or a link, vs. committing to a full blog post. For our Journal we decided we’d be using five different post types: a full entry, a link, a photo, a quote, and a video post type. Like with most things in ExpressionEngine, there are multiple ways to accomplish this. We considered using a single EE channel for the Journal, and then using categories, or even a custom field to target the different post types. But in the end we instead felt more comfortable using a dedicated channel for each post type. This gave us an easy way to use a custom field group for each post type. Here’s how we named our channels:

Field Groups

Since each channel is used for a different post type, we set up separate field groups for each of the channels. This allowed our Publish pages to have a unique set of custom fields depending on the post type. Here are the five field groups we made, along with the unique custom fields within each group:





Templates

For our Journal we made a new Template Group called “journal.” This is the name that shows up in our URL for all journal-related links on our site. So if you’re instead calling your Tumblr blog a “Notebook” for example, then you should name your Template Group accordingly. Within our Template Group we used 3 templates to render our Journal, named as follows:

In order to simplify our site’s URL structure, we’re using the “index” template to serve the appropriate “journal-main” template or “journal-article” template. We do this by using conditional embeds in the “index” template like so:

{if segment_2 == ""}
{embed
="journal/journal-main"}
{if
:else}
{embed
="journal/journal-article"}
{
/if} 

The “journal-main” template is used to render the main page of the Journal where all of the article summaries are listed. Using a single Channel Entries Tag and a set of conditionals we’re able to stream a chronological list of every post type. For each post type we’ve set up a unique HTML structure, and the conditionals tell ExpressionEngine what HTML to use for each post type. It looks like this:

{exp:channel:entries channel="journal-entry|journal-link|journal-photo|journal-quote|journal-video" limit="20" orderby="date"}
  {if channel_short_name 
== 'journal-link'}
  
<div class="link">
      <
h2><a href="{journal-link-URL}">{title}</a></h2>
      
{journal-link-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
  </
div>
  
{if:elseif channel_short_name == 'journal-quote'}
  
<div class="quote">
      <
h2><a href="{journal-quote-URL}">{title}</a></h2>
      <
blockquote>{journal-quote}</blockquote>
      <
span class="source"><a href="{journal-quote-URL}">{journal-quote-source}</a></span>
      
{journal-quote-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
  </
div>
  
{if:elseif channel_short_name == 'journal-entry'}
  
<div class="entry">
      <
h2><a href="{title_permalink="journal"}">{title}</a></h2>
      <
span class="author">Written by <strong>{author}</strong></span>
      <
p>{journal-entry-summary} <span><a href="{title_permalink="journal"}">Read&nbsp;More&hellip;</a></span></p>
      <
span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
  </
div>
  
{if:elseif channel_short_name == 'journal-photo'}
  
<div class="photo">
      <
h2><a href="{title_permalink="journal"}">{title}</a></h2>
      <
img src="{journal-photo-upload}" alt="" />
      
{journal-photo-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
  </
div>
  
{if:elseif channel_short_name == 'journal-video'}
  
<div class="video">
      <
h2><a href="{journal-video-URL}">{title}</a></h2>
      <
div class="video-container">
          <!-- 
start of embed code -->
          
{journal-video-embed}
          
<!-- end of embed code -->
      </
div>
      
{journal-video-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
  </
div>
  
{/if}
{
/exp:channel:entries} 

The “journal-article” template is used to render the full version of a single article. It’s similar to the “journal-main” template, except it’s limited to display a single post, and instead of a summary it displays the full entry for any “Journal-Entry” post types. Again conditionals are used to target the correct HTML to use for each post type. It looks like this:

{exp:channel:entries channel="journal-entry|journal-link|journal-photo|journal-quote|journal-video" limit="1"}
  {if channel_short_name 
== 'journal-link'}
  
<div class="link">
      <
h2><a href="{journal-link-URL}">{title}</a></h2>
      
{journal-link-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
      <
a href="http://twitter.com/share" class="twitter-share-button">Tweet</a>
  </
div>
  
{if:elseif channel_short_name == 'journal-quote'}
  
<div class="quote">
      <
h2><a href="{journal-quote-URL}">{title}</a></h2>
      <
blockquote>{journal-quote}</blockquote>
      <
span class="source"><a href="{journal-quote-URL}">{journal-quote-source}</a></span>
      
{journal-quote-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
      <
a href="http://twitter.com/share" class="twitter-share-button">Tweet</a>
  </
div>
  
{if:elseif channel_short_name == 'journal-entry'}
  
<div class="entry full">
      <
h2><a href="{title_permalink="journal"}">{title}</a></h2>
      <
span class="author">Written by <strong>{author}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}"><strong>Permalink</strong></a></span>
      
{journal-entry-body}
      
<span class="entry-tweet"><a href="http://twitter.com/share" class="twitter-share-button">Tweet</a></span>
  </
div>
  
{if:elseif channel_short_name == 'journal-photo'}
  
<div class="photo">
      <
h2><a href="{title_permalink="journal"}">{title}</a></h2>
      <
img src="{journal-photo-upload}" alt="" />
      
{journal-photo-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
      <
a href="http://twitter.com/share" class="twitter-share-button">Tweet</a>
  </
div>
  
{if:elseif channel_short_name == 'journal-video'}
  
<div class="video">
      <
h2><a href="{journal-video-URL}">{title}</a></h2>
      <
div class="video-container">
          <!-- 
start of embed code -->
          
{journal-video-embed}
          
<!-- end of embed code -->
      </
div>
      
{journal-video-description}
      
<span class="date">Posted on <strong>{entry_date format="%F %j, %Y"}</strong>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{title_permalink="journal"}">Permalink</a></span>
      <
a href="http://twitter.com/share" class="twitter-share-button">Tweet</a>
  </
div>
  
{/if}
{
/exp:channel:entries} 

We could take these templates even further and break up individual components into EE Snippets or Global Variables to have avoided needing to manually duplicate chunks of code between the “journal-main” and “journal-article” templates. But they’re easy enough as-is for us to manage, and we don’t plan on needing to make many edits to these templates in the future.

Now add your own CSS and you’re ready to start publishing your content! This setup has worked really well for us, and we hope it can be at least a helpful starting point for others who are interested in doing the same thing with ExpressionEngine.

Back to Journal Listing