Featured Community Plugin: Trending Recipes
This post is part of a series, featuring the incredible work of plugin authors who grow the TRMNL plugin ecosystem with every contribution. The TRMNL team has individually selected these plugins and authors to be featured.
Trending Recipes Plugin
Community member ExcuseMe (Discord: ExcuseMe) created the Trending Recipes plugin; here are their words on how it was created.
Why did you want this plugin to exist?
As someone who has published a couple of recipes, I found myself checking installs and forks more than once a day whenever I'd put something new out there. It's always exciting to see whether your idea, and your execution of it, resonates enough to earn a spot on someone's screen. But there was no easy way to see that momentum at a glance: which recipes are gaining traction right now, and how does mine compare? I wanted that feedback loop right on my TRMNL, not buried in a browser tab.
Why were you the person to make it?
I already had experience building a simple backend with a database for TRMNL recipes, and this plugin couldn't exist without one since it needs to take hourly snapshots to calculate deltas over time. But more than the technical side, I think it came down to scratching my own itch. I wanted a better way to track how my published recipes are doing while also keeping an eye on what the rest of the community is building. Once I realized nobody else was surfacing that kind of trending data, it felt like the obvious next thing to build.
How did you balance look vs functionality?
At the start, the data was clear: mainly the current connections and how they changed over the last x hours or days. It became harder to balance once the plugin started extracting statistics that weren't available before, like trending ranks, overall connection rankings, and user-level stats. Had this been just a private recipe, more numbers would have made it onto the screen because their meaning was obvious to me. But you can't expect that from a regular user. You also can't explain every number with just a little icon in front of it, and even if you could, that would look messy in a repeating section.
What was your process for creating the plugin?
It started with a small Python server in a Docker container that fetches all the public recipe data on a regular schedule, plus an endpoint to serve that data to a TRMNL recipe. AI is especially useful for these early steps to get a minimal viable product going, since the goal is to find out as soon as possible whether a recipe idea is even worth the time. From there, I build a simple version of the recipe using TRMNL's framework styling, just displaying the rough data to get a feel for whether it's on the right track. This one borrows from my Network Devices recipe: Columns with the overflow functionality to fill any screen with items, leaving little unused space; especially great when larger screen devices. After that it's refining. Add something, refine again; until you're happy enough to publish.
Did you learn anything that you want to apply to other recipes you create(d)?
One thing worth sharing is an SVG filter I picked up from L #1385, something I didn't even know was possible. Recipe icons are user-uploaded and can be full-color, which can render as muddy gray on a 1-bit or 2-bit screen. This hidden SVG filter converts colors to grayscale and snaps them to discrete levels, keeping icons crisp on e-ink:
<svg width="0" height="0" style="position: absolute">
<defs>
<filter id="binarize">
<feColorMatrix
type="matrix"
values="0.0722 0.7152 0.2126 0 00.0722 0.7152 0.2126 0 00.0722 0.7152 0.2126 0 00 0 0 1 0"
/>
<feComponentTransfer>
<feFuncR type="discrete" tableValues="0 0.25 0.75 1" />
<feFuncG type="discrete" tableValues="0 0.25 0.75 1" />
<feFuncB type="discrete" tableValues="0 0.25 0.75 1" />
</feComponentTransfer>
</filter>
</defs>
</svg>
Then apply it conditionally with CSS so it only kicks in on e-ink screens:
.screen--1bit .binarize, .screen--2bit .binarize {filter: url(#binarize);}
Any element with the "binarize" class gets its colors crunched down to 4 levels on the device, but renders normally in the preview.
Is there a tip you would give to a new developer?
Use a main template so you don't have to duplicate your code in each view for maintainability. What works well for me is to start by designing the full view of the recipe, then strip down the data as the views get smaller, or maybe change the layout between horizontal and vertical depending on the view. One of the best ways to achieve that is defining a template in your shared.liquid and calling render from each view. For example, in the full view of this plugin I just have this code:
{% render "main", trmnl:trmnl, recipes:recipes, user_recipes:user_recipes, user_stats:user_stats, global_stats:global_stats, timeframe:timeframe, columns:3, compact: false%}All the data is passed as arguments (including the global {{trmnl}} variable), along with view-specific parameters.The columns argument defines the maximum columns per view, and the compact flag decides whether I need to limit the text inside the title bar.
What is your favorite plugin that someone else created and why?
Having recently set up a home media server, at the moment I would say it's Servarr Dashboard. A mashup combines Radarr and Sonarr into a single status report that's also useful for the rest of the family.