The Statamic Add-on Roundup

July 23, 2017 —John Koster

This article was written for a site migration that happened targeting an early version of Statamic 2. The content of this article is outdated, and no longer applies to the Stillat.com website.

I was asked on Twitter about the custom Statamic add-ons that power the Stillat site; here we go! I will discuss the reason for each add-on at a high level, even if they are incredibly site-specific. In the article Rebuilding Stillat.com I talked about how there are sixteen custom add-ons that power the site. Here is a list of all of the add-ons this site is running (at the time of writing) as they appeared in the Statamic Control Panel:

By no means do you need to create this many specialized add-ons to create an amazing Statamic site. Most of them were an excuse to get to know the add-on API and underlying systems :)

Name
BillingContent
BuildResources
CategoriesFilter
Configurable Composer Manager
DataTools
Gazelle
Magpie
MarkdownModifier
Markdown Tools
Meerkat
PostImage
RainFrog
RecentlyPublishedTags
Request
RouteList
TechResources

#BillingContent

The BillingContent add-on acts as a content delivery API for a customized Laravel Spark installation. The Laravel Spark installation uses many of the same assets as the Statamic site; this API delivers content to the Spark application so that I do not have to remember to update the content of the Spark application every time I update something within Statamic.

#BuildResources

The BuildResources add-on only provides some incredibly specialized console commands. There is a section of the site Technology Resources. This section of the site parses many of the "awesome" lists that can be found on GitHub and provides categorized access to them (well, any of them that are made available by the site).

This command simply fetches the new content from each of these lists and populates specialized collections with content and attribution (the command will analyze the license of each of these repositories).

The roots of this section of the site can be found in this (very old) article: Thoughts on a "Guidance Engine".

#TechResources

The TechResources add-on is related to the BuildResources add-on. Many of the views (or pages) that can be seen on the Technology Resources section of the site are implemented as Laravel Blade templates. The reason this was done was to leverage Collection chunking as well as partial view rendering (also, complicated logic could be done in PHP without enabling PHP in Antlers templates). This add-on builds up a string that is cached, and then ultimately returned to the client as the page that loads when you vist https://stillat.com/projects/tech.

#CategoriesFilter

The CategoriesFilter add-on is simply a custom Statamic Collection Filter that is really good at figuring out how articles on the site are related to one another based on their category. This is made simpler by the fact that I am limiting each article on the site to exactly one category.

This add-on was originally developed before Statamic version 2.5.9, which fixed a bug this custom add-on addressed. This add-on now simply supplements Statamic's features based on how categories are setup for this site.

#Configurable Composer Manager

The ConfigurableComposerManager add-on simply allows developers to make configuration changes to the Composer executable that Statamic internally uses to manage add-on updates. This also allowed me to specify a custom Composer installation location when I developed the site on Windows systems (I now use a 27 inch iMac and a MacBook Pro for all Stillat development).

A properly configured Windows development environment can address the issues that this add-on solves, but that becomes messy when working with many different web servers and PHP versions.

This add-on is freely available at https://github.com/JohnathonKoster/statamic-configurable-composer-manager.

#Data Tools

The DataTools add-on allows me to perform arbitrary arithmetic and comparison operations within an Antlers template. Granted, I could have enabled PHP within templates but I really didn't want to (also, there might be some syntax to accomplish this with Antlers, I just couldn't figure it out at the time). You can use comparision operators in Antlers templates, but that becomes much more complicated when variables are being passed into partials, and those partials themselves are deeply nested.

An example is how the "Projects" section of this site's footer is constructed:

1<ul class="list list-simple-mini font-s13">
2 {{ relate:featured_projects }}
3 <li>
4 {{ if commercial_url }}
5 <a class="font-w600" href="{{ homepage }}{{ commercial_url }}">{{ name | truncate:15:... }}</a>
6 {{ elseif {data_tools:le value="{project_url}" length="0"} || keep_local }}
7 <a class="font-w600" href="{{ url }}">{{ name | truncate:15:... }}</a>
8 {{ else }}
9 <a class="font-w600" href="{{ project_url }}" target="_blank">{{ name | truncate:15:... }}</a>
10 {{ /if }}
11 </li>
12 {{ /relate:featured_projects }}
13</ul>

As you can see, we are using the DataTools add-on in a weird way to perform comparisons on nested variables (the above example is checking that the project_url is less than or equal to 0). Ugly, but useful (not to mention you have to create a tag function for each operation!).

#Gazelle

The Gazelle add-on is just a way for Antlers templates to detect if the client has JavaScript enabled or not. It uses a meta redirects to indicate that JavaScript is not enabled. Not a limitation of Statamic, just a curiosity.

#Magpie

