<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
  <author>
    <name>Rasmus Grouleff</name>
    <uri>https://mstdn.social/@nerdd.dk</uri>
    <email>rasmus@nerdd.dk</email>
  </author>
  <id>https://nerdd.dk/feed.atom.xml</id>
  <link href="https://nerdd.dk/feed.atom.xml"
    rel="self"
    type="application/atom+xml"/>
  <link href="https://nerdd.dk/"
    rel="alternate"
    type="text/html"
    hreflang="en"/>
  <subtitle>This is the tiny corner of the Internet belonging to Rasmus Grouleff, a freelance software developer.</subtitle>
  <title>Nerdd.dk</title>
  <updated>2026-03-23T11:11:13+00:00</updated>
  <entry>
    <author>
      <name>Rasmus Grouleff</name>
      <uri>https://mstdn.social/@nerdd.dk</uri>
      <email>rasmus@nerdd.dk</email>
    </author>
    <category term="ai"
      label="tag"/>
    <category term="rant"
      label="tag"/>
    <category term="politics"
      label="tag"/>
    <category term="open-source"
      label="tag"/>
    <category term="general-election"
      label="tag"/>
    <content type="html">&lt;p&gt;My hate for AI in the form that is being peddled by techno-fascist dude-bros right now burns with the intensity of a thousand suns, and when it is used for political purposes, I hate it even more. So I created &lt;a href=&quot;https://slopaganda.dk&quot;&gt;Slopaganda.dk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So when DR (the Danish public service broadcasting corporation) wrote an &lt;a href=&quot;https://www.dr.dk/nyheder/politik/folketingsvalg/partiernes-ai-videoer-vaekker-opsigt-valgkampen-praeges-af-slopaganda&quot;&gt;article about the use of AI-slop in the election campaigns&lt;/a&gt; leading up to the Danish general election on March 24, I &lt;a href=&quot;https://mstdn.social/@nerdd/116147541285282604&quot;&gt;posted on Mastodon&lt;/a&gt;, that it would be handy to have a website tracking which candidates was using AI-slop. I even posted, &lt;a href=&quot;https://mstdn.social/@nerdd/116147713703642240&quot;&gt;I was willing to buy a domain name for it and host it&lt;/a&gt;, if someone would build it and keep it updated as more slop was found.&lt;/p&gt;

&lt;p&gt;Someone did come forward and offered to build it, but when they disclosed that they had used an AI chatbot while building it, I immediately declined hosting that.&lt;/p&gt;

&lt;p&gt;I had however already secured the domain &lt;a href=&quot;https://slopaganda.dk&quot;&gt;Slopaganda.dk&lt;/a&gt;, so at 2:30 AM last Sunday, when I couldn’t sleep because of anger and frustration, I dragged my computer into bed and furiously hacked together the simplest possible site generator that could turn a CSV-file containing submitted tips into an HTML page. The first version was small enough to fit into &lt;a href=&quot;https://mstdn.social/@nerdd/116160733528465459&quot;&gt;a single Mastodon-post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The way it works is incredibly simple. On the page there is an iframe that shows a &lt;a href=&quot;https://tally.so&quot;&gt;tally.so&lt;/a&gt; form where anyone anonymously can submit tips about slopaganda. When there are new submissions, I verify that it actually is slop, download the submissions as a CSV-file, rebuild the page, and upload it to the server.&lt;/p&gt;

&lt;p&gt;Later that Sunday, the domain name was activated, and the site was live.&lt;/p&gt;

&lt;p&gt;My original plan had been to not associate myself too much with the site during the election, and then write about it here afterwards, but that plan pretty quickly went down the drain, because I started pushing it quite hard on Mastodon. You didn’t have to be too smart to put two and two together to figure out, I might be the creator.&lt;/p&gt;

&lt;p&gt;Since the first version, I have added some extra features like an RSS-feed and the ability to apply modifications to submissions, if a name is spelled incorrectly, something has been submitted twice etc. I was also asked if the source code was available online, and if I accepted pull requests. After a couple of minutes I had put &lt;a href=&quot;https://codeberg.org/rb_grouleff/slopaganda.dk&quot;&gt;the source up on Codeberg.org&lt;/a&gt; and released it in the public domain.&lt;/p&gt;

&lt;p&gt;Anyway I am pretty happy with it, and &lt;a href=&quot;https://tally.so&quot;&gt;tally.so&lt;/a&gt; seems like a great service for gathering tips.&lt;/p&gt;

