PieCrust

Using blog posts

There are typically a few pages that need to display a list of articles, like the main page of a blog. To do this in PieCrust, you can use the pagination variable on a page. For example, if you’re using the default template engine Twig:

{% for post in pagination.post %}
## [{{ post.title }}]({{ post.uri }})
<span class="post-date">{{ post.date }}</span>
{{ post.content|raw }}
{% endfor %}

This will display a list of posts, and for each display the title with a link to the article, followed by the date and the excerpts.

What PieCrust does is merely expose pagination values to the template engine, and you can use them in any way you like. Check the Twig documentation to find out what you can do.

Note that the pagination variable is called like that because it will paginate the current page by creating sub-pages (see below). If you want to display pages with a list of blogs without any pagination (i.e. without any sub-page), you can either set single_page to true in the page configuration, or use the blog archive variables like blog.posts instead.

Sub-pages

Most pages don’t have sub-pages — there’s just the page. However, pages that show a list of blog posts could have sub-pages if there are too many blog posts. For example, if you only show 5 posts per page and you have written 17 posts in total, your blog’s main page would have 4 sub-pages: sub-page 1 would show posts 17 to 13, sub-page 2 would show posts 12 to 7, etc. (posts are sorted in reverse-chronological order). The visitor would then click on “previous entries” and “next entries” links to navigate back and forth.

If a page’s URL is domain.com/blog, its 3rd sub-page’s URL would look like domain.com/blog/3. This means it’s a bad idea to create an actual page whose name is just a number!

Pagination filtering

If you want to create a page that lists only specific posts, you can filter what you get from the pagination object. You do this with the posts_filters configuration section in your page. For example:

posts_filters:
    has_tags: announcement
    has_tags: piecrust

…will only return posts with the announcement and piecrust tags.

The syntax works like this:

  • has_something: this will look for the something setting in the post’s configuration header. If that setting is an array, and it contains the specified value, then the post is included in the page. Otherwise, it’s skipped.
  • is_something: this will look for the something setting in the post’s configuration header. If that setting exists and is the same as the specified value, then the post is included in the page. Otherwise, it’s skipped.

You can also group has_* and is_* statements in and and or sections to create more complex queries:

posts_filters:
    has_tags: announcement
    or:
        has_tags: piecrust
        has_tags: stupidhttp

This would return only posts with announcements regarding PieCrust or StupidHttp.

You can also use the not clause to exclude something:

post_filters:
    has_tags: announcement
    not:
        has_tags: family

This will return all announcement posts except those regarding the family.

Pagination reference

Pagination object reference

Here’s a list of variables accessible on the pagination object:

  • posts: That’s the list of blog posts for the current page. The number of posts in the list is at most posts_per_page, as defined in either the page’s or the site’s configuration. PieCrust takes care of returning the correct posts if the current page is a sub-page (e.g. page #2 of your blog’s main page).

  • prev_page: The URL of the previous sub-page, if any.

  • this_page: The URL of this sub-page.

  • next_page: The URL of the next sub-page, if any.

  • posts_per_page: The effective number of posts to be theoritically displayed on the page.

  • posts_this_page: The actual number of posts displayed on this page (can be anything between 1 and posts_per_page).

  • prev_page_number: The previous sub-page number, if any.

  • this_page_number: The current sub-page number, if any.

  • next_page_number: The next sub-page number, if any.

  • total_post_count: The total number of posts across all sub-pages.

  • total_page_count: The total number of sub-pages.

  • next_post: The next post object.

  • prev_post: The previous post object.

Posts array reference

The posts variable, on top of being enumerable (e.g. with the for construct in Twig), also has a few methods:

  • posts.all: Resets the filtering currently active for the page and returns all posts. It’s the only way to get rid of the default filtering applied by PieCrust which “slices” the array of posts in order to return only the appropriate portion to be displayed on the current page (e.g. posts 6 through 10 on page 2, assuming 5 posts per page). If you’re using this in conjunction with the single_page setting, you might as well use blog.posts instead. See the blog archives documentation.

  • posts.skip(n): Skips n posts from the beginning of the posts array.

  • posts.limit(n): Limits the number of posts in the array to n.

  • posts.filter(filtername): Applies a filter named filtername to the pagination. This must be a page configuration setting similar to post_filters, but named filtername.

  • posts.in_category(name): Returns only posts in category name.

  • posts.with_tag(name): Returns only posts with tag name.

  • posts.with_tags(name1, name2, ...): Returns only posts with all given tag names.

  • posts.count: Returns the number of posts in the array (after all filters,

  • offsets and limits have been applied).

All those methods return the posts array itself, so you can chain them. For instance, the following code snippet would return the first 10 posts in category ‘recipes`.

pagination.posts.all.in_category('recipes').limit(10)

Note that skip is not cumulative, so posts.skip(3).skip(1) will not skip 4 posts from the beginning of the array — it will only skip 1 post! (the last specified skip value). Similarly, in_category, with_tag and with_tags are not cumulative either: posts.in_category('recipes').with_tag('apple') will return all posts tagged with “apple” regardless of their category. Those methods are only for convenience — if you want complex filtering, use the filter() method, or the post_filters feature.

Post object reference

Now here’s a list of variables available on each post:

  • url: That’s the local address of the post. You need to prepend the site.root to it, or pass it through the pcurl function if you want to use it as a hyperlink.

  • slug: The relative URL of the post.

  • date: The formatted date of the post. The date format is the one defined in the page’s or site’s configuration.

  • timestamp: The timestamp of the post, in case you need to re-format the date yourself.

  • content: The contents of the post.

  • has_more: If the post had a page break in it, the content variable only returns the first part (the “excerpt”), and has_more is set to true so you can add a “Read more…” link that points to the post’s URL.

Also, the whole page configuration of the post is available directly.

Fork me on GitHub