Magpie allows me to create backups of the site incredibly easily. It is a command line utility, which means I can easily schedule its execution. There is a lot to this add-on, like configurable off-site storage locations; the details can be found at https://github.com/JohnathonKoster/magpie-backups-for-statamic. This add-on is also freely available to the Statamic community.

#MarkdownModifier

The MarkdownModifier add-on is another site-specific add-on. You may have noticed that tables, images, etc. that appear within blog posts are wider than the actual post. This would be a pain to manage for each post, so this add-on handles the dynamic re-structuring of each blog post as it is requested.

This add-on will also add the alt text of images inline, as well as alternate which side of the image the text appears on throughout the post.

Perhaps one of the most useful features this add-on provides is a way to dynamically generate a table of contents for a blog post or article. This feature is used heavily in the Meerkat Documentation section of the site.

#Markdown Tools

Markdown Tools for Statamic is another freely available add-on (you can find it at https://github.com/JohnathonKoster/statamic-markdown-tools). It allows site admins to handle text replacements across the entire site (for example, to handle the renaming of the Apple desktop operating system to macOS, as I do on this blog).

The Markdown Tools for Statamic will also generate Markua-flavored Markdown for authors who write a lot of content that is shared between LeanPub publications as well as their blog.

#Meerkat

Meerkat is an add-on that provides a flat-file comment system for Statamic sites; it was designed to be as familiar to users coming from WordPress as possible while also taking advantage of Statamic features. It is a commercial add-on; this is mainly due to the amount of time it took to complete.

#PostImage

You may have noticed that there are many different sizes of "post images" on this site. One of the first versions of the site that I built used an image with the same dimensions for each place a blog post might appear. For example, on the home page, you will find a section containing featured blog posts, recent blog posts as well as an "explore" blog posts section (this is simply a restructured version of the "Up Next" section you will find below this post). Each of these sections have varying requirements for image sizes. When I was using just one image for all of these places, the compression/expansion of the images produced a result I was unhappy with.

Now, each blog post that has an image actually has five different images associated with it that were created for each place it might appear on the site. I use the post_image add-on tag like so:

1{{ post_image placement="{placement}" }}

The placement variable simply indicates where on the site it will appear, and the tag will inspect the context from which it was called to figure out whether to show a category image, or an image for that specific blog post. This add-on was first implemented as an Antlers template partial, but that became way too complicated, and probably should have been implemented as add-on in the first place.

its definitely more work for each blog post, but worth it.

#RainFrog

RainFrog is an add-on that I developed as a sort of "catch-all" add-on. It will produce meta tags for me automatically when I have not specified them for any given post:

1<meta itemprop="description" content="{{ rain_frog:keywords }}">

or a description like so:

1<meta itemprop="description" content="{{ rain_frog:description }}">

The keywords method simply produces a list of keywords based on the frequency of which they appear in the blog post. It uses MySQL's word stop-list to filter out common English words. It would be trivial to implement this in other languages, I just don't have a need for that at the moment.

The description method is a little more complicated because it will get the first sentence of "logical" paragraphs and use that as a description for the blog post. This is similar to the "summarize" feature found in many first-party Apple products.

This add-on also provides ways for me to force an exception or 404 error on a page to test the error pages for the template.

This add-on is considered "specialized" since the structure and writing style of each author's blog post will affect the implementation greatly. A general purpose add-on could be built utilizing IBM's Watson APIs, but that is over-kill (that doesn't mean I don't like the idea, however).

#RecentlyPublishedTags

The RecentlyPublishedTags add-on is just another Collection filter. Let's consider a blog post that has a tag "Laravel" that was published in the year 2014. If this tag is executed within the context of that blog post, it would automatically find any recent posts from the current year (or the most recent year it can find) that has matching tags.

It is used in the following manner:

1{{ collection:blog filter="recently_published_tags" sort="date:desc" scope="tag" limit="5" }}
2 
3{{ /collection:blog }}

#Request

The Request add-on provides a request tag that can be used to get information about the client's request. For example, there was no easy way to determine if a URL query parameter was present; that was the main reason this add-on exists. It is used on the search page. I wanted a way to customize the search results page if a user directly accessed the page without entering a search query.

Here is an example of how it used on this site:

1{{ if {request:has param="q"} }}
2 
3{{ /if }}

#RouteList

The RouteList is another add-on that is freely available to the Statamic community (you can read specific details about it at https://github.com/JohnathonKoster/statamic-route-list-command). I am really comfortable developing applications with Laravel, and when I first started developing my site with Statamic, the YAML routes syntax felt a little awkward. This add-on was developed primarily to check that the routes I was writing using the YAML syntax were actually working. This is not a deficiency of Statamic, but rather a learning curve issue.

#Conclusion

That's all of the custom add-ons that were developed to make the new site work. Granted, some of these add-ons are primarily useful only during the development of the site, but, because of the amazing work-flows that Statamic enables, they should not be discounted.

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.