&lt;p&gt;If you are a Dane or you know someone Danish, I would really like, if you would talk about it to as many as possible. Because this is a community effort. I cannot monitor every media and wander every street looking for slopaganda. And if you see something that might be slop, &lt;a href=&quot;https://slopaganda.dk&quot;&gt;&lt;em&gt;please&lt;/em&gt; submit a tip&lt;/a&gt;!&lt;/p&gt;</content>
    <id>repo://posts.collection/_posts/2026-03-07-a-general-election-in-the-age-of-ai-slop.md</id>
    <link href="https://nerdd.dk/2026/03/07/a-general-election-in-the-age-of-ai-slop/"
      rel="alternate"
      type="text/html"
      title="A general election in the age of &quot;AI&quot;-slop"/>
    <published>2026-03-07T15:46:21+00:00</published>
    <summary>AI slop is making its mark on the Danish general election, and I hate it. So I decided to track its usage and put it on display for everyone to see on slopaganda.dk.</summary>
    <title>A general election in the age of “AI”-slop</title>
    <updated>2026-03-07T15:46:21+00:00</updated>
    <dc:date>2026-03-07T15:46:21+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Rasmus Grouleff</name>
      <uri>https://mstdn.social/@nerdd.dk</uri>
      <email>rasmus@nerdd.dk</email>
    </author>
    <category term="programming"
      label="tag"/>
    <category term="css"
      label="tag"/>
    <category term="rant"
      label="tag"/>
    <category term="tailwindcss"
      label="tag"/>
    <content type="html">&lt;p&gt;For more than a year now, I have been using Tailwind CSS, both on my own website and for clients. So it is on a reasonably informed basis I can state, I don’t like it.&lt;/p&gt;

&lt;p&gt;Let me explain.&lt;/p&gt;

&lt;h2 id=&quot;endless-lists-of-classes&quot;&gt;Endless lists of classes&lt;/h2&gt;

&lt;p&gt;Styling pages with utility classes like Tailwind CSS intends leads to adding lots of classes to the &lt;code class=&quot;highlighter-rouge&quot;&gt;HTML&lt;/code&gt; elements, and what ends up happening is that it makes it incredibly hard to figure out the structure of a page, when the majority of the content in either my editor or in the browser dev tools consists of classes on elements. This is not made any better by the fact that many of the classes are the same.&lt;/p&gt;

&lt;h2 id=&quot;wheres-my-repl&quot;&gt;Where’s my REPL?&lt;/h2&gt;

&lt;p&gt;When I build pages, I usually use the DOM and style inspector in the browser in a way like I would use a REPL for backend-stuff. I select an element in the inspector, add a bit of CSS or an extra class, look at what it looks like in the browser, and then tweaking the styling, until I’m satisfied and actually implement it.&lt;/p&gt;

&lt;p&gt;Tailwind CSS breaks this in two ways. The first: the selectors Tailwind CSS generates are not always easy to understand, especially not in plugins (take a look at &lt;a href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot;&gt;tailwind-typography&lt;/a&gt;). The second: the generated CSS only includes styles for whatever classes I have used before, so if I haven’t used &lt;code class=&quot;highlighter-rouge&quot;&gt;gap-4&lt;/code&gt; before, I’m out of luck when playing around in the browser, unless I look up how Tailwind CSS generates the styles for &lt;code class=&quot;highlighter-rouge&quot;&gt;gap-4&lt;/code&gt; and paste them into the inspector.&lt;/p&gt;

&lt;h2 id=&quot;arbitrary-values&quot;&gt;Arbitrary values&lt;/h2&gt;

&lt;p&gt;When the default values Tailwind CSS provides are not enough, and you need to apply something specific to a single element, you of course can. But instead of using plain CSS, they seem to encourage using their bracket notation in classes. This ends up with something like &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;div class=&quot;top-[117px]&quot;&amp;gt;&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;div class=&quot;grid grid-cols-[1fr_500px_2fr]&quot;&amp;gt;&lt;/code&gt;. That is pretty much just a bad way of writing &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;div style=&quot;grid-template-columns: 1fr 500px 2fr&quot;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;cascade-no-more&quot;&gt;Cascade no more&lt;/h2&gt;

