<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Matt Soria&apos;s Journal</title><description>A collection of thoughts, musings, snapshots, and doodles.</description><link>https://mattsoria.com/journal</link><language>en-us</language><item><title>Slitscanner</title><link>https://mattsoria.com/journal/slitscanner</link><guid isPermaLink="true">https://mattsoria.com/journal/slitscanner</guid><pubDate>Tue, 24 Mar 2026 05:55:00 GMT</pubDate><content:encoded>&lt;img src=&quot;personal/slitscanner-screenshot.jpg&quot; alt=&quot;Screenshot of the Slitscanner web application in use.&quot; /&gt;&lt;p&gt;&lt;p&gt;&lt;strong&gt;tl;dr: I built a web app called &lt;/strong&gt;&lt;a href=&quot;https://www.slitscanner.app/&quot;&gt;&lt;strong&gt;Slitscanner&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/p&gt;&lt;p&gt;I was working on the redesign of this very website when I was noodling on what, if any, photo of myself to put on the site. Plenty of photos exist of me online, but I&apos;m still a little shy about putting more of them out there, so my mind went to distorting a portrait a bit to be just enough to satisfy the need, but still have some fun with it. I had been using the &quot;slit-scan&quot; effect with my flatbed scanner a bit recently for some fun little side projects, so I thought I could apply that technique to get something usable.&lt;/p&gt;&lt;p&gt;As is often the case when working on a personal project, I was doing this late at night in my office, which shares a wall with my 3-year-old daughter&apos;s bedroom, and my big flatbed scanner is pretty loud. Not wanting to chance waking her, I thought, &quot;There must be a web-based tool for simulating this effect.&quot; But after searching around, I couldn&apos;t really find anything that did exactly what I was looking for.&lt;/p&gt;&lt;img src=&quot;personal/journal/slitscanner/slitscanner-2400x2400-1772174889745.png&quot; alt=&quot;Black and white portrait of a man that is wobbly and distorted, with the face covered by an illustration of a distorted smiley face.&quot; /&gt;&lt;p&gt;I did find &lt;a href=&quot;https://antlii.work/SKAAAN-Tool&quot;&gt;this tool&lt;/a&gt;, wonderfully named &quot;SKAAAN Tool&quot;, made by a fellow named Antlii. It is really well done, but I found the controls a little unintuitive, and it didn&apos;t have a few features I found myself wanting—like the ability to add multiple layers and add text.&lt;/p&gt;&lt;img src=&quot;personal/journal/slitscanner/skaaan-tool.jpg&quot; alt=&quot;&quot; /&gt;&lt;p&gt;I genuinely found the prospect of creating the tool I was looking for exciting, because there just aren&apos;t many things I need or even want to do that don&apos;t already have a decent solution. &lt;i&gt;But&lt;/i&gt;, this was pretty much the definition of &lt;a href=&quot;https://en.wiktionary.org/wiki/yak_shaving&quot;&gt;yak shaving&lt;/a&gt;. After all, it was just a dang photo of myself that I needed for the website I was supposed to be rebuilding. So I knew I couldn&apos;t resist, but I also didn&apos;t want to spend &lt;i&gt;too&lt;/i&gt; much time on it. &lt;/p&gt;&lt;p&gt;So, as much as I have been a critic and a skeptic, and as much as it pained (and still pains) me to say it, this seemed like a good candidate for giving &apos;vibe coding&apos; (god I hate even typing that) a chance. I&apos;m not sure what people even consider &apos;vibe coding&apos;—like, is it never touching a line of code yourself? Or is it just &lt;i&gt;heavily assisted&lt;/i&gt;? Whatever the case, it doesn&apos;t matter, but I would put this in the &lt;i&gt;heavily assisted camp&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;I knew it was going to be canvas-based, cause cnavas is what you use when you want to generate some raster art and make it savable. But I honestly don&apos;t have a ton of experience with canvas. I&apos;ve used &lt;a href=&quot;https://p5js.org/&quot;&gt;p5.js&lt;/a&gt; in the past for some simple effects, but nothing too complicated. And I knew I wanted to build it in &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;, because I just really like building little projects in Astro—I know it well enough to make it a quick and enjoyable process that doesn&apos;t get hung up on project configuration.&lt;/p&gt;&lt;p&gt;So I set up an Astro project, and got to prompting. I didn&apos;t have the foresight to document my prompting journey in Cursor, but I believe I started pretty basic, in &lt;a href=&quot;https://cursor.com/docs/agent/plan-mode&quot;&gt;&apos;plan&apos; mode&lt;/a&gt;, probably with something like:&lt;/p&gt;Create a plan for building a web-app in this astro.build project that simulates the &apos;slit-scan&apos; effect acheived when placing an object on a flatbed scanner, hitting &apos;scan&apos;, and dragging the object around as it scans. It should use HTML canvas, and allow the visitor to upload an image to the canvas, hit a &quot;scan&quot; button, and drag it around as a line that simulates the scanning bulb moves from the top of the canvas, to the bottom of the canvas, saving the llines on the canvas it passes in place as it progresses.&lt;p&gt;I&apos;m sure the actual prompt differed quite a bit, but that was the gist. And it did a pretty good job of getting that basic functionality down right off the bat. From there there process looked like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Test the output&lt;/li&gt;&lt;li&gt;Manually modify the markup or JavaScript logic where needed&lt;/li&gt;&lt;li&gt;Prompt for additional functionality, or tedious tasks (like reordering things, moving the general layout around)&lt;/li&gt;&lt;li&gt;Test the output&lt;/li&gt;&lt;li&gt;Repeat &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This was more or less the same process for the majority of the project until I got close to what felt like a version 1 feature-complete tool, and at that point, I went in and overhauled the CSS and heavily adjusted the markup to my liking. I gave it some general styling pointers throughout, but it was pretty bland and unnecessary to nail down during the early stages. I&apos;m still a semi-reluctant user of these tools to begin with, and I just felt like CSS and styling are things I&apos;m both good at, and enjoy doing. &lt;/p&gt;&lt;img src=&quot;personal/journal/slitscanner/virtual-scan-2400x1800-1770878969193.png&quot; alt=&quot;null&quot; /&gt;&lt;p&gt;Even though the whole reason I started this adventure was to create a fun self-portrait, pretty early on in building the thing I realized it would be way more fun to be able to mess around with text. So I added the ability to add text to the canvas, and of course you need to be able to choose a font you want to work with. The fun thing about that part is that the &lt;code&gt;font-family&lt;/code&gt; property can be any font you have installed locally on your machine, and because it&apos;s just being dispalyed on the page and not saved to a server, you don&apos;t have to upload a font file, you just set the name in a text input and you&apos;re good to go!&lt;/p&gt;&lt;p&gt;I sent an early in-progress version to a few friends who I thought would have fun with it, and they gave me some really great feedback, and some bug reports. After more iterations, and more features (using your device camera as a layer, adding some easing to the drag, setting layer blending modes), I felt like I got it to a pretty good place. &lt;/p&gt;&lt;img src=&quot;personal/journal/slitscanner/will-miller_superrr.jpg&quot; alt=&quot;&quot; /&gt;&lt;p&gt;I shared it in a few different channels (friends, Reddit, Discord), and to be honest, I thought it would create a lot more spark than it did. I had generally positive reactions to it, but no evidence of sustained use. I even took the opportunity to try out &lt;a href=&quot;https://usefathom.com/&quot;&gt;Fathom&lt;/a&gt; as a privacy-focused alternative to Google Analytics, and I found it to be an awesome piece of traffic tracking software that only gives you enough non-personal data to get a decent idea of what kind of traffic a site is getting.&lt;/p&gt;&lt;p&gt;This could be in part because I&apos;m just not very comfortable marketing myself, or things that I&apos;ve made. But I also realized that while I find this tool super fun, and pretty dang good at achieving what I wanted—an easy-to-use, web app to create images using the &apos;slit-scan&apos; effect, that&apos;s just not something most people have a need for very often. Even designers and creative types like me, don&apos;t need to do that but once in a while. &lt;/p&gt;&lt;p&gt;I think I got excited about building something (with lots of assistance) that for once didn&apos;t already have a dozen good alternatives, and thought it might gain some traction for that reason alone. But it won&apos;t get used if no one knows it exists, and being that it has such a niche use case, with an already pretty niche group, it was never going to be a tool anyone turns to daily—myself included! I spent a lot of time building it over a few weeks or so, and have only used it a handful of times since.&lt;/p&gt;&lt;p&gt;Maybe that&apos;s also kind of how &apos;vibe-coded&apos; projects tend to go. If you find yourself wanting to build something that doesn&apos;t already have a decent tool, maybe it&apos;s already pretty niche, and maybe scratching your own itch is pretty satisfying at first, but it may be an itch few others have, and you yourself may lose interest in a short period of time.&lt;/p&gt;&lt;p&gt;It&apos;s probably just me, though.&lt;/p&gt;&lt;p&gt;If you do find yourself in a situation where you do need to create some slit-scan imagery, I hope you find this, and I hope you find Slitscanner does a good job, and you have fun with it. Please feel free to &lt;a href=&quot;mailto:matt.soria@hey.com&quot;&gt;share anything you make with it&lt;/a&gt;—I&apos;d love to see it.&lt;/p&gt;</content:encoded><category>Dev</category><category>Design</category></item><item><title>Gradient-Revealed Text: An Alternative Approach to Gsap&apos;s SplitText</title><link>https://mattsoria.com/journal/gradient-revealed-text-an-alternative-approach-to-gsaps-splittext</link><guid isPermaLink="true">https://mattsoria.com/journal/gradient-revealed-text-an-alternative-approach-to-gsaps-splittext</guid><pubDate>Mon, 16 Feb 2026 09:11:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;p&gt;&lt;strong&gt;tl;dr: &lt;/strong&gt;&lt;a href=&quot;#gsap-free-solution&quot;&gt;jump to my CSS/GSAP-free solution&lt;/a&gt;&lt;/p&gt;&lt;/p&gt;&lt;p&gt;I was working on a client project recently that featured a section of text that was supposed to start at a very low-contrast color, and then as the section scrolled into view, the text was supposed to transition, character-by-character, to a high-contrast color. This is something I&apos;ve seen before, and I&apos;m sure you have too. I immediately thought: &quot;GSAP&apos;s SplitText.&quot;&lt;/p&gt;&lt;p&gt;And that&apos;s exactly what I turned to. I put together a component that used &lt;a href=&quot;https://gsap.com/docs/v3/Plugins/ScrollTrigger/&quot;&gt;GSAP&apos;s ScrollTrigger plugin&lt;/a&gt; to handle the triggering of the event when the section was at the right position in the viewport, and &lt;a href=&quot;https://gsap.com/docs/v3/Plugins/SplitText/&quot;&gt;GSAP&apos;s SplitText plugin&lt;/a&gt; to handle the character-by-character color animation. &lt;/p&gt;&lt;p&gt;This all worked well, and was easy to implement, but then I pulled up Deque&apos;s AXE Devtools to test the page for simple accessibility concerns, and it flagged an error on my new component: &lt;a href=&quot;https://dequeuniversity.com/rules/axe/4.11/aria-prohibited-attr?application=AxeChrome&quot;&gt;&lt;strong&gt;Elements must only use permitted ARIA attributes&lt;/strong&gt;&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/itsmattsoria/pen/EayGyvG/8bf89d2ea46ac24a14ceb346536ba539&quot;&gt;
  GSAP SplitText A11y Error&lt;/a&gt; by Matt Soria (&lt;a href=&quot;https://codepen.io/itsmattsoria&quot;&gt;@itsmattsoria&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;p&gt;If you have &lt;a href=&quot;https://www.deque.com/axe/devtools/extension&quot;&gt;Deque&apos;s AXE Devtools browser extension&lt;/a&gt; installed and you run it on that demo, you&apos;ll see that same error. &lt;/p&gt;&lt;p&gt;I could see what the issue was: I had initiated SplitText on a &lt;code&gt;div&lt;/code&gt;, which is the element SplitText slapped &lt;code&gt;aria-label&lt;/code&gt; onto with the text content of the inner HTML, and a div, without a given role, can&apos;t have &lt;code&gt;aria-label&lt;/code&gt;. I was using a div for a good reason, though: the text I wanted to animate was coming from a rich text field of a CMS, which could contain multiple &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; elements, and some styled &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; elements as well, so a generic container made the most sense. I could futz around with stripping that data of the tags as long as it was all going to be communicated by &lt;code&gt;aria-label&lt;/code&gt; anyway, but whenever I find myself getting into the territory of stripping semantics and structural meaning, it&apos;s a clear red flag begging the question, &quot;Is there not a simpler way?&quot;&lt;/p&gt;&lt;p&gt;GSAP has this very scenario &lt;a href=&quot;https://gsap.com/docs/v3/Plugins/SplitText/#alternate-strategy-for-maximizing-nested-element-accessibility&quot;&gt;covered in their docs,&lt;/a&gt; though, and the proposed solution is to tell GSAP to leave off all of the &lt;code&gt;aria&lt;/code&gt; attributes and let you handle it by duplicating the text markup in question, and visually hiding it, while adding &lt;code&gt;aria-hidden=&quot;true&quot;&lt;/code&gt; to the element to be animated by GSAP:&lt;/p&gt;
&lt;div&gt;
  &lt;p&gt;Animated text...&lt;/p&gt;
  &lt;p&gt;Some &lt;strong&gt;more&lt;/strong&gt; animated text.&lt;/p&gt;
&lt;div&gt;


&lt;div&gt;
  &lt;p&gt;Animated text...&lt;/p&gt;
  &lt;p&gt;Some &lt;strong&gt;more&lt;/strong&gt; animated text.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;My coworker Abigail actually shared &lt;a href=&quot;https://adrianroselli.com/2026/02/you-know-what-just-dont-split-words-into-letters.html&quot;&gt;this post by Adrian Roselli&lt;/a&gt; urging you to just not do it, the day after I encountered this. I was already unsatisfied with the look of the animation (seen in the above CodePen) and this encouraged me to take another look and see if I couldn&apos;t find another approach.&lt;/p&gt;&lt;p&gt;That&apos;s when I decided to try and try it without SplitText and just go straight CSS. For the purposes of the design I was implementing, it actually wasn&apos;t important to be able to animate each letter individually since the letters themselves were meant to stay stationary, and the starting point of the animation was the same text, just at a lighter color.&lt;/p&gt;&lt;p&gt;Here&apos;s what I came up with:&lt;/p&gt;&lt;div id=&quot;gsap-free-solution&quot;&gt;&lt;p&gt;
      &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/itsmattsoria/pen/azZxLBz&quot;&gt;
  GSAP-Free Animated Text Gradient Fill&lt;/a&gt; by Matt Soria (&lt;a href=&quot;https://codepen.io/itsmattsoria&quot;&gt;@itsmattsoria&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
      &lt;/p&gt;
      &lt;/div&gt;&lt;p&gt;I like the smoothness of the gradient spreading across the text over the abruptness of the letter-by-letter color change that happens when using SplitText.&lt;/p&gt;&lt;p&gt;And aesthetics aside, I love this approach because it&apos;s accessible without needing to do anything hacky (it&apos;s just plain markup), and it&apos;s JavaScript-free :sparkles:.&lt;/p&gt;&lt;p&gt;Here&apos;s what the markup looks like:&lt;/p&gt;&lt;div&gt;
  &lt;p&gt;Lorem, ipsum dolor sit amet consectetur adipisicing elit. Minima maiores dicta &lt;strong&gt;vero voluptatem architecto&lt;/strong&gt; quos quo saepe, est error quisquam. Exercitationem quas similique at perferendis voluptate repudiandae consectetur quis itaque!&lt;/p&gt;
  &lt;p&gt;Lorem ipsum dolor sit amet consectetur adipisicing elit. Excepturi officia eum corporis! Quaerat atque, consequuntur nulla, fuga deleniti obcaecati rem blanditiis reiciendis ipsum facilis dolorum voluptatum id tempore eligendi nemo!&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;That&apos;s it! It&apos;s just a container of semantic text markup with a class on it. &lt;/p&gt;&lt;p&gt;And here&apos;s what the CSS looks like:&lt;/p&gt;:root {
  --color-start: #BBAC9B;
  --color-end: #121110;
}

.animated-text {
  /* Set this as the end/legible color in case a visitor prefers reduced-motion */
  color: var(--color-end);
}

/* Wrap all of the animation styles in check for the visitor&apos;s motion preferences */
@media (prefers-reduced-motion: no-preference) {
  .animated-text {
    /* Scroll-driven Animation Properties */
    view-timeline-name: --animated-text;
    view-timeline-axis: block;
    animation: linear animatedTextBackground forwards;
    animation-timeline: --animated-text;
    animation-range: entry 45% cover 60%;
    /* The background gradient styles */
    color: transparent;
    background-clip: text;
    background-size: 100% 300%;
    background-position: 50% 100%;
    will-change: background-position;
    /* The gradient that creates the effect */
    background-image: linear-gradient(172deg, var(--color-end) 45%, var(--color-start) 55%);
  }
}

/* Animation that moves the background gradient into position */
@keyframes animatedTextBackground {
  from {
    background-position: 50% 90%;
  }
  to {
    background-position: 50% 0%;
  }
}&lt;p&gt;That&apos;s it! The markup is inherently accessible, and on top of that, we can take a &lt;a href=&quot;https://www.tatianamac.com/posts/prefers-reduced-motion&quot;&gt;&lt;i&gt;no-motion-first &lt;/i&gt;approach&lt;/a&gt;, ensuring the text is legible by default, and sprinkling on the animation if it&apos;s (assumed to be) acceptable to the visitor.&lt;/p&gt;&lt;h2&gt;No Hate for GSAP&lt;/h2&gt;&lt;p&gt;I just want to make clear that this post isn&apos;t meant as a dump on GSAP, or to convince you to not use GSAP—I think it&apos;s an incredibly powerful and useful tool, and I find a use for it on nearly every project I take on. It&apos;s just that for this particular design challenge, it seemed like a less-is-more approach was worth considering, and avoided the potential issues that Adrian outlined in his post.&lt;/p&gt;</content:encoded><category>Front-End</category><category>CSS</category><category>Dev</category></item><item><title>Daily Summer Commute</title><link>https://mattsoria.com/journal/daily-summer-commute</link><guid isPermaLink="true">https://mattsoria.com/journal/daily-summer-commute</guid><pubDate>Mon, 16 Jun 2025 07:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I live in an impossibly beautiful place—South Lake Tahoe, California. My daughter&apos;s daycare is on the other side of a state park that butts up against our back yard. So in the summer, I get to ride my mountain bike through the forest and glorious meadow to pick my daughter up, and some days it just feels unreal. I finally felt like I needed to capture a little taste of this commute, so well, here it is:&lt;/p&gt;&lt;div&gt;&lt;/div&gt;</content:encoded><category>Lifestyle</category><category>Cycling</category></item><item><title>TRMNL</title><link>https://mattsoria.com/journal/trmnl</link><guid isPermaLink="true">https://mattsoria.com/journal/trmnl</guid><pubDate>Fri, 16 May 2025 09:02:00 GMT</pubDate><content:encoded>&lt;img src=&quot;personal/journal/trmnl/trmnl-1.jpg&quot; alt=&quot;Photo of the terminal display in black and white.&quot; /&gt;&lt;p&gt;&lt;p&gt;Note: Since writing this, there is &lt;a href=&quot;https://trmnl.com/integrations/notion&quot;&gt;an official Notion Plugin&lt;/a&gt;, but it still may be desirable to create your own if you really want to customize it.&lt;/p&gt;&lt;/p&gt;&lt;p&gt;I picked up this thing recently: &lt;a href=&quot;https://usetrmnl.com/&quot;&gt;https://usetrmnl.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I dug that it was e-ink, having previously been an e-ink dumb phone user, and the documentation on building custom plugins made it seem super easy, so I was intrigued.&lt;/p&gt;&lt;p&gt;The design system is really pleasing, and the simplicity of it is really nice. I’m not a big fan of screens being all over the home. We have one of those frame tvs that appears pretty convincingly to be a framed picture when the tv isn’t in use, and other than our laptops floating away from our desks on occasion, we don’t have any screens that are just on and sitting around.&lt;/p&gt;&lt;p&gt;I liked the idea of a little display to show our shared calendar, some to-do lists, and maybe a few other fun little things, but a full color screen on constant rotation felt like the kind of noise we typically try to avoid in our house. So this seemed great!&lt;/p&gt;&lt;p&gt;And so far, it is! Much like my &lt;a href=&quot;https://www.thelightphone.com/&quot;&gt;Light Phone&lt;/a&gt;, it took a little getting used to its limitations, but after that it becomes pretty enjoyable. In the case of TRMNL it’s main limitation is that it isn’t interactive at all. It’s just a display. There aren’t even any physical buttons to push to rotate through screens—you set intervals for screens in a web-based portal.&lt;/p&gt;&lt;p&gt;The other great thing about it is how easy they made creating custom plugins. In TRMNL land a plugin is the whole thing. It’s what you choose to be displayed on the device. They have &lt;a href=&quot;https://trmnl.com/integrations#explore&quot;&gt;a ton to choose from&lt;/a&gt; in their marketplace, but making your own is pretty dang easy if you’re at least a little bit of a programmer.&lt;/p&gt;&lt;p&gt;I haven’t spent too much time exploring the possibilities, but I did make my own plugin to display a list of to-dos from a database in Notion, and it was super easy. After creating a new private plugin in the TRMNL portal all you really need to do is the following:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Go to your Notion profile and &lt;a href=&quot;https://developers.notion.com/guides/get-started/create-a-notion-integration#create-your-integration-in-notion&quot;&gt;create a new internal integration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Grab the API secret for that integration&lt;/li&gt;&lt;li&gt;Find the database ID of the Notion databse you want to read and display in your plugin. If you copy the link to your database in Notion it will be the long string in the URL after your username (ex: notion.so/username/&lt;code&gt;XXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;/code&gt;)&lt;/li&gt;&lt;li&gt;In your TRMNL plugin settings add the URL (with the database ID you just grabbed) &lt;code&gt;https://api.notion.com/v1/databases/XXXXXXXXXXXXXXXXXXXXXXXXXXX/query&lt;/code&gt; to the &quot;Polling URL(s)&quot; field&lt;/li&gt;&lt;li&gt;Add &lt;code&gt;authorization=Bearer YOUR_NOTION_INTEGRATION_API_SECRET&lt;/code&gt; to the &quot;Polling Headers&quot; field&lt;/li&gt;&lt;li&gt;Save, and go to &quot;Edit Markup&quot; to edit how you want to display your Notion data&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I know that last one is pretty vague, but TRMNL has a really nice editor (pictured below) that shows you exactly what variables you have access to from TRMNL, and if you&apos;ve connected to the Notion API correctly, the data it&apos;s getting back from Notion. They also have &lt;a href=&quot;https://trmnl.com/framework/docs&quot;&gt;extensive documentation&lt;/a&gt; on their very nice design system.&lt;/p&gt;&lt;img src=&quot;personal/journal/trmnl/screenshot_2026-02-14_at_02.09.38%402x_2026-02-14-100158_evhn.jpg&quot; alt=&quot;A screenshot of the markup editor in TRML&apos;s web portal.&quot; /&gt;&lt;p&gt;And that&apos;s pretty much it! Even if I don&apos;t get too much more creative than this, it&apos;s already been a really nice thing to have up on the fridge. If I do end up doing anything else interesting with it, I&apos;ll make another post about it and link to it here. &lt;/p&gt;</content:encoded><category>Gadgets</category><category>Technology</category><category>Lifestyle</category></item></channel></rss>