&lt;p&gt;Tailwind CSS’s design renders the cascading part of CSS almost useless. Tailwind CSS offers several ways of defining more general styles, but the documentation encourages using the utility classes as much as possible, meaning styles are only ever applied to the specific elements with the specific utility classes.&lt;/p&gt;

&lt;h2 id=&quot;overly-specific-styles&quot;&gt;Overly specific styles&lt;/h2&gt;

&lt;p&gt;The discouragement of using the cascade results in overly specific styles that are hard to adjust in a general way. This leads to having to repeatedly adding the same utility classes over and over again. The argument is to instead rely on the templating language used for rendering the HTML and build components in that.&lt;/p&gt;

&lt;h2 id=&quot;component-libraries---utility-or-semantic&quot;&gt;Component libraries - utility or semantic?&lt;/h2&gt;

&lt;p&gt;Component libraries try to solve some of the annoyances above. They minimize the need for utility classes and let you use more semantic classes, but this is the completely opposite of what Tailwind CSS is preaching. Why use Tailwind CSS at all in the first place, if you don’t want to use utility classes? And with component libraries, I always seem to end up with having to write something like &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;button class=&quot;btn&quot;&amp;gt;Click me&amp;lt;/button&amp;gt;&lt;/code&gt;, repeating the fact that it actually &lt;em&gt;is&lt;/em&gt; a button I am adding.&lt;/p&gt;

&lt;h2 id=&quot;extra-non-semantic-elements&quot;&gt;Extra non-semantic elements&lt;/h2&gt;

&lt;p&gt;It has happened several times that I have had to add extra child divs to get elements to behave or look in a certain way, after I have muddled around with all sorts of funky &lt;a href=&quot;#arbitrary-values&quot;&gt;arbitrary values&lt;/a&gt; or &lt;a href=&quot;#endless-lists-of-classes&quot;&gt;endless lists of classes&lt;/a&gt;. Sometimes I have even needed extra divs, arbitrary values, and endless lists of classes as a nice triple whammy.&lt;/p&gt;

&lt;h2 id=&quot;you-do-you&quot;&gt;You do you&lt;/h2&gt;

&lt;p&gt;This is not to dunk on Tailwind CSS at all (well, it kinda is, I guess…). Even though it isn’t for me, it is not something that would make me turn down clients, if that is what they want to use. But if I am asked, I will not recommend it, and I will not use it on my own things.&lt;/p&gt;</content>
    <id>repo://posts.collection/_posts/2026-01-25-i-don-t-like-tailwind-css.md</id>
    <link href="https://nerdd.dk/2026/01/25/i-don-t-like-tailwind-css/"
      rel="alternate"
      type="text/html"
      title="I don&#39;t like Tailwind CSS"/>
    <published>2026-01-25T14:53:25+00:00</published>
    <summary>After having used Tailwind CSS for a year, I have come to realize I really don&#39;t like it. Let me tell you why.</summary>
    <title>I don’t like Tailwind CSS</title>
    <updated>2026-01-25T14:53:25+00:00</updated>
    <dc:date>2026-01-25T14:53:25+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Rasmus Grouleff</name>
      <uri>https://mstdn.social/@nerdd.dk</uri>
      <email>rasmus@nerdd.dk</email>
    </author>
    <category term="swift"
      label="tag"/>
    <category term="macos"
      label="tag"/>
    <category term="business"
      label="tag"/>
    <category term="software"
      label="tag"/>
    <category term="time-tracker"
      label="tag"/>
    <content type="html">&lt;p&gt;When the app I have used for years for tracking working hours stopped working a while back, I started looking for a replacement. But I did not find any that satisfied my needs.&lt;/p&gt;

&lt;p&gt;So I ended up &lt;a href=&quot;https://github.com/rbgrouleff/Time-Tracker.app&quot;&gt;building my own&lt;/a&gt;. I have no idea if it could be useful for anybody else, but that certainly won’t stop me from offering it to the world.&lt;/p&gt;

&lt;h2 id=&quot;the-current-app-landscape&quot;&gt;The current app landscape&lt;/h2&gt;

&lt;p&gt;Pretty much all business related apps these days are basically just frontends for subscription services. They usually offer the most basic functionality for free, but if you need anything else, you have to subscribe to yet another service.&lt;/p&gt;

&lt;p&gt;This is fine, I guess. We all have to make a living in this late stage capitalistic hellscape of a society, we’re living in.&lt;/p&gt;

&lt;p&gt;The problem I have (besides having to pay for yet another subscription) is, that what happens to my data? Is it secure? What happens, if the company running the service shuts it down? Or if the company is acquired?&lt;/p&gt;

&lt;p&gt;Why can’t I just pay once for an app, I can run locally, that does not send my data somewhere else, that functions regardless of internet connectivity, and that doesn’t require a third party service to be running?&lt;/p&gt;

&lt;h2 id=&quot;the-app&quot;&gt;The app&lt;/h2&gt;

&lt;p&gt;The app I have built is nothing fancy, but it covers my needs, and it doesn’t come with a subscription or requires a third party service.&lt;/p&gt;

&lt;p&gt;It is a native macOS app, and it lets me have multiple clients with multiple projects, and it can track the time I spend on each of these projects and how much time I have invoiced on each project.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/scratching-my-own-itch/app-screenshot.png&quot; alt=&quot;Screenshot of the app, there is a client, &amp;quot;MegaCorp&amp;quot;, and it has one project, &amp;quot;The Big One&amp;quot;. The project has three timing sessions with one currently running.&quot; class=&quot;mx-auto&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;development&quot;&gt;Development&lt;/h2&gt;

&lt;p&gt;It is the first time I have built anything native for any Apple device, and it is the first time I have used Swift. So there is probably lots of room for improvement.&lt;/p&gt;

&lt;p&gt;A lot of the time I felt like the dog in the meme, where it is sat in front of a computer, but somehow I managed to cobble together something that seemingly works (on my computer™️).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/scratching-my-own-itch/i-have-no-idea-what-im-doing.jpg&quot; alt=&quot;A golden retriever wearing a red tie and with its tongue out is sitting in front of a laptop with its front paws on the keyboard. It looks slightly confused. In the top left corner there is a caption: &amp;quot;I have no idea what I&#39;m doing&amp;quot;&quot; class=&quot;mx-auto&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is all made by me without any use of AI, and the source code and a build of the app is available in the link above. The source is MIT licensed, so do with it, what you will – within the limits of the license.&lt;/p&gt;

&lt;p&gt;As the README states, I welcome any issues, suggestions and pull requests. Unless AI has been used to create them.&lt;/p&gt;

&lt;h2 id=&quot;say-hi&quot;&gt;Say hi!&lt;/h2&gt;

&lt;p&gt;I would love to hear from you, if Time Tracker is useful to you. You are also more than welcome to say hi, if you want to talk about the source. I’m sure there is a lot to talk about, since, as I mentioned, it is the first time I have played with Swift and macOS development.&lt;/p&gt;

&lt;p&gt;👋&lt;/p&gt;</content>
    <id>repo://posts.collection/_posts/2025-06-11-scratching-my-own-itch.md</id>
    <link href="https://nerdd.dk/2025/06/11/scratching-my-own-itch/"
      rel="alternate"
      type="text/html"
      title="Scratching my own itch"/>
    <published>2025-06-11T15:02:54+00:00</published>
    <summary>I have built a native macOS app for tracking my working hours, because I couldn&#39;t find any that didn&#39;t require a third party service or a subscription.</summary>
    <title>Scratching my own itch</title>
    <updated>2025-06-11T15:02:54+00:00</updated>
    <dc:date>2025-06-11T15:02:54+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Rasmus Grouleff</name>
      <uri>https://mstdn.social/@nerdd.dk</uri>
      <email>rasmus@nerdd.dk</email>
    </author>
    <category term="ruby"
      label="tag"/>
    <category term="bridgetown"
      label="tag"/>
    <content type="html">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;If I want to give myself a better chance to write and publish posts here, it has
to be as easy as possible.&lt;/p&gt;

&lt;p&gt;While Bridgetown does make it pretty easy, I think it could be even easier with
a couple of extra commands to manage posts.&lt;/p&gt;

&lt;p&gt;Let me show you, how I implemented commands for generating new posts and
updating both unpublished and published posts.&lt;/p&gt;

&lt;p&gt;TLDR: You can get &lt;a href=&quot;https://gist.github.com/rbgrouleff/67a159c489a15976248a7edb14a0c697&quot;&gt;the source code here&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;what-i-want-to-achieve&quot;&gt;What I want to achieve&lt;/h2&gt;

&lt;p&gt;When I want to write a new post I want to be able to run the command
&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown posts new &quot;Adding a couple of commands for managing posts in Bridgetown&quot;&lt;/code&gt;
and have that create a new markdown file with the right filename and correctly
formatted frontmatter.&lt;/p&gt;

&lt;p&gt;If I need to update a post, I want to be able to run the command
&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown posts touch 2025-01-16-adding-a-couple-of-commands-for-managing-posts-in-bridgetown&lt;/code&gt;
and let it either rename the file with the current date and update the
frontmatter if the post is unpublished or only update the frontmatter, if the
post is published.&lt;/p&gt;

&lt;h2 id=&quot;how-on-earth-do-i-add-commands-to-a-bridgetown-project&quot;&gt;How on earth do I add commands to a Bridgetown project?&lt;/h2&gt;

&lt;p&gt;In a Bridgetown project directory there is a &lt;code class=&quot;highlighter-rouge&quot;&gt;Rakefile&lt;/code&gt; where you can add new
tasks, and they can be invoked using &lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown&lt;/code&gt;. This is the easiest way
to add extra commands. It is just not as nice to work with commandline options
and flags in Rake.&lt;/p&gt;

&lt;p&gt;Fortunately Bridgetown uses &lt;a href=&quot;http://whatisthor.com&quot;&gt;Thor&lt;/a&gt; for its own commands. Thor comes with
a lot of functionality for handling options and flags, and it can generate help
texts as well.&lt;/p&gt;

&lt;p&gt;The only drawback with Thor is you have to add a &lt;code class=&quot;highlighter-rouge&quot;&gt;config/boot.rb&lt;/code&gt; in the project
directory where you set up Bundler and require the file containing the code for
your commands:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# config/boot.rb&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$LOAD_PATH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__dir__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;../lib&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# lib contains the new command&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Bridgetown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;local/commands/posts&#39;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Requiring the new command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is &lt;a href=&quot;https://www.bridgetownrb.com/docs/configuration/initializers#low-level-boot-customization&quot;&gt;documented here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;implementing-posts-new&quot;&gt;Implementing &lt;code class=&quot;highlighter-rouge&quot;&gt;posts new&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The next step is to actually start implementing the commands.&lt;/p&gt;

&lt;p&gt;We’ll add the file &lt;code class=&quot;highlighter-rouge&quot;&gt;lib/local/commands/post.rb&lt;/code&gt; which will contain the code for
the commands with the bare minimum to make it possible to invoke
&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown posts&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;require_all&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;bridgetown-core/commands/concerns&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Local&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Commands&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Thor&lt;/span&gt;
      &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Thor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Actions&lt;/span&gt;
      &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Bridgetown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ConfigurationOverridable&lt;/span&gt;

      &lt;span class=&quot;no&quot;&gt;Bridgetown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Commands&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Registrations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;posts &amp;lt;command&amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Manage posts&#39;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;subcommand&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;posts&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Posts&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source_root&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With that it is now possible to call &lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown posts help&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;~/nerdd.dk &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bin/bridgetown posts &lt;span class=&quot;nb&quot;&gt;help
&lt;/span&gt;Commands:
  bridgetown posts &lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;COMMAND]  &lt;span class=&quot;c&quot;&gt;# Describe subcommands or one specific subcommand&lt;/span&gt;

Options:
  &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;, &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--environment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ENVIRONMENT]  &lt;span class=&quot;c&quot;&gt;# The environment used for this command (aka development, test, production, etc.)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s add the code for generating a basic new post.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;pathname&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Local&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Commands&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Thor&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;new TITLE&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Add a new post with current date and the given title&#39;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;%Y-%m-%d&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Bridgetown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.md&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;templates/new_post.md.tt&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                 &lt;span class=&quot;ss&quot;&gt;context: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

      &lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Bridgetown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;_posts&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It generates a new file in the &lt;code class=&quot;highlighter-rouge&quot;&gt;src/_posts&lt;/code&gt; directory with the slugified title
and the current time.&lt;/p&gt;

&lt;p&gt;It uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;lib/local/commands/templates/new_post.md.tt&lt;/code&gt; template.&lt;/p&gt;

&lt;div class=&quot;language-erb highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;%# lib/local/commands/templates/new_post.md.tt %&amp;gt;&lt;/span&gt;
---
title: &quot;&lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;&quot;
date: Thu, 16 Jan 2025 17:03:01 +0100last_modified_at: Fri, 17 Jan 2025 12:46:55 +0100
last_modified_at: Fri, 17 Jan 2025 12:52:58 +0100
published: false
---
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s continue and add some optional options for setting an author and a list of
tags.&lt;/p&gt;

&lt;p&gt;In the command we need to add a couple of &lt;code class=&quot;highlighter-rouge&quot;&gt;method_option&lt;/code&gt; lines and pass the
input for author and tags along in the context to the template.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;new TITLE [options]&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Add a new post with current date and the given title&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;method_option&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;type: :string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;aliases: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;-a&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;desc: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;author identifier&#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;method_option&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;type: :array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;desc: &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;list of tags&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;author&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;&#39;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;tags&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;title: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And in the template we’ll insert the author and tags if they are not empty.&lt;/p&gt;

&lt;div class=&quot;language-erb highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;%# lib/local/commands/templates/new_post.md.tt %&amp;gt;&lt;/span&gt;
---
# ...
published: false
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;-%&amp;gt;&lt;/span&gt;
author: &lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;author&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;-%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;empty?&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;-%&amp;gt;&lt;/span&gt;
tags: &lt;span class=&quot;cp&quot;&gt;&amp;lt;%=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;%-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;-%&amp;gt;&lt;/span&gt;
---
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that is basically it. A new unpublished post can be created with
&lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bt posts new &quot;My amazing post&quot; --author=rasmus --tags=this is amazing&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;touching-posts&quot;&gt;Touching posts&lt;/h2&gt;

&lt;p&gt;The command for touching posts should look like &lt;code class=&quot;highlighter-rouge&quot;&gt;bin/bridgetown posts touch FILENAME&lt;/code&gt;,
and it should be able to find the correct post with only a partial filename. If
the partial filename matches multiple posts, it should just list the found
filenames instead of touching everyone of them, and if none matches the given
filename, it should also print a helpful message.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;touch FILENAME&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;Updates filename and post date for drafts, sets or updates last_modified_at on published posts&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;touch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;find_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# TODO: Implement find_posts&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;touch_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# TODO: Implement touch_post&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Found multiple posts. Name should be unambiguous. Please try again with one of these:&#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sort_by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:ctime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.md&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Could not find any posts with a file name starting with &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s add the &lt;code class=&quot;highlighter-rouge&quot;&gt;find_posts&lt;/code&gt; method next. It simply finds all the files in the
&lt;code class=&quot;highlighter-rouge&quot;&gt;src/_posts&lt;/code&gt; directory where the filename matches the string containing the
(possible) partial filename.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;find_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;select&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;extname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;.md&#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Regexp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Touching a post is slightly more complicated than creating a new one. When a post
is unpublished, it needs to alter the date in filename to the current date and
update the &lt;code class=&quot;highlighter-rouge&quot;&gt;date&lt;/code&gt; field in the frontmatter. For published posts, it must leave
the filename and &lt;code class=&quot;highlighter-rouge&quot;&gt;date&lt;/code&gt; alone and instead set or update the &lt;code class=&quot;highlighter-rouge&quot;&gt;last_modified_at&lt;/code&gt;
field in the frontmatter.&lt;/p&gt;

&lt;p&gt;So we’ll split it in two separate steps.&lt;/p&gt;

&lt;h2 id=&quot;touching-an-unpublished-post&quot;&gt;Touching an unpublished post&lt;/h2&gt;

&lt;p&gt;First we’ll implement touching an unpublished post.&lt;/p&gt;

&lt;p&gt;Since this needs to rename the file, we have to be careful to not overwrite any
existing posts. If a post with the new filename already exists, we will back out
and not do anything. But otherwise the easiest and safest way to do this is to
first make a copy with the new filename, then update the frontmatter and finally
removing the old file. If anything goes wrong after copying the file, the new
file is deleted, and a message is printed to the console.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;DATETIME_FORMAT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;%a, %d %b %Y %T %z&#39;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;touch_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;now&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;new_filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^\d{4}-\d{2}-\d{2}/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;%Y-%m-%d&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; already exists, aborting.&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;begin&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;copy_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;gsub_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^date: .*$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;date: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DATETIME_FORMAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;remove_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;StandardError&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;remove_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist?&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;say&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Could not touch the post named &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;.md&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, aborting.&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;touching-a-published-post&quot;&gt;Touching a published post&lt;/h2&gt;

&lt;p&gt;Renaming the file and updating &lt;code class=&quot;highlighter-rouge&quot;&gt;date&lt;/code&gt; in the frontmatter is fine for unpublished
posts, but for posts that are already published, it is not ideal, since renaming
the file changes the URL to the post on the built site and makes it appear to
have been published at the new date.&lt;/p&gt;

&lt;p&gt;Instead we only want to set or update &lt;code class=&quot;highlighter-rouge&quot;&gt;last_modified_at&lt;/code&gt; in the frontmatter, if
the post is published.&lt;/p&gt;

&lt;p&gt;We’ll extract everything in &lt;code class=&quot;highlighter-rouge&quot;&gt;touch_post&lt;/code&gt; except the first line to a new method
called &lt;code class=&quot;highlighter-rouge&quot;&gt;update_unpublished_post&lt;/code&gt;, and add a &lt;code class=&quot;highlighter-rouge&quot;&gt;published?&lt;/code&gt; method that tells if a
post is published, and a &lt;code class=&quot;highlighter-rouge&quot;&gt;set_or_update_last_modified_at&lt;/code&gt; method for updating
the frontmatter.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;set_or_update_last_modified_at&lt;/code&gt; will have to figure out if the post has been
modified before, which is done by checking if &lt;code class=&quot;highlighter-rouge&quot;&gt;last_modified_at&lt;/code&gt; already is set.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# lib/local/commands/posts.rb&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;touch_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;POSTS_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;published?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;set_or_update_last_modified_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;update_unpublished_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;set_or_update_last_modified_at&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modified?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gsub_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^last_modified_at: .*$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;last_modified_at: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DATETIME_FORMAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inject_into_file&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;last_modified_at: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strftime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DATETIME_FORMAT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;after: &lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^date: .*$/&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;update_unpublished_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;modified?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;any?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^last_modified_at: .*$/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;published?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;each_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;any?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^published: true$/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;These extra commands are a bit rough around the edges, especially in the way the
frontmatter is updated.&lt;/p&gt;

&lt;p&gt;If there are lines in the body of a post containing only &lt;code class=&quot;highlighter-rouge&quot;&gt;published: true&lt;/code&gt; or
&lt;code class=&quot;highlighter-rouge&quot;&gt;last_modified_at: &amp;lt;date&amp;gt;&lt;/code&gt;, they will happily be accepted as part of the
frontmatter.&lt;/p&gt;

&lt;p&gt;The commands also assume the posts are all written in Markdown, and the
frontmatter is in YAML.&lt;/p&gt;

&lt;p&gt;I have also not bothered with writing any tests.&lt;/p&gt;

&lt;p&gt;If you have made it this far, and you are interested in the code its entirety,
it is available as a &lt;a href=&quot;https://gist.github.com/rbgrouleff/67a159c489a15976248a7edb14a0c697&quot;&gt;gist on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to do with it, what you will.&lt;/p&gt;

&lt;p&gt;If you make a gem out of it, please &lt;a href=&quot;https://mstdn.social/@nerdd&quot;&gt;ping me&lt;/a&gt;, I
would love to install it. You are also more than welcome to let me know, if I
have made some stupid mistakes, or if you have improvements.&lt;/p&gt;
</content>
    <id>repo://posts.collection/_posts/2025-01-16-adding-a-couple-of-commands-for-managing-posts-in-bridgetown.md</id>
    <link href="https://nerdd.dk/2025/01/16/adding-a-couple-of-commands-for-managing-posts-in-bridgetown/"
      rel="alternate"
      type="text/html"
      title="Adding a couple of commands for managing posts in Bridgetown"/>
    <published>2025-01-16T16:03:01+00:00</published>
    <summary>A walkthrough of how I added a couple of commands for managing posts to my Bridgetown project</summary>
    <title>Adding a couple of commands for managing posts in Bridgetown</title>
    <updated>2025-01-17T11:52:58+00:00</updated>
    <dc:date>2025-01-17T11:52:58+00:00</dc:date>
  </entry>
  <entry>
    <author>
      <name>Rasmus Grouleff</name>
      <uri>https://mstdn.social/@nerdd.dk</uri>
      <email>rasmus@nerdd.dk</email>
    </author>
    <category term="meta"
      label="tag"/>
    <category term="random"
      label="tag"/>
    <category term="personal"
      label="tag"/>
    <content type="html">&lt;p&gt;&lt;em&gt;Tap tap tap&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hello, is this thing on?&lt;/p&gt;

&lt;h2 id=&quot;it-has-actually-happened&quot;&gt;It has actually happened&lt;/h2&gt;

&lt;p&gt;For years I have wanted to give my little corner of the Internet a fresh lick of paint and perhaps make it a place, where I easily can write about what I find interesting.&lt;/p&gt;

&lt;p&gt;I have started multiple times on this home improvement project, but I never seemed to be able to finish it – something about perfect being the enemy of good. Finally, however, I seem to have succeeded in the endeavour.&lt;/p&gt;

&lt;h2 id=&quot;a-bit-of-history&quot;&gt;A bit of history&lt;/h2&gt;

&lt;p&gt;Twenty years ago this website started out as a self-hosted WordPress blog, where I blogged about hobbies and personal stuff. It was back in the gloriuos days with &lt;a href=&quot;https://en.wikipedia.org/wiki/Digg&quot;&gt;Digg&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/FeedBurner&quot;&gt;Feedburner&lt;/a&gt;, blogrolls, and slapping AdSense ad panels on your blog so you once in a while could receive a small amount of sweet, sweet Google-money on a cheque.&lt;/p&gt;

&lt;p&gt;At some point I lost interest in blogging though, and Nerdd.dk ended up being neglected. I moved to different hosts a couple of times, and the database from back then is long gone.&lt;/p&gt;

&lt;p&gt;That was when I changed it to a small static site that could function as a sort of business card online. And then I neglected it again.&lt;/p&gt;

&lt;p&gt;Perhaps this time it will be different. I have at least made it easier for myself to publish stuff.&lt;/p&gt;

&lt;h2 id=&quot;whats-changed&quot;&gt;What’s changed?&lt;/h2&gt;

&lt;p&gt;What I have done to set myself up for success (or whatever this might be called) is to use &lt;a href=&quot;https://bridgetownrb.com&quot;&gt;Bridgetown&lt;/a&gt; for HTML generation, and use &lt;a href=&quot;https://tailwindcss.com&quot;&gt;Tailwindcss&lt;/a&gt; for the styling.&lt;/p&gt;

&lt;p&gt;Bridgetown is a fairly new site generator – which is capable of a heck of a lot more than what I’m using it for. I have however customised it a bit, but I’ll keep that as a topic for a separate post.&lt;/p&gt;

&lt;p&gt;For styling I went with Tailwindcss to see what all the fuss is about, and while the long lists of classes in the HTML still irks me out, I have to admit it made it quite easy to make this site not look complete pants. It is even responsive – and supports dark mode!&lt;/p&gt;

&lt;h2 id=&quot;so-are-you-back-to-blogging-again&quot;&gt;So.. are you back to blogging again?&lt;/h2&gt;

&lt;p&gt;No, not really.&lt;/p&gt;

&lt;p&gt;I am not planning on writing regularly, and I really can’t be bothered with comments. There is an Atom feed of the posts, however.&lt;/p&gt;

&lt;h2 id=&quot;what-to-expect&quot;&gt;What to expect&lt;/h2&gt;

&lt;p&gt;First of all expect irregular updates.&lt;/p&gt;

&lt;p&gt;When there are new updates, it will probably be about different aspects of software development, both technical and non-technical.&lt;/p&gt;

&lt;h2 id=&quot;thats-it-for-now-i-guess&quot;&gt;That’s it for now, I guess&lt;/h2&gt;

&lt;p&gt;Well, if you have actually made it this far, I want to thank you for reading along. I don’t know if I would have had the stamina to keep reading.&lt;/p&gt;

&lt;p&gt;Even though I wrote I couldn’t be bothered with comments, you are however more than welcome to send me an email, if you have any thoughts on what I write, suggestions for topics to write about, or improvements I can make here.&lt;/p&gt;

&lt;p&gt;Thanks, bye!&lt;/p&gt;
</content>
    <id>repo://posts.collection/_posts/2024-12-03-is-this-thing-on.md</id>
    <link href="https://nerdd.dk/2024/12/03/is-this-thing-on/"
      rel="alternate"
      type="text/html"
      title="Is this thing on?"/>
    <published>2024-12-03T10:08:13+00:00</published>
    <summary>A welcome to my revamped corner of the Internet</summary>
    <title>Is this thing on?</title>
    <updated>2024-12-03T10:08:13+00:00</updated>
    <dc:date>2024-12-03T10:08:13+00:00</dc:date>
  </entry>
  <dc:language>en</dc:language>
  <dc:date>2026-03-23T11:11:13+00:00</dc:date>
</feed>